クライアントとサーバーが異なるポートで実行されています。サーバーは実行中ですWeb API 2(v5.0.0-rc1)。
Microsoft ASP.NET Web APIクロスオリジンサポートパッケージ をインストールしてみて、WebApiConfig.cs
で有効にしました。 EnableCors()
関数が提供されるため、パッケージは正しくインストールされました。
ここで、WebApiConfig.cs
で私のRegister()
関数を見ることができます:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
GET
リクエストは正常に機能します。しかし、POST
を送信すると、次のメッセージが表示されます。
OPTIONS http://localhost:19357/api/v1/rooms? 404 (Not Found) angular.js:10159
OPTIONS http://localhost:19357/api/v1/rooms? Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin. angular.js:10159
XMLHttpRequest cannot load http://localhost:19357/api/v1/rooms. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin.
Fiddlerによると、OPTIONS
リクエストのみを送信します。その後POST
を発行しません。
WebApiConfig.cs
のconfig.EnableCors(cors);
は何もしていないと推測しているため、サーバーがPOST
リクエストの送信をクライアント/ブラウザに拒否します。
この問題を解決する方法はありますか?
EDIT 05.09.13これは5.0.0-rtm-130905で修正されました
私は間違いなく この問題 属性ルーティングでヒットしています。 問題 は 修正済み 5.0.0-rtm-130905の時点でした。しかし、それでも nightly builds を試すことができますが、これは間違いなく修正されます。
NuGetパッケージソースにナイトリーを追加するには、Tools -> Library Package Manager -> Package Manager Settings
に移動し、Package Sources
の下に次のURLを追加します。 http://myget.org/F/aspnetwebstacknightly
CORSはMicrosoft.AspNet.WebApi.Cors
バージョン5.2.2で完全に機能します。次の手順は、CORSを私にとって魅力のように構成しました。
Install-Package Microsoft.AspNet.WebApi.Cors -Version "5.2.2"
//パッケージマネージャーコンソールから実行Global.asaxで、次の行を追加します。任意のMVCルート登録前
GlobalConfiguration.Configure(WebApiConfig.Register);
WebApiConfig
Registerメソッドに、次のコードがあります。
public static void Register(HttpConfiguration config)
{
config.EnableCors();
config.MapHttpAttributeRoutes();
}
Web.configでは、次のハンドラーがパイプラインの最初のハンドラーである必要があります。
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
ApiController
から派生したコントローラーで、EnableCorsAttribute
を追加します。
[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
[RoutePrefix("")]
public class MyController : ApiController
これでうまくセットアップできます!
パッケージをインストールする必要はありませんでした。 WebAPIプロジェクトのweb.configを少し変更するだけでうまく機能します。
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
HTTPS経由でWebAPIにアクセスしていることを確認してください。
また、WebApi.configでcorsを有効にしました。
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
しかし、HTTPS URLを使用するまで、CORS要求は機能しませんでした。
将来の参照のための遅い返信。私のために働いていたのは、nugetによってそれを有効にしてから、web.configにカスタムヘッダーを追加することでした。
DelegatingHandler
を使用してメッセージパイプラインをインターセプトした場合、[EnableCors()]
アプローチを使用した参照は機能しません。私の場合、リクエストのAuthorization
ヘッダーをチェックし、ルーティングが呼び出される前にそれに応じて処理していました。つまり、リクエストはパイプラインの早い段階で処理されるため、[EnableCors()]
は効果がありません。
最後に例が見つかりました CrossDomainHandler
class( shaunx for Gist ) パイプラインでCORSを処理し、それを使用するのは、パイプラインに別のメッセージハンドラーを追加するのと同じくらい簡単です。
public class CrossDomainHandler : 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<HttpResponseMessage> 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);
}
}
}
使用するには、登録済みメッセージハンドラーのリストに追加します
config.MessageHandlers.Add(new CrossDomainHandler());
ブラウザによるプリフライトリクエストはすべて処理されて渡されます。つまり、コントローラに[HttpOptions]
IHttpActionResult
メソッドを実装する必要はありませんでした。
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
var constraints = new {httpMethod = new HttpMethodConstraint(HttpMethod.Options)};
config.Routes.IgnoreRoute("OPTIONS", "*pathInfo",constraints);