5

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

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

我目前不得不写两个类

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

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

4

2 回答 2

0

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

于 2013-09-12T19:05:32.557 回答
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;
}
于 2021-06-20T02:38:16.240 回答