【问题标题】:Custom Content-Type validation filter?自定义内容类型验证过滤器?
【发布时间】:2016-11-11 09:00:21
【问题描述】:

我想实现自定义 Content-Type 验证过滤器,以便可以提供 415 Unsupported Media Type 上的自定义错误模型。

类似这样的:

public class ValidateContentTypeFilterAttribute : ActionFilterAttribute
{
    private const string JsonMimeType = "application/json";

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        string requestMethod = context.HttpContext.Request.Method.ToUpper();

        if (requestMethod == WebRequestMethods.Http.Post || requestMethod == WebRequestMethods.Http.Put)
        {
            if (request.ContentType != JsonMimeType)
            {
                // "Unsupported Media Type" HTTP result.
                context.Result = new HttpUnsupportedMediaTypeResult();
                return;
            }
        }
    }
}

问题在于 MVC 管道似乎在执行任何自定义过滤器之前“捕获”了不受支持或无效的 Content-Type 值。即使是“application/xml”内容类型也会被拒绝。

在哪里配置?

我的 MVC 配置仅包含以下内容:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddMvc()
        .AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Include;
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            options.SerializerSettings.Converters.Add(new SquidJsonConverter());
        })
        .AddMvcOptions(options =>
        {
            options.Filters.Add(typeof(ValidateAntiForgeryTokenAttribute));
            options.Filters.Add(typeof(ValidateContentTypeFilterAttribute));
            options.Filters.Add(typeof(ValidateAcceptFilterAttribute));
            options.Filters.Add(typeof(ValidateModelFilterAttribute));
        });
    ...
}

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc asp.net-core-1.0 asp.net-mvc-filters


    【解决方案1】:

    动作过滤器在处理管道中为时已晚,无法实现您在此处尝试实现的目标。

    “传入”请求的过滤器执行顺序如下:

    1. 授权过滤器的OnAuthorization..方法调用
    2. 资源过滤器的OnResourceExecuting..方法调用模型
    3. 发生模型绑定(这是内容类型检查的地方 制作)
    4. 动作过滤器的OnActionExecuting.. 方法调用
    5. 动作执行发生

    您可以改为创建资源过滤器。一个例子:

    public class CustomResourceFilter : IResourceFilter
    {
        private readonly string jsonMediaType = "application/json";
    
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
        }
    
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            if (context.HttpContext.Request.Method == "PUT" || context.HttpContext.Request.Method == "POST")
            {
                if (!string.Equals(
                    MediaTypeHeaderValue.Parse(context.HttpContext.Request.ContentType).MediaType,
                    jsonMediaType,
                    StringComparison.OrdinalIgnoreCase))
                {
                    context.Result = new JsonResult(new { Error = "An error message here" }) { StatusCode = 415 };
                }
            }
        }
    }
    

    如果您想修改所有类型的UnsupportedMediaTypeResult 响应,那么您可以编写一个结果过滤器。

    传出响应的过滤器管道是:

    1. 动作过滤器的OnActionExecuted...方法调用
    2. 结果过滤器的OnResultExecuting..方法调用
    3. 结果过滤器的OnResultExecuted..方法调用
    4. 资源过滤器的OnResourceExecuted.. 方法调用

    带有结果过滤器的示例:

    public class CustomResultFilter : ResultFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            var result = context.Result as UnsupportedMediaTypeResult;
            if (result != null)
            {
                context.Result = new JsonResult(new { Error = "An error message here" }) { StatusCode = 415 };
            }
        }
    }
    

    【讨论】:

    • 结果过滤器对我来说是新的!这非常有效 - 谢谢。
    猜你喜欢
    • 1970-01-01
    • 2022-12-08
    • 2015-08-01
    • 2010-09-12
    • 2014-03-03
    • 2020-02-14
    • 2016-12-11
    • 1970-01-01
    • 2021-02-13
    相关资源
    最近更新 更多