POST localhost:80でホストされているjavascriptアプリから、別のポートでホストされているWCF REStfulサービスへのリクエストを許可しようとしていますが、どういうわけか機能しません。追加しようとしましたカスタムプロパティをヘッダーに追加し、サービスのJSONData
メソッドにプログラムで追加しましたが、応答で「405メソッドは許可されていません」がまだ表示されます。ここでの適切なアプローチは何ですか?
これは私のインターフェースです:
namespace RestService
{
public class RestServiceImpl : IRestServiceImpl
{
#region IRestServiceImpl Members
public string JSONData()
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
return "Your POST request";
}
#endregion
}
}
そしてサービスコード:
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web.Script.Services;
namespace RestService
{
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
[ScriptMethod]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "export")]
string JSONData();
}
}
そして最後に設定:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<endpoint address ="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
これは、Web.configバージョンよりもうまく機能しました。
Global.asax
を作成する
このメソッドをGlobal.asax.cs
に追加します。
using System.Web;
namespace StackOverflow
{
public class Global : System.Web.HttpApplication
{
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
}
}
これらのノードをWeb.configに追加します。
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
<add name="Access-Control-Max-Age" value="1728000" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
非GETリクエストに対してCORSを有効にするには、Access-Control-Allow-Origin
ヘッダーを設定するだけでは不十分です。これは、preflightリクエストも処理する必要があるため、OPTIONS
リクエストは、実際のリクエストが送信される前に、データを変更する可能性のある操作(POST、PUT、DELETEなど)を実行しても安全かどうかをサーバーに尋ねます。
WCFに対するCORSサポートの追加に関するブログ投稿を作成しました。これは最も単純な実装ではありませんが、うまくいけば、投稿のコードをプロジェクトに単にコピー/貼り付けることができます。投稿は http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx にあります。
次の.NETコード(global.asax)には、*ではなく、Originドメインをエコーバックすることが重要な違いがあります。これにより、CORS(NTLM/Kerberosなど)およびプリフライトを介した認証が可能になるためです。
void Application_BeginRequest(object sender, EventArgs e)
{
if (Request.HttpMethod == "OPTIONS")
{
Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
Response.AddHeader("Access-Control-Max-Age", "1728000");
Response.End();
}
else
{
Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (Request.Headers["Origin"] != null)
Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]);
else
Response.AddHeader("Access-Control-Allow-Origin" , "*");
}
}