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

时间:2013-09-12 17:21:52

标签: c# asp.net .net asp.net-mvc-4 asp.net-web-api

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

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

我目前要写两个班级

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

这可以通过使用代理模式来实现。下面是一个简化的 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;
}