ASP.NET Core使用筛选器发送参数验证



我有一个控制器方法,它有两个输入参数:DateTime dFrom, dtTo

所以,现在我检查间隔如下:

public async Task<ActionResult> GetValues([FromQuery] DateTime dtFrom, [FromQuery] DateTime dtTo)
{
if (dtFrom > dtTo)
{
return BadRequest($"{nameof(dtFrom)} < {nameof(dtTo)}");
}
}

但是,我想这样做验证:

[DateFilterAttribute(dtFrom,dtTo)]
public async Task<ActionResult> GetValues([FromQuery] DateTime dtFrom, [FromQuery] DateTime dtTo)
{
if (dtFrom > dtTo)
{
return BadRequest($"{nameof(dtFrom)} < {nameof(dtTo)}");
}
}

其中DateFilterAttribute:

public class DateFilterAttribute : ActionFilterAttribute
{
private DateTime _fromDt;
private DateTime _dtTo;
public DateFilterAttribute(DateTime fromDt, DateTime dtTo)
{
_fromDt = fromDt;
_dtTo = dtTo;
}
public override void OnActionExecuting(ActionExecutingContext context)
{            
context.HttpContext.Response.StatusCode = 400;
var errorStr = $"{nameof(_fromDt)} < {nameof(_dtTo)}";
context.HttpContext.Response.Headers.Add("Error", new string[] { errorStr });
}
}

但是,我不能在属性中使用输入参数。那么,我可以这样做吗?这是正确的方式吗?

我们可以使用ActionArguments属性,该属性为我们的操作中使用的每个参数都有条目。

public class DateRangeAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var fromKey = "fromDate";
var toKey = "toDate";
if (!context.ActionArguments.ContainsKey(fromKey) ||
!context.ActionArguments.ContainsKey(toKey))
{
context.Result = new BadRequestResult();
return;
}
if (!(context.ActionArguments[fromKey] is DateTime fromDate))
{
context.Result = new BadRequestResult();
return;
}
if (!(context.ActionArguments[toKey] is DateTime toDate))
{
context.Result = new BadRequestResult();
return;
}
if (fromDate > toDate)
{
context.Result = new BadRequestObjectResult(new
{
Error = "Bad date range"
});
return;
}
base.OnActionExecuting(context);
}
}

在我们的行动

[DateRangeAttribute]
public IActionResult Index(DateTime fromDate, DateTime toDate)
{
return View();
}

对于在查询字符串中传递的参数,您可以直接使用HttpContext.Request.Query,因此不需要向DateFilterAttribute构造函数传递任何内容:

public class DateFilterAttribute : ActionFilterAttribute
{
private DateTime _fromDt;
private DateTime _dtTo;
public override void OnActionExecuting(ActionExecutingContext context)
{
_fromDt = Convert.ToDateTime(context.HttpContext.Request.Query["dtFrom"]);
_dtTo = Convert.ToDateTime(context.HttpContext.Request.Query["dtTo"]);
context.HttpContext.Response.StatusCode = 400;
var errorStr = $"{nameof(_fromDt)} < {nameof(_dtTo)}";
context.HttpContext.Response.Headers.Add("Error", new string[] { errorStr });
}
}

现在你的GetValues应该是这样的:

[DateFilterAttribute]
public async Task<ActionResult> GetValues([FromQuery] DateTime dtFrom,
[FromQuery] DateTime dtTo)
{
//The rest of the code
}

最新更新