C# 解析Angular 10中的400响应以获取ModelState问题

C# 解析Angular 10中的400响应以获取ModelState问题,c#,angular,asp.net-web-api,C#,Angular,Asp.net Web Api,我有一个在viewmodel中执行的非常简单的控制器操作。我只想在代码中检查模型,如果它无效,则将modelstate作为BadRequest转储回 [HttpPost] [Route("SaveBraceStep1")] [SwaggerOperation(OperationId = "SaveBraceStep1")] [ProducesResponseType(200, Type = typeof(VM.ProjectBraceDataModelSt

我有一个在viewmodel中执行的非常简单的控制器操作。我只想在代码中检查模型,如果它无效,则将modelstate作为BadRequest转储回

[HttpPost]
[Route("SaveBraceStep1")]
[SwaggerOperation(OperationId = "SaveBraceStep1")]
[ProducesResponseType(200, Type = typeof(VM.ProjectBraceDataModelStep1))]
public async Task<IActionResult> SaveBraceStep1(VM.ProjectBraceDataModelStep1 model)
{
  if (!ModelState.IsValid)
  {
    return new BadRequestObjectResult(ModelState.Errors());
  }
  var project = await bracingDataService.SaveBraceStep1(model);
  return Ok(project);
}
[HttpPost]
[路由(“SaveBraceStep1”)]
[SwaggerOperation(OperationId=“SaveBraceStep1”)]
[ProductsResponseType(200,Type=typeof(VM.ProjectBraceDataModelStep1))]
公共异步任务SaveBraceStep1(VM.ProjectBraceDataModelStep1模型)
{
如果(!ModelState.IsValid)
{
返回新的BadRequestObjectResult(ModelState.Errors());
}
var project=await bracingDataService.SaveBraceStep1(模型);
返回Ok(项目);
}
当结果返回到Chrome时,正如预期的那样

我有一个http拦截器,如下所示:

import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
export class HttpErrorInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request)
            .pipe(catchError(err => {
                // how can I read the results of the ModelState here
                console.log(err);
                return throwError('An error has been thrown');
            }));
    }
}
从'@angular/common/http'导入{HttpEvent,HttpInterceptor,HttpHandler,HttpRequest,};
从“rxjs”导入{observatable,throwerr};
从“rxjs/operators”导入{catchError};
导出类HttpErrorInterceptor实现HttpInterceptor{
拦截(请求:HttpRequest)

我已经搜索了大量的谷歌搜索和用户blob,但我似乎找不到一个公认的简洁的方法来做到这一点

我真的被吓坏了,因为我希望到现在为止这已经是相当标准化的了

有什么想法吗?提前谢谢你。编码快乐


~Mike

好的,我在他的帮助下解决了这个问题

基本上,您必须注册一个新的操作类型,然后将其插入管道

public Task ExecuteResultAsync(ActionContext context)
    {
      var modelStateEntries = context.ModelState.Where(e => e.Value.Errors.Count > 0).ToArray();
      var errors = new List<ValidationError>();

      var details = "See ValidationErrors for details";

      if (modelStateEntries.Any())
      {
        if (modelStateEntries.Length == 1 && modelStateEntries[0].Value.Errors.Count == 1 && modelStateEntries[0].Key == string.Empty)
        {
          details = modelStateEntries[0].Value.Errors[0].ErrorMessage;
        }
        else
        {
          foreach (var modelStateEntry in modelStateEntries)
          {
            foreach (var modelStateError in modelStateEntry.Value.Errors)
            {
              var error = new ValidationError
              {
                Name = modelStateEntry.Key,
                Description = modelStateError.ErrorMessage
              };

              errors.Add(error);
            }
          }
        }
      }

      var problemDetails = new ValidationProblemDetails
      {
        Status = 400,
        Title = "Request Validation Error",
        Instance = $"urn:myorganization:badrequest:{Guid.NewGuid()}",
        Detail = details,
        ValidationErrors = errors
      };
      context.HttpContext.Response.StatusCode = 400;
      var json = JsonConvert.SerializeObject(problemDetails);
      context.HttpContext.Response.WriteAsync(json);
      return Task.CompletedTask;
    }
  }
  public class ValidationProblemDetails : ProblemDetails
  {
    public ICollection<ValidationError> ValidationErrors { get; set; }
  }
  public class ValidationError
  {
    public string Name { get; set; }
    public string Description { get; set; }
  }
public Task executesSultAsync(ActionContext上下文)
{
var modelStateEntries=context.ModelState.Where(e=>e.Value.Errors.Count>0).ToArray();
var errors=新列表();
var details=“有关详细信息,请参阅ValidationErrors”;
if(modelStateEntries.Any())
{
if(modelStateEntries.Length==1&&modelStateEntries[0]。Value.Errors.Count==1&&modelStateEntries[0]。Key==string.Empty)
{
详细信息=modelStateEntries[0]。值。错误[0]。错误消息;
}
其他的
{
foreach(modelStateEntries中的var modelStateEntry)
{
foreach(modelStateEntry.Value.Errors中的var modelStateError)
{
var error=新的ValidationError
{
Name=modelStateEntry.Key,
Description=modelStateError.ErrorMessage
};
错误。添加(错误);
}
}
}
}
var problemDetails=new ValidationProblemDetails
{
状态=400,
Title=“请求验证错误”,
实例=$“urn:myorganization:badrequest:{Guid.NewGuid()}”,
细节=细节,
ValidationErrors=错误
};
context.HttpContext.Response.StatusCode=400;
var json=JsonConvert.SerializeObject(problemDetails);
context.HttpContext.Response.WriteAsync(json);
返回Task.CompletedTask;
}
}
公共类验证ProblemDetails:ProblemDetails
{
公共ICollection验证错误{get;set;}
}
公共类验证错误
{
公共字符串名称{get;set;}
公共字符串说明{get;set;}
}
然后在startup.cs中注册它

