1. ホーム
  2. asp.net

[解決済み] ASP.NET MVC/WebAPIアプリケーションでHTTP OPTIONS動詞をサポートする方法

2023-07-02 23:02:31

質問

MVC 4/Web API テンプレートで始まる ASP.NET Web アプリケーションをセットアップしました。物事は本当にうまくいっているように見えます - 私が認識している問題はありません。私はChromeとFirefoxを使用して、サイトを通過させました。Fiddler を使用してテストしたところ、すべての応答が適切であるように見えました。

そこで、この新しい Web API を使用するための簡単な Test.aspx を書き進めます。スクリプトの関連する部分です。

<script type="text/javascript">
    $(function () {

        $.ajax({
            url: "http://mywebapidomain.com/api/user",
            type: "GET",
            contentType: "json",
            success: function (data) {

                $.each(data, function (index, item) {

                    ....

                    });
                }
                );

            },
            failure: function (result) {
                alert(result.d);
            },

            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("An error occurred, please try again. " + textStatus);
            }

        });

    });
</script>

これはREQUESTヘッダを生成します。

OPTIONS http://host.mywebapidomain.com/api/user HTTP/1.1
Host: host.mywebapidomain.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://mywebapidomain.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type
Connection: keep-alive

そのままでは、Web APIは405 Method Not Allowedを返します。

HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 13:28:12 GMT
Content-Length: 96

<Error><Message>The requested resource does not support http method 'OPTIONS'.</Message></Error>

Web APIコントローラでは、OPTIONS動詞はデフォルトでは配線されていないことは理解しているのですが...。そこで、UserController.csに以下のコードを配置しました。

// OPTIONS HTTP-verb handler
public HttpResponseMessage OptionsUser()
{
    var response = new HttpResponseMessage();
    response.StatusCode = HttpStatusCode.OK;
    return response;
}

...そして、これは405 Method Not Allowedエラーを排除しましたが、レスポンスは完全に空です - データが返されません。

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 12:56:21 GMT
Content-Length: 0

追加ロジックがあるはずなのですが...。Optionsメソッドを適切にコーディングする方法がわからないし、コントローラがそのコードを置くのに適切な場所かどうかもわからない。Web API サイトが Firefox または Chrome から表示されたときに適切に応答するにもかかわらず、上記の .ajax 呼び出しがエラーになるのは(私にとって)奇妙なことです。.ajaxコード内の"preflight"チェックはどのように処理すればいいのでしょうか?クライアント側の.ajaxロジックでこの問題に対処すべきなのでしょうか?または、OPTIONS動詞を処理しないことによるサーバー側の問題である場合。

どなたか助けていただけませんか。これは非常に一般的な問題であるはずで、ここで回答されているのであれば申し訳ありません。検索してみましたが、役立つ回答は見つかりませんでした。

UPDATE IMHOは、これはクライアントサイドの問題であり、上記のAjax JQueryコードに関係していると考えています。私がこれを言うのは、ウェブ ブラウザから mywebapidomain/api/user にアクセスしたときに、Fiddler が 405 エラー ヘッダーを表示しないためです。この問題を再現できるのは、JQueryの.ajax()コールだけです。また、上記の同一のAjax呼び出しは、サーバー(同じドメイン)上で実行されたときに正常に動作します。

別の投稿を見つけました。 プロトタイプの AJAX リクエストが GET ではなく OPTIONS として送信され、501 エラーが発生する。 という投稿があり、それに関連しているようですが、その提案をいじってみましたが、成功しませんでした。どうやら、JQuery は、Ajax リクエストがクロスドメインの場合(私の場合はそうです)、OPTIONS ヘッダーを何らかの形でトリガーするいくつかのヘッダーを追加するようにコード化されているようです。

'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,

JQueryのコアコードを修正するよりも、もっと良い解決策が利用できるはずだと思うのですが...。

以下に提供される回答は、これがサーバー側の問題であると仮定しています。たぶん、そうだと思いますが、私はクライアント側に傾いており、ホスティング プロバイダーに電話しても解決しないでしょう。

どのように解決するのですか?

Daniel A. White 氏がコメントで述べているように、OPTIONS リクエストは、クロスドメイン JavaScript リクエストの一部としてクライアントによって作成される可能性が最も高いと思われます。これは、Cross Origin Resource Sharing (CORS) に準拠したブラウザーによって自動的に実行されます。このリクエストは予備的な、あるいは プリフライト リクエストは、実際の AJAX リクエストの前に行われ、どのリクエスト動詞とヘッダーが CORS でサポートされるかを判断します。サーバーは、HTTP 動詞のいずれか、すべて、または一部について CORS をサポートするよう選択することができます。

この図を完成させるために、AJAX リクエストには追加の "Origin" ヘッダーがあり、JavaScript をホストしている元のページがどこから提供されたかを識別します。サーバーはどのオリジンからのリクエストもサポートするか、または既知の信頼できるオリジンのセットだけをサポートするかを選択することができます。任意のオリジンを許可すると、クロスサイトリクエストフォージェリ (CSRF) のリスクが高まるため、セキュリティ上のリスクがあります。

したがって、CORS を有効にする必要があります。

ASP.Net Web API でこれを行う方法を説明したリンクはこちらです。

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

そこで説明されている実装では、特に以下を指定することができます。

  • アクション単位、コントローラ単位、またはグローバル単位での CORS サポート
  • 対応する原産地
  • コントローラまたはグローバルレベルで CORS を有効にする場合、サポートされる HTTP verbs は以下のとおりです。
  • サーバーがクロスオリジンリクエストでクレデンシャルの送信をサポートしているかどうか。

一般に、これは問題なく動作しますが、特にどのドメインからのクロスオリジンリクエストも許可する場合は、セキュリティリスクを認識していることを確認する必要があります。これを許可する前に、非常に慎重に考えてください。

どのブラウザが CORS をサポートしているかという点では、Wikipedia によると、以下のエンジンがサポートしているとのことです。

  • Gecko 1.9.1 (FireFox 3.5)
  • WebKit (Safari 4, Chrome 3)
  • MSHTML/Trident 6 (IE10) IE8と9で部分的にサポートされています。
  • プレスト(オペラ12番)

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support