在ASP.NET Web API中处理ModelState验证

Cal*_*ass 100 c# asp.net-web-api

我想知道如何使用ASP.NET Web API实现模型验证.我的模型是这样的:

public class Enquiry
{
    [Key]
    public int EnquiryId { get; set; }
    [Required]
    public DateTime EnquiryDate { get; set; }
    [Required]
    public string CustomerAccountNumber { get; set; }
    [Required]
    public string ContactName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我在我的API控制器中有一个Post动作:

public void Post(Enquiry enquiry)
{
    enquiry.EnquiryDate = DateTime.Now;
    context.DaybookEnquiries.Add(enquiry);
    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

如何添加if(ModelState.IsValid)然后处理错误消息以传递给用户?

cuo*_*gle 177

为了分离关注点,我建议您使用动作过滤器进行模型验证,因此您不需要太在意如何在api控制器中进行验证:

using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace System.Web.Http.Filters
{
    public class ValidationActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var modelState = actionContext.ModelState;

            if (!modelState.IsValid)
                actionContext.Response = actionContext.Request
                     .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这需要的名称空间是`System.Net.Http`,`System.Net``System.Web.Http.Controllers`和`System.Web.Http.Filters`. (26认同)
  • 官方的ASP.NET Web Api页面上也有类似的实现:http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web- API (11认同)
  • 值得指出的是,返回的错误响应由 [IncludeErrorDetailPolicy](https://msdn.microsoft.com/en-us/library/system.web.http.httpconfiguration.includeerrordetailpolicy(v=vs.118) 控制。 ASPX)。默认情况下,对远程请求的响应仅包含通用的“发生错误”消息,但将其设置为“IncludeErrorDetailPolicy.Always”将包含详细信息(存在向用户公开详细信息的风险) (3认同)
  • 即使不将 [ValidationActionFilter] 放在 web api 上方,它仍然会调用代码并给我错误的请求。 (2认同)

And*_*rpi 28

像这样,例如:

public HttpResponseMessage Post(Person person)
{
    if (ModelState.IsValid)
    {
        PersonDB.Add(person);
        return Request.CreateResponse(HttpStatusCode.Created, person);
    }
    else
    {
        // the code below should probably be refactored into a GetModelErrors
        // method on your BaseApiController or something like that

        var errors = new List<string>();
        foreach (var state in ModelState)
        {
            foreach (var error in state.Value.Errors)
            {
                errors.Add(error.ErrorMessage);
            }
        }
        return Request.CreateResponse(HttpStatusCode.Forbidden, errors);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将返回这样的响应(假设JSON,但XML的基本原理相同):

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
(some headers removed here)

["A value is required.","The field First is required.","Some custom errorm essage."]
Run Code Online (Sandbox Code Playgroud)

您当然可以按照自己喜欢的方式构建错误对象/列表,例如添加字段名称,字段ID等.

即使它是一种"单向"Ajax调用,就像新实体的POST一样,你仍然应该向调用者返回一些内容 - 这表明请求是否成功.想象一下,您的用户将通过AJAX POST请求添加一些自己的信息.如果他们试图输入的信息无效,他们将如何知道他们的保存行动是否成功?

执行此操作的最佳方法是使用Good Old HTTP Status Code200 OK.这样,您的JavaScript可以使用正确的回调(错误,成功等)正确处理失败.

这是一个关于此方法的更高级版本的精彩教程,使用ActionFilter和jQuery:http://asp.net/web-api/videos/getting-started/custom-validation


Are*_*aas 26

也许不是你想要的东西,但也许有人知道:

如果您使用.net Web Api 2,您可以执行以下操作:

if (!ModelState.IsValid)
     return BadRequest(ModelState);
Run Code Online (Sandbox Code Playgroud)

根据模型错误,您会得到以下结果:

{
   Message: "The request is invalid."
   ModelState: {
       model.PropertyA: [
            "The PropertyA field is required."
       ],
       model.PropertyB: [
             "The PropertyB field is required."
       ]
   }
}
Run Code Online (Sandbox Code Playgroud)


san*_*ula 7

或者,如果您正在为您的应用程序寻找简单的错误集合..这是我的实现:

public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid) 
        {

            var errors = new List<string>();
            foreach (var state in modelState)
            {
                foreach (var error in state.Value.Errors)
                {
                    errors.Add(error.ErrorMessage);
                }
            }

            var response = new { errors = errors };

            actionContext.Response = actionContext.Request
                .CreateResponse(HttpStatusCode.BadRequest, response, JsonMediaTypeFormatter.DefaultMediaType);
        }
    }
Run Code Online (Sandbox Code Playgroud)

错误消息响应将如下所示:

{
  "errors": [
    "Please enter a valid phone number (7+ more digits)",
    "Please enter a valid e-mail address"
  ]
}
Run Code Online (Sandbox Code Playgroud)


May*_*aur 6

在 startup.cs 文件中添加以下代码

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = (context) =>
                {
                    var errors = context.ModelState.Values.SelectMany(x => x.Errors.Select(p => new ErrorModel()
                   {
                       ErrorCode = ((int)HttpStatusCode.BadRequest).ToString(CultureInfo.CurrentCulture),
                        ErrorMessage = p.ErrorMessage,
                        ServerErrorMessage = string.Empty
                    })).ToList();
                    var result = new BaseResponse
                    {
                        Error = errors,
                        ResponseCode = (int)HttpStatusCode.BadRequest,
                        ResponseMessage = ResponseMessageConstants.VALIDATIONFAIL,

                    };
                    return new BadRequestObjectResult(result);
                };
           });
Run Code Online (Sandbox Code Playgroud)