为啥我们不再需要在更高版本的 ASP.NET Core 中手动验证模型?
Posted
技术标签:
【中文标题】为啥我们不再需要在更高版本的 ASP.NET Core 中手动验证模型?【英文标题】:Why do we no longer need to manually validate models in higher versions of ASP.NET Core?为什么我们不再需要在更高版本的 ASP.NET Core 中手动验证模型? 【发布时间】:2020-03-31 06:40:41 【问题描述】:我的所有模型在到达端点之前都会自动验证,如果某种形式的验证失败,则会返回相应的错误。
我记得在 ASP.NET Core 2.2 中,我们需要手动调用 ModelState.IsValid
以确保对象已通过验证检查,但在最新的 ASP.NET Core 3.0 中,情况似乎并非如此,而且我在任何地方都没有明确地包含/配置任何服务以使这种行为存在。
有人能对此事有所了解,或许可以链接他们提到此更改的相关来源吗?
编辑:是因为[ApiController]
属性吗?见:https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1#automatic-http-400-responses
谢谢!
【问题讨论】:
您是使用 MVC 还是仅使用 Web API 构建 Web 应用程序? @citronas 我正在使用services.AddControllers
、app.UseRouting
和app.UseEndpoints
控制器实现Controller
,而不是BaseController
(他们也使用属性[ApiController]
)
【参考方案1】:
使用[ApiController]
属性时,不需要在每个方法中检查ModelState.IsValid,因为会自动返回400状态码以及验证失败的字段名称,参见https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-3.1
您甚至可以修改 400 状态代码的外观。这篇博客文章应该可以帮助您入门:https://coderethinked.com/customizing-automatic-http-400-error-response-in-asp-net-core-web-apis/
添加这个依赖:
services.AddMvc.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.ConfigureApiBehaviorOptions(options =>
options.InvalidModelStateResponseFactory = context =>
var problems = new CustomBadRequest(context);
return new BadRequestObjectResult(problems);
;
);
您的自定义错误请求类可能如下所示。如果您想包含有关错误的其他信息,例如错误严重性、警告等,请创建一个 YourErrorClass 类。
public class CustomBadRequest
[JsonProperty("httpstatuscode")]
public string HttpStatusCode get; set;
[JsonProperty("errors")]
public List<YourErrorClass> Errors get; set; = new List<YourErrorClass>();
public CustomBadRequest(ActionContext context)
this.HttpStatusCode = "400";
this.Errors = new List<YourErrorClass>();
this.ConstructErrorMessages(context);
private void ConstructErrorMessages(ActionContext context)
foreach (var keyModelStatePair in context.ModelState)
var key = keyModelStatePair.Key;
var errors = keyModelStatePair.Value.Errors;
if (errors != null && errors.Count > 0)
foreach (var error in errors)
Errors.Add(new YourErrorClass()
ErrorMessage = error.ErrorMessage
// add additional information, if you like
);
【讨论】:
我添加了一些代码来自定义返回的错误类 这太有用了,谢谢!除了不检查模型是否有效之外,您也不需要检查对象是否为空,对吧?因为它自动要求其属性具有某种形式的价值? 也不应该是error
而不是errors[0]
吗?你从来没有使用过error
,你只是在迭代元素?
是的,感谢您的关注。我在回答中简化了解决方案并犯了一个错误,现在我更正了;)
谢谢!!奇迹般有效!只是一个额外的问题..有没有办法显示错误。ErrorMessage 翻译成特定的语言?谢谢!【参考方案2】:
是的,这是因为 ApiController
属性。
但是,即使在 Core 2.2 中也会发生这种情况,但是有一个选项可以将兼容性设置为 2.0,但是从 3.0 起不再有效,这可能解释了您看到的行为。
要在 3.0 及更高版本中关闭它,您需要在执行 services.AddControllers()
或 services.AddMvc()
时在选项中设置它,如下代码所示:
services.AddControllers().ConfigureApiBehaviorOptions(options =>
options.SuppressModelStateInvalidFilter = true;
另请注意,核心 2.1 和更高版本之间存在差异,如 this MSDN article 中所述,如下例所示:
Core 2.1 示例响应:
"": [
"A non-empty request body is required."
]
Core 2.2 及更高版本示例响应:
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors":
"": [
"A non-empty request body is required."
]
要恢复 2.1 的行为,您可以将兼容性设置回 2.1,但这在 3.0 及更高版本后不再有效,而是在执行 services.AddControllers()
或 services.AddMvc()
时需要在选项配置中添加以下代码在以下代码中:
services.AddControllers().ConfigureApiBehaviorOptions(options =>
options.InvalidModelStateResponseFactory = context =>
new BadRequestObjectResult(new SerializableError(context.ModelState));
);
【讨论】:
以上是关于为啥我们不再需要在更高版本的 ASP.NET Core 中手动验证模型?的主要内容,如果未能解决你的问题,请参考以下文章
我的导航栏显示了太多项目和溢出。如何在更高的屏幕宽度下折叠它? [复制]
Linq 查询在 ASP.NET-Core 3.0 及更高版本中对数字等字符串进行排序
React-Native .apk 文件在更高版本的 android 设备中失败
React Native 版本 .apk 在更高版本的 android 设备中崩溃,地理定位权限被拒绝错误