自定义中间件,用于输入验证

arp*_*tro 2 c# validation asp.net-core-middleware asp.net-core-2.0

我的API只有POST操作方法。我想创建一个库来验证对我的API的输入。现在,我想在点击控制器操作方法之前进行此验证。

我决定使用中间件方法-

public class ValidateInputMiddleware
{
    private readonly RequestDelegate _next;

    public ValidateInputMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        //read the request body

        //serialize the json body to input model

        //validations
        if(reqJsonObj.Id == null)
            //return response - id is null

        //other validations

        await _next(httpContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果满足我的验证条件,那么我不希望管道中的其他项目执行。

我需要帮助-

  1. 我如何限制执行中的其他项目。

  2. 如何以JSON形式返回自定义的错误响应。

pok*_*oke 6

您不应为此使用自定义中间件。中间件是非常底层的,正如您所注意到的,您将必须自己阅读和解析请求主体。这不仅很复杂,而且还会导致这种情况发生两次(同样在MVC中间件内部)。

相反,您应该使用MVC过滤器,尤其是动作过滤器。筛选器作为MVC管道的一部分运行,因此您可以依赖MVC管道已经为您完成的各种操作,例如模型绑定或授权。

这也使终止响应并返回自定义JSON响应变得更加容易,因为您不必再​​次手动序列化内容,而是可以使用高级MVC结果。

针对您的情况的操作过滤器可能如下所示:

public class InputValidationActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // we can even *still* use model state properly…
        if (!context.ModelState.IsValid)
        {
            var responseObj = new {
                successful = false,
                error = "The input is not valid",
            };

            // setting the result shortcuts the pipeline, so the action is never executed
            context.Result = new JsonResult(responseObj)
            {
                StatusCode = 400
            };
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    { }
}
Run Code Online (Sandbox Code Playgroud)

  • 经过长时间的讨论.. 我们现在准备采用 ActionFilter 方法.. 感谢@poke 推理中间件 ActionFilter 的用法 (2认同)