在aspx页面中支持OPTIONS请求标头

ari*_*ari 5 .net c# asp.net ajax webforms

我正在维护一个接受表单帖子并添加对CORS请求的支持的服务我在Firefox 3.6中遇到了问题,它发送带有OPTIONS请求标头的预检请求.

我在使用通用的http处理程序页面添加必要的Access-Control-Allow-Origin响应头时没有遇到任何问题,但是我在完整的aspx页面上遇到了困难.它肯定没有击中Page_Load,我无法弄清楚它在页面生命周期中的位置.

有人有主意吗?

谢谢!

Ste*_*eve 10

你可以用an HttpModule和an 来做到这一点HttpHandler

我认为其中一些来自某个地方的文章,其中的其他部分是在内部开发的...所以,如果其中一部分来自其他地方,我提前道歉,因为没有给予应有的信誉:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YourNamespaceHere
{
    using System;
    using System.Web; 
    using System.Collections;

    public class CrossOriginModule : IHttpModule {
        public String ModuleName {
            get { return "CrossOriginModule"; } 
        }    

        public void Init(HttpApplication application) {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e) {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            CrossOriginHandler.SetAllowCrossSiteRequestOrigin(context);
        }

        public void Dispose() 
        {
        }
    }

   public class CrossOriginHandler : IHttpHandler
    {
        #region IHttpHandler Members
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            //Clear the response (just in case)
            ClearResponse(context);

            //Checking the method
            switch (context.Request.HttpMethod.ToUpper())
            {
                //Cross-Origin preflight request
                case "OPTIONS":
                    //Set allowed method and headers
                    SetAllowCrossSiteRequestHeaders(context);
                    //Set allowed origin
                    //This happens for us with our module:
                    SetAllowCrossSiteRequestOrigin(context);
                    //End
                    context.Response.End();
                    break;

                default:
                    context.Response.Headers.Add("Allow", "OPTIONS");
                    context.Response.StatusCode = 405;
                    break;
            }

            context.ApplicationInstance.CompleteRequest();
        }
        #endregion

        #region Methods
        protected void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        protected void SetNoCacheHeaders(HttpContext context)
        {
            context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
            context.Response.Cache.SetValidUntilExpires(false);
            context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetNoStore();
        }
        #endregion

        public static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);
        }

        public static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                //This is necessary for Chrome/Safari actual request
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并在Web.config中:

  ...
  <system.webServer>
     ...
     <modules runAllManagedModulesForAllRequests="true">
     ...
           <add name="CrossOriginModule" preCondition="managedHandler" type="YOURNANMESPACEHERE.CrossOriginModule, ASSEMBLYNAME" />
    </modules>
    <handlers>
           <add name="CrossOrigin" verb="OPTIONS" path="*" type="YOURNAMESPACEHERE.CrossOriginHandler, ASSEMBLYNAME" />
    </handlers>
  </system.webServer>
Run Code Online (Sandbox Code Playgroud)


rob*_*pim 5

史蒂夫的答案是惊人的,它不可避免地导致我在我的情况下解决,这就是我投票的原因.但是,在我看来,HttpHandler可能不是明确必需的.所以我配置CORS,严格地在模块本身插入请求管道.我的代码:

using System;
using System.Web;

namespace NAMESPACE.HttpModules
{
    public class CrossOriginModule : IHttpModule
    {
        public String ModuleName
        {
            get { return "CrossOriginModule"; }
        }

        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            string httpMethod = context.Request.HttpMethod.ToUpper();

            //preflight
            if (httpMethod == "OPTIONS")
            {
                ClearResponse(context);

                //Set allowed method and headers
                SetAllowCrossSiteRequestHeaders(context);
                //Set allowed origin
                SetAllowCrossSiteRequestOrigin(context);

                //end request
                context.ApplicationInstance.CompleteRequest();
            }
            else
            {
                SetAllowCrossSiteRequestOrigin(context);
            }

        }
        static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);

            //allow credentials
            context.Response.AppendHeader("Access-Control-Allow-Credentials", "true");
        }

        static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }

        static void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        public void Dispose()
        {
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

在你的 web.config

<modules runAllManagedModulesForAllRequests="true">
    <add name="CrossOriginModule" preCondition="managedHandler" type="NAMESPACE.HttpModules.CrossOriginModule" />
</modules>
Run Code Online (Sandbox Code Playgroud)

这将根据需要配置响应头,并让MVC像往常一样处理请求.