ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – ASP.Net核心验证问题状态 – 绑定验证不返回问题详细信息

2019-06-22 08:54:41  阅读:498  来源: 互联网

标签:c asp-net-core asp-net-core-2-1


同样的问题发布在这里:https://github.com/aspnet/Mvc/issues/8564

我有一个问题,当执行命中控制器时,我的代码显式返回ValidationProblemDetails响应.

但是,当绑定验证阻止执行到达控制器时,我得到以下JSON响应(标准模型状态验证对象).

{
  "Email": [
    "Invalid email address"
  ]
}

为什么不在响应中返回验证问题详细信息?

我正在使用Microsoft.AspNetCore.App 2.1.4包.

请求模型

public class RegistrationRequest
{
    [Description("Given Name")]
    [MaxLength(100)]
    [Required(ErrorMessage = "Given Name is required")]
    public string GivenName { get; set; }

    [MaxLength(100)]
    [Required(ErrorMessage = "Surname is required")]
    public string Surname { get; set; }

    [MaxLength(255)]
    [Required(ErrorMessage = "Email is required")]
    [EmailAddress(ErrorMessage = "Invalid email address")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Password is required")]
    public string Password { get; set; }

    [Description("Confirm Password")]
    [Compare(nameof(Password), ErrorMessage = "Passwords do not match")]
    public string ConfirmPassword { get; set; }
}

启动

public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        ...
        services.Configure<ApiBehaviorOptions>(options =>
        {
            options.InvalidModelStateResponseFactory = context =>
            {
                var problemDetails = new ValidationProblemDetails(context.ModelState)
                {
                    Instance = context.HttpContext.Request.Path,
                    Status = (int)HttpStatusCode.BadRequest,
                    Detail = "Please refer to the errors property for additional details"
                };

                return new BadRequestObjectResult(problemDetails)
                {
                    ContentTypes = "applicaton/json"
                };
            };
        });
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        ...
    }
}

调节器

[ApiController]
[Authorize]
[Route("users")]
public sealed class UserController : Controller
{
    public UserController(
        UserManager userManager,
        IMapper mappingProvider)
    {
        Manager = userManager;
        Mapper = mappingProvider;
    }

    private UserManager Manager { get; }
    private IMapper Mapper { get; }

    [HttpPost]
    [AllowAnonymous]
    [Consumes("application/json")]
    [Produces("application/json")]
    [ProducesResponseType(200)]
    [ProducesResponseType(400, Type = typeof(ValidationProblemDetails))]
    public async Task<IActionResult> Post([FromBody]ApiModels.RegistrationRequest request)
    {
        if (request == null) throw new ArgumentNullException(nameof(request));

        var user = Mapper.Map<DataModels.User>(request);

        var result = await Manager.Create(user, request.Password); // return OperationResult

        return result.ToActionResult();
    }
}

将OperationResult转换为IActionResult的扩展方法

public static class OperationResultExtensions
{
    public static ValidationProblemDetails ToProblemDetails(this OperationResult result)
    {
        if (result == null) throw new ArgumentNullException(nameof(result));

        var problemDetails = new ValidationProblemDetails()
        {
            Status = (int)HttpStatusCode.BadRequest
        };

        if (problemDetails.Errors != null)
        {
            result.Errors
               .ToList()
               .ForEach(i => problemDetails.Errors.Add(i.Key, i.Value.ToArray()));
        }

        return problemDetails;
    }

    public static IActionResult ToActionResult(this OperationResult result)
    {
        switch (result.Status)
        {
            case HttpStatusCode.OK:
                return new OkResult();

            case HttpStatusCode.NotFound:
                return new NotFoundResult();

            case HttpStatusCode.BadRequest:
                var problems = result.ToProblemDetails();
                return new BadRequestObjectResult(problems);

            default:
                return new StatusCodeResult((int)result.Status);
        }
    }
}

解决方法:

您有配置< ApiBehaviorOptions>在AddMvc之前:对AddMvc的调用注册了一个类implements IConfigureOptions<ApiBehaviorOptions>,它最终会覆盖你使用services配置的实例.Configure< ApiBehaviorOptions>并有效地resets the factory function.

要使其正常工作,您需要做的就是在ConfigureServices中切换顺序:

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        ...
    };
});

我也注意到虽然它不完全是粗体,但docs表明这种排序也很重要:

Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.Configure<ApiBehaviorOptions>(options => ... );

标签:c,asp-net-core,asp-net-core-2-1
来源: https://codeday.me/bug/20190622/1261742.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有