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

时间:2018-04-04 08:52:34

标签: c# validation asp.net-core-2.0 asp.net-core-middleware

我的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);
    }
}

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

我需要帮助 -

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

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

1 个答案:

答案 0 :(得分:5)

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

相反,您应该使用MVC filter,尤其是action filter。过滤器作为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)
    { }
}