15

重複の可能性:
XmlHttpRequest の WebAPI を使用した CORS



webApi プロジェクトにクロスドメイン ajax 投稿を実装しようとしています。
1. webapiアクションを変更するまで、常に204エラーが発生 していました。

public void submit(Submission model)

public bool submit(Submission model)

理由はわかりませんが、200 OKステータス

2 を取得しています。まだ ajax 起動エラー コールバックです。

3.ずっと前に、この種のクロスドメイン投稿のエラーを追加して解決しました

HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");

私のコントローラーに。しかし、今では webApi に固有のもので: ApiController あり、このトリックは機能しません。Error an object reference is required for the non-static field, method, or property"System.Web.HttpContext.Response.get"

経由で投稿しようとしたコンパイラを表示しますdataType: 'JSONP'が、null モデルを取得します。

Javascript リクエストは次のようになります。

変数モデル = {
        "type": $("#model-type").val(),
        "subject": $("#subject-text").val(),
        "body": $("#body-text").val()
    };

    $.ajax({
        タイプ: "ポスト",
        データ型: 'JSONP',
        URL: $("#submit-url").val(),
        データ・モデル、
        成功: 関数 () {
            alert("正常に送信されました");
        }、
        エラー: 関数 () {
            alert("エラー...");
        }
    });

私が間違っていることは何ですか?

解決した

私を助けてくれたみんなに感謝します。コメントリンクの1つで解決策を見つけました。私は次のアプローチを使用しましたが、これは非常に簡単だと思います。

出典:
ASP.NET Web API での CORS サポートの実装


私が作ったもの:

1.プロジェクトに新しいクラスを作成しました:CorsHandler.csそして次のコードをコピーして貼り付けました:


public class CorsHandler : DelegatingHandler
    {
        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";

        protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            bool isCorsRequest = request.Headers.Contains(Origin);
            bool isPreflightRequest = request.Method == HttpMethod.Options;
            if (isCorsRequest)
            {
                if (isPreflightRequest)
                {
                    return Task.Factory.StartNew(() =>
                    {
                        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                        response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());

                        string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
                        if (accessControlRequestMethod != null)
                        {
                            response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
                        }

                        string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
                        if (!string.IsNullOrEmpty(requestedHeaders))
                        {
                            response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
                        }

                        return response;
                    }, cancellationToken);
                }
                else
                {
                    return base.SendAsync(request, cancellationToken).ContinueWith(t =>
                    {
                        HttpResponseMessage resp = t.Result;
                        resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
                        return resp;
                    });
                }
            }
            else
            {
                return base.SendAsync(request, cancellationToken);
            }
        }
    }

  1. Global.asaxを開い て変更しましたApplication_Start

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
        }

アクションの最後の行に注意してください。

このアプローチは、MVC3 および .NET 4.0 と互換性があります。うまく機能し、ajax で「成功」と「エラー」のコールバックを処理できるようになりました。

4

2 に答える 2

1

それぞれの質問への回答:

  1. ステータス 204 はエラーではありません。つまり、返されるコンテンツはありませんが、すべて問題ありません。RFC2616での 204 の定義は次のとおりです。

10.2.5 204 コンテンツなし

サーバーは要求を満たしましたが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。レスポンスには、新しいメタ情報または更新されたメタ情報がエンティティ ヘッダーの形式で含まれる場合があります。エンティティ ヘッダーが存在する場合は、リクエストされたバリアントに関連付ける必要があります。

クライアントがユーザー エージェントである場合、リクエストが送信された原因となったドキュメント ビューを変更すべきではありません (SHOULD NOT)。この応答は主に、ユーザー エージェントのアクティブなドキュメント ビューを変更せずにアクションの入力を許可することを目的としていますが、現在ユーザー エージェントのアクティブなビューにあるドキュメントには、新しいメタ情報または更新されたメタ情報を適用する必要があります。

204 応答にはメッセージ本文を含めてはならない (MUST NOT) ため、常にヘッダー フィールドの後の最初の空行で終了します。

  1. あなたが遭遇したエラーは何ですか?現在、ASP.NET Web API には、すぐに使える JSONP フォーマッタがありません。3番目の部分の実装は次のとおりです。
  1. Web API では、Response を参照する方法は HttpContext ではありません。アクセス方法は複数あります。

最初のオプションは、アクションを返す HttpResponse を直接定義することです。

    public HttpResponseMessage Get(int id)
    {
        var response = this.Request.CreateResponse();
        response.StatusCode = HttpStatusCode.OK;
        response.Headers.Add("Access-Control-Allow-Origin", "*");

        return response;
    }

2 番目のオプションは、ActionFilter を使用することです。

// define action filter for cross domain
public class CrossDomainActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        bool needCrossDomain = true;

        if (needCrossDomain)
        {
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        }

        base.OnActionExecuted(actionExecutedContext);
    }
}

// At Controller
// GET api/values/5
[CrossDomainActionFilter]
public string Get(int id)
{
    return "value";
}

最後のオプションはMessageHandlerを使用することです:

public class CrossDomainMessageHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, 
        CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        response.Headers.Add("Access-Control-Allow-Origin", "*");

        return response;
    }
}
于 2012-10-22T20:02:54.027 に答える
0

ajax から別のドメインに情報を送信する場合は、jsonp を使用する必要があります (これは、post リクエストではなく get リクエストでのみ機能することに注意してください)。もう 1 つの方法 (両方のドメインを制御している場合) は、ARR (アプリケーション リクエスト ルーティング) を使用してブラウザーをだましてリクエストがローカルであると認識させ、ARR を使用してリクエストを別のドメインに書き換えます。この手法を使用すると、通常のように単純な ajax の get と post を使用できます。

于 2012-10-22T19:18:32.280 に答える