services.Configure<ApiBehaviorOptions>(options =>
      {
        options.InvalidModelStateResponseFactory = ctx => new ValidationProblemDetailsResult();
      });
services.Configure(选项=>
{
options.InvalidModelStateResponseFactory=ctx=>new ValidationProblemDetailsResult();
});
然后连接到拦截器上

@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {

    constructor(private uiService: Services.UIService, private injector: Injector) {
    }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request)
            .pipe(catchError((err: HttpErrorResponse) => {
                const reader = new FileReader();
                reader.addEventListener('loadend', (e) => {
                    const result = this.buildResponse(JSON.parse(e.srcElement['result']));
                    this.uiService.HttpError(result);
                });
                reader.readAsText(err.error);
                return throwError(err);
            }));
    }

    buildResponse(e: any): ApplicationHttpErrorResponse {
        const model: ApplicationHttpErrorResponse = { ValidationErrors: [] };
        if (e.ValidationErrors && e.ValidationErrors.length > 0) {
            for (let i = 0; i < e.ValidationErrors.length; i++) {
                const validator: ApplicationHttpError = {
                    Name: e.ValidationErrors[i].Name,
                    Description: e.ValidationErrors[i].Description
                };
                model.ValidationErrors.push(validator);
            }
        }
        return model;
    }
}
@Injectable()
导出类HttpErrorInterceptor实现HttpInterceptor{
构造函数(专用uiService:Services.uiService,专用注入器:注入器){
}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回next.handle(请求)
.pipe(catchError((err:HttpErrorResponse)=>{
const reader=new FileReader();
reader.addEventListener('loadend',(e)=>{
const result=this.buildResponse(JSON.parse(e.srcement['result']);
this.uiService.HttpError(结果);
});
reader.readAsText(err.error);
回程抛掷器(err);
}));
}
buildResponse(e:any):ApplicationHttpErrorResponse{
常量模型:ApplicationHttpErrorResponse={ValidationErrors:[]};
如果(e.ValidationErrors&&e.ValidationErrors.length>0){
for(设i=0;i

然后可以在UI服务中使用它向最终用户显示问题。

好的,所以我在

基本上,您必须注册一个新的操作类型,然后将其插入管道

public Task ExecuteResultAsync(ActionContext context)
    {
      var modelStateEntries = context.ModelState.Where(e => e.Value.Errors.Count > 0).ToArray();
      var errors = new List<ValidationError>();

      var details = "See ValidationErrors for details";

      if (modelStateEntries.Any())
      {
        if (modelStateEntries.Length == 1 && modelStateEntries[0].Value.Errors.Count == 1 && modelStateEntries[0].Key == string.Empty)
        {
          details = modelStateEntries[0].Value.Errors[0].ErrorMessage;
        }
        else
        {
          foreach (var modelStateEntry in modelStateEntries)
          {
            foreach (var modelStateError in modelStateEntry.Value.Errors)
            {
              var error = new ValidationError
              {
                Name = modelStateEntry.Key,
                Description = modelStateError.ErrorMessage
              };

              errors.Add(error);
            }
          }
        }
      }

      var problemDetails = new ValidationProblemDetails
      {
        Status = 400,
        Title = "Request Validation Error",
        Instance = $"urn:myorganization:badrequest:{Guid.NewGuid()}",
        Detail = details,
        ValidationErrors = errors
      };
      context.HttpContext.Response.StatusCode = 400;
      var json = JsonConvert.SerializeObject(problemDetails);
      context.HttpContext.Response.WriteAsync(json);
      return Task.CompletedTask;
    }
  }
  public class ValidationProblemDetails : ProblemDetails
  {
    public ICollection<ValidationError> ValidationErrors { get; set; }
  }
  public class ValidationError
  {
    public string Name { get; set; }
    public string Description { get; set; }
  }
public Task executesSultAsync(ActionContext上下文)
{
var modelStateEntries=context.ModelState.Where(e=>e.Value.Errors.Count>0).ToArray();
var errors=新列表();
var details=“有关详细信息,请参阅ValidationErrors”;
if(modelStateEntries.Any())
{
if(modelStateEntries.Length==1&&modelStateEntries[0]。Value.Errors.Count==1&&modelStateEntries[0]。Key==string.Empty)
{
详细信息=modelStateEntries[0]。值。错误[0]。错误消息;
}
其他的
{
foreach(modelStateEntries中的var modelStateEntry)
{
foreach(modelStateEntry.Value.Errors中的var modelStateError)
{
var error=新的ValidationError
{
Name=modelStateEntry.Key,
Description=modelStateError.ErrorMessage
};
错误。添加(错误);
}
}
}
}
var problemDetails=new ValidationProblemDetails
{