如何在 ASP.NET Core Web API 中的每个方法中进行模型验证?
How to do model validation in every method in ASP.NET Core Web API?
我正在进入 ASP.NET Core 2.0 with Web API。我的第一个方法是登录:
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data)
{
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null)
{
return Unauthorized();
}
else
{
return Ok(token);
}
}
我的 LoginData
使用 DataAnnotations:
public class LoginData
{
[Required]
[MaxLength(50)]
public string Username { get; set; }
[Required]
public string Password { get; set; }
[Required]
[MaxLength(16)]
public string IpAddress { get; set; }
}
所以我的 ModelState
会在登录时自动填充,例如密码为空(当然在客户端稍后也应该进行验证)。
最好的方法是什么
- 检查模型状态,
- 从所有错误中获取可读的字符串并且
- return
BadRequest
有这个错误?
当然我可以用辅助方法自己写。但我考虑过过滤器吗?
How to check the model state?
在动作中查看控制器的ModelState
以获取模型的状态。
getting a readable string out of all errors and return a BadRequest with this error?
使用 BadRequest(ModelState)
到 return HTTP 错误请求响应,它将检查模型状态并使用错误构造消息。
完成代码
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data) {
if(ModelState.IsValid) {
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null) {
return Unauthorized();
} else {
return Ok(token);
}
}
return BadRequest(ModelState);
}
Of course I could write it all myself in a helper method... But I thought about a filter maybe?
为了避免在需要模型验证的每个操作中重复 ModelState.IsValid
代码,您可以创建一个过滤器来检查模型状态并使请求短路。
例如
public class ValidateModelAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext context) {
if (!context.ModelState.IsValid) {
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
可以直接应用于动作
[ValidateModel] //<-- validation
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data) {
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null) {
return Unauthorized();
} else {
return Ok(token);
}
}
或全局添加以应用于应检查模型状态的所有请求。
要检查模型状态是否有效,请使用 ModelState 属性(由控制器 class 继承自的 ControllerBase class 公开)
ModelState.IsValid
要从 ModelState 中获取错误,您可以从字典中过滤出错误,然后return将它们作为列表
var errors = ModelState
.Where(a => a.Value.Errors.Count > 0)
.SelectMany(x => x.Value.Errors)
.ToList();
然后,一个选项是验证每个 method/controller 中的状态,但我建议您在基础 class 中实施验证,该基础验证
中的模型
像这样的 OnActionExecuting 方法
public class ApiController : Controller
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!ModelState.IsValid)
{
var errors = ModelState
.Where(a => a.Value.Errors.Count > 0)
.SelectMany(x => x.Value.Errors)
.ToList();
context.Result = new BadRequestObjectResult(errors);
}
base.OnActionExecuting(context);
}
}
然后每个应该具有自动模型状态验证的控制器都继承自基础class
public class TokenController : ApiController
{
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data)
{
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null)
{
return Unauthorized();
}
else
{
return Ok(token);
}
}
}
我强烈建议使用 [ApiController]
和其他有助于在基于 Web API 的项目中简化验证的属性。
[ApiController]
此属性在进入方法之前为您完成模态框的所有基本验证。因此,如果您想进行某种形式的自定义验证,则只需检查模态。
我正在进入 ASP.NET Core 2.0 with Web API。我的第一个方法是登录:
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data)
{
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null)
{
return Unauthorized();
}
else
{
return Ok(token);
}
}
我的 LoginData
使用 DataAnnotations:
public class LoginData
{
[Required]
[MaxLength(50)]
public string Username { get; set; }
[Required]
public string Password { get; set; }
[Required]
[MaxLength(16)]
public string IpAddress { get; set; }
}
所以我的 ModelState
会在登录时自动填充,例如密码为空(当然在客户端稍后也应该进行验证)。
最好的方法是什么
- 检查模型状态,
- 从所有错误中获取可读的字符串并且
- return
BadRequest
有这个错误?
当然我可以用辅助方法自己写。但我考虑过过滤器吗?
How to check the model state?
在动作中查看控制器的ModelState
以获取模型的状态。
getting a readable string out of all errors and return a BadRequest with this error?
使用 BadRequest(ModelState)
到 return HTTP 错误请求响应,它将检查模型状态并使用错误构造消息。
完成代码
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data) {
if(ModelState.IsValid) {
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null) {
return Unauthorized();
} else {
return Ok(token);
}
}
return BadRequest(ModelState);
}
Of course I could write it all myself in a helper method... But I thought about a filter maybe?
为了避免在需要模型验证的每个操作中重复 ModelState.IsValid
代码,您可以创建一个过滤器来检查模型状态并使请求短路。
例如
public class ValidateModelAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext context) {
if (!context.ModelState.IsValid) {
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
可以直接应用于动作
[ValidateModel] //<-- validation
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data) {
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null) {
return Unauthorized();
} else {
return Ok(token);
}
}
或全局添加以应用于应检查模型状态的所有请求。
要检查模型状态是否有效,请使用 ModelState 属性(由控制器 class 继承自的 ControllerBase class 公开)
ModelState.IsValid
要从 ModelState 中获取错误,您可以从字典中过滤出错误,然后return将它们作为列表
var errors = ModelState
.Where(a => a.Value.Errors.Count > 0)
.SelectMany(x => x.Value.Errors)
.ToList();
然后,一个选项是验证每个 method/controller 中的状态,但我建议您在基础 class 中实施验证,该基础验证
中的模型
像这样的 OnActionExecuting 方法
public class ApiController : Controller
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!ModelState.IsValid)
{
var errors = ModelState
.Where(a => a.Value.Errors.Count > 0)
.SelectMany(x => x.Value.Errors)
.ToList();
context.Result = new BadRequestObjectResult(errors);
}
base.OnActionExecuting(context);
}
}
然后每个应该具有自动模型状态验证的控制器都继承自基础class
public class TokenController : ApiController
{
/// <summary>
/// API endpoint to login a user
/// </summary>
/// <param name="data">The login data</param>
/// <returns>Unauthorizied if the login fails, The jwt token as string if the login succeded</returns>
[AllowAnonymous]
[Route("login")]
[HttpPost]
public IActionResult Login([FromBody]LoginData data)
{
var token = _manager.ValidateCredentialsAndGenerateToken(data);
if (token == null)
{
return Unauthorized();
}
else
{
return Ok(token);
}
}
}
我强烈建议使用 [ApiController]
和其他有助于在基于 Web API 的项目中简化验证的属性。
[ApiController]
此属性在进入方法之前为您完成模态框的所有基本验证。因此,如果您想进行某种形式的自定义验证,则只需检查模态。