c# - 如何删除 ASP.NET Core 2.0 中错误消息的 ModelState 前缀?

标签 c# .net-core asp.net-core-2.0 modelstate asp.net-core-mvc-2.0

我正在开发将由我的客户使用的 ASP.NET Core 2.0 API。我遇到的问题之一是,当我使用 ModelState 对请求负载进行输入验证时,消费者看到的结果错误消息在响应 JSON 中有一个 [objectPrefix].PropertyName。我们的 API 文档列出了属性名称而不是对象类,因此当消费者编写将 JSON 响应反序列化到其本地对象模型的代码时,前缀会产生问题。

我可以在 Startup.cs ConfigureServices 方法中为 Service.AddMvc 或类似的东西设置任何选项来禁用此前缀吗?

如果重要的话,我在我的 API、.NET Core 2.0.4 和 VS2016 v15.5.7 中使用 Microsoft.AspNetCore.All(2.0.7) 依赖项。

我正在使用 System.ComponentModel.DataAnnotations 库中的数据注释并装饰我创建的 DTO 类属性,如下所示;

    [Required]
    [MaxLength(14)]
    public string AccountNumber
    {
        get => _accountNumber;
        set => _accountNumber = !string.IsNullOrWhiteSpace(value) ? value.Trim() : string.Empty;
    }

当消费者没有在请求有效负载中提供帐号时,返回的错误如下所示;

{
    "[AccountDto].AccountNumber": [
        "The AccountNumber field is required."
    ]
}

我想做的是消除 [AccountDto]。前缀,以便错误 JSON 看起来像这样;

{
    "AccountNumber": [
        "The AccountNumber field is required."
    ]
}

我找到了这个 SO发布,但它似乎引用了旧的 ASP.NET。

目前,我正在让我的客户对 json 响应进行字符串替换,但我真的希望有更好的解决方案。

有什么想法吗?

2018 年 5 月 16 日更新

看来前缀的问题与我在 *ForCreationDtos 中使用 Validate 方法有关。

例如,

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {

        if (CompanyId == 0)
        {
            yield return new ValidationResult("A Company ID is required.", new[] { "CompanyId" });
        }

    }

但是,我找到了一种变通方法,方法是使用全局 ModelState 处理程序并修改它以解析出前缀。

public class ValidateModelAttribute : ActionFilterAttribute
{

    /// <summary>
    /// Validates model state upon action execution
    /// </summary>
    /// <param name="context">ActionExecutingContext object</param>
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.ModelState.IsValid) return;
        var errorList = context.ModelState.Where(ms => ms.Value.Errors.Any()).ToDictionary(
            kvp => kvp.Key.Replace("[0].", ""),
            kvp => kvp.Value.Errors.Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage).ToArray()
        );
        var globalErrorDto = new GlobalErrorDto { Errors = errorList };
        context.Result = new BadRequestObjectResult(globalErrorDto);
    }
}

这有点粗略,假设为“[0]”。作为前缀,但这是我在 DTO 类中实现 Validate 方法时得到的前缀。这似乎解决了我的具体问题。

最佳答案

我正在使用 Microsoft.AspNetCore.All v2.0.8、Microsoft.NETCore.App v2.0.7 和 Visual Studio Community 2017 v15 .7.1,一切都如您所愿。

屏幕截图 #1:无帐号 - 400

No account number - 400

屏幕截图 #2:帐号太长 - 400

Account number too long - 400

屏幕截图 #3:有效帐号 - 201

Valid account number - 201

我无法重现您的问题。我什至想也许我只是在 Web 项目中创建了模型,所以我什至创建了一个单独的类项目来包含 DTO。结果仍然如您所愿!

DTO

using System.ComponentModel.DataAnnotations;

namespace DL.SO.ModelState.Dto.Users
{
    public class AccountModel
    {
        [Required]
        [MaxLength(14)]
        [Display(Name = "account number")]
        public string AccountNumber { get; set; }
    }
}

Controller

using DL.SO.ModelState.Dto.Users;
using Microsoft.AspNetCore.Mvc;

namespace DL.SO.ModelState.Controllers
{
    [Route("api/[controller]")]
    public class UsersController : ControllerBase
    {
        [HttpGet("{id}")]
        public IActionResult GetById(string id)
        {
            // Just testing 
            return Ok(id);
        }

        [HttpPost]
        public IActionResult Post(AccountModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // Just testing so I pass in null
            return CreatedAtAction(nameof(GetById), 
                 new { id = model.AccountNumber }, null);
        }
    }
}

启动

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace DL.SO.ModelState
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }
}

关于c# - 如何删除 ASP.NET Core 2.0 中错误消息的 ModelState 前缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50139720/

相关文章:

c# - C# 中的 Apple 推送通知服务器端

c# - 使用 SELECT 查询时抛出异常 : 'System.Collections.Generic.KeyNotFoundException' in mscorlib. dll

c# - 如何在 asp.net-core-2.0 中的项目中添加 'IDesignTimeDbContextFactory<DataContext>' 的实现

c# - 在 asp.net core 中使用 Identity server4 对登录 Controller 进行 API 集成测试

c# - 不使用 ASP.Net Core 2 中的迁移命令 Update-Database 创建数据库

c# - 检查一组对象是否正在移动 Unity 3D

c# - 在 C# 中,是否有任何我不应该使用的内置异常?

c# - 如何更新最新次要版本Nuget解决方案的所有软件包?

c# - 添加 .resx 文件时 WPF .net Core 3.0 编译错误

visual-studio - 如果生成单个文件,如何在堆栈跟踪中显示行号