编写适用于 MVC 和 Web API 请求的过滤器

Posted

技术标签:

【中文标题】编写适用于 MVC 和 Web API 请求的过滤器【英文标题】:Writing a filter that applies to both MVC and Web API requests 【发布时间】:2013-09-17 05:07:27 【问题描述】:

我的 ASP.NET 应用程序使用 ASP.NET MVC 为网页提供服务,并使用 ASP.NET Web API 为源自这些网页的 AJAX 请求提供服务。

我想要某些事情,例如检查请求是否经过身份验证,在 HttpContext 中设置适当的事情,无论我正在处理哪种请求。

我现在要写两个类

1) 一个继承 - System.Web.Mvc.ActionFilterAttribute 用于 MVC 请求 2)一个继承 - System.Web.Http.Filters.ActionFilterAttribute for Web API请求

有没有办法为网站应用同时针对 MVC 和 API 请求运行的过滤器?或者通过旧的http模块是这种用例的推荐方式?

【问题讨论】:

【参考方案1】:

我没有看到将 MVC 和 Web API 中的身份验证/授权过滤器放入单个过滤器的好方法,因为它们的行为非常不同。对于当用户授权失败时的 MVC 请求,您希望将他们重定向到另一个页面以以另一个用户身份登录,或者只是让他们知道他们无权访问该页面。对于用户授权失败时的 Web API 请求,您希望发送指示授权失败的 HTTP 状态代码并让客户端处理它。例如,如果您 add basic authentication to your filter as described in this article,他们甚至可以在行为和功能上更多地离题。这仅对 Web API 请求有意义,对 MVC 请求无效。我认为拥有两个不同的过滤器是一种更清洁的分离方式。

【讨论】:

当然,我认为身份验证是一个不好的例子。假设我们想根据请求在 HttpContext 中设置某些东西 - 我想对 MVC 和 Web API 请求都这样做。【参考方案2】:

这可以通过使用代理模式来实现。下面是一个简化的EnableCorsAttribute 示例,用于展示如何:

using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Mvc;
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System;

public class EnableCorsAttribute:System.Web.Mvc.ActionFilterAttribute, System.Web.Http.Filters.IActionFilter 
    class HttpActionFilter:System.Web.Http.Filters.ActionFilterAttribute 
        public override void OnActionExecuted(HttpActionExecutedContext filterContext) 
            var res = filterContext.Response;
            res.Headers.Add("Access-Control-Allow-Origin", String.Join(",\x20", m_httpFilter.Origins));
            res.Headers.Add("Access-Control-Allow-Headers", String.Join(",\x20", m_httpFilter.Headers));
            res.Headers.Add("Access-Control-Allow-Credentials", "true");
            base.OnActionExecuted(filterContext);
        

        public HttpActionFilter(EnableCorsAttribute filter) 
            m_httpFilter=filter;
        

        EnableCorsAttribute m_httpFilter;
    

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
        var res = filterContext.HttpContext.Response;
        res.Headers.Add("Access-Control-Allow-Origin", String.Join(",\x20", this.Origins));
        res.Headers.Add("Access-Control-Allow-Headers", String.Join(",\x20", this.Headers));
        res.Headers.Add("Access-Control-Allow-Credentials", "true");
        base.OnActionExecuted(filterContext);
    

    public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
        return m_mvcFilter.ExecuteActionFilterAsync(actionContext, cancellationToken, continuation);
    

    public EnableCorsAttribute(String origins, String headers, String methods) 
        m_mvcFilter=new HttpActionFilter(this);

        var separator = new[]  ',' ;
        var options = StringSplitOptions.RemoveEmptyEntries;
        this.Origins=origins.Split(separator, options);
        this.Headers=headers.Split(separator, options);
        this.Methods=methods.Split(separator, options);
    

    public IList<String> Origins 
        get; private set;
    

    public IList<String> Headers 
        get; private set;
    

    public IList<String> Methods 
        get; private set;
    

    System.Web.Http.Filters.IActionFilter m_mvcFilter;

【讨论】:

以上是关于编写适用于 MVC 和 Web API 请求的过滤器的主要内容,如果未能解决你的问题,请参考以下文章

使 servlet 过滤器适用于所有 Web 应用程序

从 ionic iOS 原生到 WP rest API 的 http 请求出错(适用于 web 视图和 DevApp)

过滤,获取控制器前的url(Spring MVC)

多个 CORS 适用于 GET 但不适用于 PUT/POST 与飞行前请求 Web api 2

使用 MVC3 的 Paypal API 请求

在 .NET MVC 4 (Web API) 中,如何拦截对控制器的请求并更改其 Content-Type?