从 ValidationAttribute 更改响应状态代码
Change Response Status Code from ValidationAttribute
在 aspnet 核心 web api 项目中我有逻辑
if(!_entityService.Exists(entityId))
return NotFound($"{entityId} not found.");
分散在许多 endpoints/controllers 中。我想将这个横切关注点重构为一个属性,例如 ValidationAttribute:
class EntityExistsAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
var entityId = (int)value;
var entityService = validationContext.GetRequiredService<EntityService>();
if(entityService.Exists(entityId))
return ValidationResult.Success;
var httpContext = validationContext.GetRequiredService<IHttpContextAccessor>().HttpContext;
httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
return new ValidationResult($"{entityId} not found.");
}
}
尝试在控制器中应用:
class EntitiesController
{
[HttpGet("{id:int}")]
public Entity Get([FromRoute] [EntityExists] int id)
{
// no need to clutter here with the 404 anymore
}
}
虽然这似乎不起作用 - 端点仍将 return 400 错误请求。
possible/advised 在 asp.net 核心网络 api 中做这样的事情吗?我考虑过使用 middleware/action 过滤器,但也看不出如何通过这些过滤器实现上述目标。
您可以像下面这样自定义 ActionFilter 属性:
public class CustomActionFilter:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var entityId = int.Parse(context.HttpContext.Request.RouteValues["id"].ToString());
var entityService = context.HttpContext.RequestServices.GetService<EntityService>();
if (!entityService.Exists(entityId))
{
context.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
context.Result = new NotFoundObjectResult($"{entityId} not found.");
}
base.OnActionExecuting(context);
}
}
控制器:
[HttpGet("{id:int}")]
[CustomActionFilter]
public void Get([FromRoute] int id)
{
// no need to clutter here with the 404 anymore
}
结果:
在 aspnet 核心 web api 项目中我有逻辑
if(!_entityService.Exists(entityId))
return NotFound($"{entityId} not found.");
分散在许多 endpoints/controllers 中。我想将这个横切关注点重构为一个属性,例如 ValidationAttribute:
class EntityExistsAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
var entityId = (int)value;
var entityService = validationContext.GetRequiredService<EntityService>();
if(entityService.Exists(entityId))
return ValidationResult.Success;
var httpContext = validationContext.GetRequiredService<IHttpContextAccessor>().HttpContext;
httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
return new ValidationResult($"{entityId} not found.");
}
}
尝试在控制器中应用:
class EntitiesController
{
[HttpGet("{id:int}")]
public Entity Get([FromRoute] [EntityExists] int id)
{
// no need to clutter here with the 404 anymore
}
}
虽然这似乎不起作用 - 端点仍将 return 400 错误请求。
possible/advised 在 asp.net 核心网络 api 中做这样的事情吗?我考虑过使用 middleware/action 过滤器,但也看不出如何通过这些过滤器实现上述目标。
您可以像下面这样自定义 ActionFilter 属性:
public class CustomActionFilter:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var entityId = int.Parse(context.HttpContext.Request.RouteValues["id"].ToString());
var entityService = context.HttpContext.RequestServices.GetService<EntityService>();
if (!entityService.Exists(entityId))
{
context.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
context.Result = new NotFoundObjectResult($"{entityId} not found.");
}
base.OnActionExecuting(context);
}
}
控制器:
[HttpGet("{id:int}")]
[CustomActionFilter]
public void Get([FromRoute] int id)
{
// no need to clutter here with the 404 anymore
}
结果: