14

私の Sencha Touch アプリは私のPOST WebService にフォームを投稿していますが、それを送信するのではなく、送信していOPTIONSます。

ここで同様のスレッドを読んでいますOPTIONSが、コードでメソッドを処理する方法がわかりません。

アクションに属性を追加しようとし[AllowAjax]ましたが、MVC3 には存在しないようです。

オプション /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.5.206/ Access-Control-Request-Method: POST
Origin: http://192.168.5.206
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (Gecko のような KHTML) Chrome/11.0.696.71 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Content-Type
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

私の ActionMethod では、次のコードを使用しています。

    public JsonpResult CommunicateCard(CommunicateCard communicateCard)
    {

        // Instantiate a new instance of MailMessage
        MailMessage mMailMessage = new MailMessage();

        // removed for security/brevity

        // Set the body of the mail message
        mMailMessage.Body = communicateCard.name; // THIS IS CURRENTLY BLANK :-(

        // removed for security/brevity
        mSmtpClient.Send(mMailMessage);

        // do server side validation on form input
        // if it's valid return true
        // else return false
        // currently returning NULL cuz I don't care at this point.
        return this.Jsonp(null);
    }
4

6 に答える 6

15

私は作成しなければならなかったことが判明しましたActionFilterAttribute

namespace WebService.Attributes
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();

            filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", "*");

            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
            {
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin, Content-Type");
            }
            base.OnActionExecuting(filterContext);
        }
    }
}
于 2011-08-09T20:47:28.077 に答える
10

MVCとIISでこれを別の方法で解決しました。この問題を見つけた理由は、クライアント側の JavaScript (JSONP が機能しない) からデータを POST したかったためであり、その上で、POST 要求のコンテンツ内にある JSON データを許可したかったためです。

実際には、コードは最初の CORS OPTIONS リクエストを無視したいと考えています。これは、API 呼び出しごとの設定ではなく、「サイト全体の設定」である可能性が高いためです。

まず、CORS 応答を送信するように IIS を構成しました。これは、IIS マネージャー (または web.config の更新) を介して行うことができます。IIS を使用している場合は、次の 2 つの値を追加するサイトに移動します。

  • Access-Control-Allow-Origin を "*" に変更 (テストの場合、セキュリティを強化するために、特定の呼び出し元ドメインに制限する必要がある場合があります)
  • Access-Control-Allow-Headers, "Content-Type, Accept" (これは JSON データを投稿するためのものです)

次に、カスタム ActionFilter を作成しました。これは、CORS 要求をトリガーできる POST データを受け入れたいコントローラーごとに適用する必要があります。カスタム アクション フィルターは次のとおりです。

public class CORSActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
        {
            // do nothing let IIS deal with reply!
            filterContext.Result = new EmptyResult();
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
    }
}

次に、各コントローラーの開始時に、属性を追加するためにこれを適用する必要があります。

[CORSActionFilter]
public class DataSourcesController : Controller

これで、MVC ソリューション全体でこれを行う方法があると確信していますが (ソリューションを歓迎します)、BBQ を作成する必要があり、上記のソリューションが機能します!

于 2012-08-10T09:58:07.740 に答える
9

<system.webServer>config セクションに以下を追加しました。

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Headers" value="Content-Type, Accept, X-Requested-With"/>
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
    <add name="Access-Control-Allow-Origin" value="*"/>
  </customHeaders>
</httpProtocol>
于 2013-01-22T21:14:33.737 に答える
4

ブラウザがCORS(クロスオリジンリソースシェアリング)を実装しているため、「POST」ではなく「OPTIONS」という質問に答えるだけです。これは、最初にOPTIONSリクエストを送信する2つの部分からなるプロセスであり、サーバーが許容可能な条件で応答した場合、ブラウザはデータ/コンテンツを含む実際のリクエストをPOSTします。

于 2012-08-10T09:44:54.570 に答える
1

ここですべての答えを試しましたが、どれもうまくいきませんでした。最終的に、200 以外が返された場合、ブラウザーはプリフライト チェックを失敗として処理することに気付きました。私の場合、IIS はヘッダーを含めても 404 を返していました。これは、コントローラー メソッドに [HttpPost] と [HttpOptions] の 2 つの属性があったためです。どうやら、これは複数の動詞を表現するための有効なメカニズムではありません。代わりにこの属性を使用する必要がありました: [AcceptVerbs(HttpVerbs.Options | HttpVerbs.Post)]

于 2016-10-26T22:45:56.223 に答える
1

かなり苦労した結果、CORS プリフライト リクエストを処理する唯一の方法は、HttpModule と HttpHandler のペアで処理することであることがわかりました。必要なヘッダーを送信するだけでは不十分です。OPTIONS リクエストを早期に処理し、コントローラーに到達させないようにする必要があります。コントローラーで失敗するためです。

これを行う唯一の方法は、HttpModule を使用することでした。

私はこのブログ投稿に従いました:

http://geekswithblogs.net/abhijeetp/archive/2016/06/04/adding-cors-support-for-asp.net--webapi-the-no-hassle.aspx

作業を要約すると、これはコードです。

namespace WebAPI.Infrastructure
{
    using System;
    using System.Web;
    using System.Collections;
    using System.Net;
    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.AddCorsResponseHeaders(context);
        }

        public void Dispose()
        {
        }
    }

    public class CrossOriginHandler : IHttpHandler
    {
        #region Data Members
        const string OPTIONS = "OPTIONS";
        const string PUT = "PUT";
        const string POST = "POST";
        const string PATCH = "PATCH";
        static string[] AllowedVerbs = new[] { OPTIONS, PUT, POST, PATCH };
        const string Origin = "Origin";
        const string AccessControlRequestMethod = "Access-Control-Request-Method";
        const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
        const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
        const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
        const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
        const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
        const string AccessControlMaxAge = "Access-Control-Max-Age";
        const string MaxAge = "86400";
        #endregion

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

        public void ProcessRequest(HttpContext context)
        {
            switch (context.Request.HttpMethod.ToUpper())
            {
                //Cross-Origin preflight request
                case OPTIONS:
                    AddCorsResponseHeaders(context);
                    break;

                default:
                    break;
            }
        }
        #endregion

        #region Static Methods
        public static void AddCorsResponseHeaders(HttpContext context)
        {
            if (Array.Exists(AllowedVerbs, av => string.Compare(context.Request.HttpMethod, av, true) == 0))
            {
                var request = context.Request;
                var response = context.Response;
                var originArray = request.Headers.GetValues(Origin);
                var accessControlRequestMethodArray = request.Headers.GetValues(AccessControlRequestMethod);
                var accessControlRequestHeadersArray = request.Headers.GetValues(AccessControlRequestHeaders);
                if (originArray != null &&
                    originArray.Length > 0)
                    response.AddHeader(AccessControlAllowOrigin, originArray[0]);
                response.AddHeader(AccessControlAllowCredentials, bool.TrueString.ToLower());

                if (accessControlRequestMethodArray != null &&
                    accessControlRequestMethodArray.Length > 0)
                {
                    string accessControlRequestMethod = accessControlRequestMethodArray[0];
                    if (!string.IsNullOrEmpty(accessControlRequestMethod))
                    {
                        response.AddHeader(AccessControlAllowMethods, accessControlRequestMethod);
                    }
                }
                if (accessControlRequestHeadersArray != null &&
                    accessControlRequestHeadersArray.Length > 0)
                {
                    string requestedHeaders = string.Join(", ", accessControlRequestHeadersArray);
                    if (!string.IsNullOrEmpty(requestedHeaders))
                    {
                        response.AddHeader(AccessControlAllowHeaders, requestedHeaders);
                    }
                }
            }
            if (context.Request.HttpMethod == OPTIONS)
            {
                context.Response.AddHeader(AccessControlMaxAge, MaxAge);
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                context.Response.End();
            }
        } 
        #endregion
    }
}

それらをに追加しますweb.config

<system.webServer>  
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
      <add name="CrossOriginModule" preCondition="managedHandler" type="WebAPI.Infrastructure.CrossOriginModule, Your_Assembly_Name" />
    </modules>
    <handlers>
      <remove name="WebDAV"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." 
           verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." 
           verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." 
           verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <add name="CrossOrigin" verb="OPTIONS" path="*" type="WebAPI.Infrastructure.CrossOriginHandler, Your_Assembly_Name" />
    </handlers>   
     <security>
       <authorization>
         <remove users="*" roles="" verbs=""/>
         <add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,PATCH,DELETE,DEBUG"/>
       </authorization>
     <requestFiltering>
       <requestLimits maxAllowedContentLength="6000"/>
       <verbs>
         <remove verb="OPTIONS"/>
         <remove verb="PUT"/>
         <remove verb="PATCH"/>
         <remove verb="POST"/>         
         <remove verb="DELETE"/>
       </verbs>
     </requestFiltering>
   </security> 
  </system.webServer>

これは、Web API と MVC で機能します。

于 2019-02-12T19:39:58.637 に答える