Ich versuche, POST -Anfragen von meiner bei localhost gehosteten Javascript-App an einen WCF-REStful-Dienst zu erlauben, der an einem anderen Port gehostet wird, aber irgendwie funktioniert es nicht. Ich habe versucht, dem Header benutzerdefinierte Eigenschaften hinzuzufügen, und zwar programmgesteuert in die JSONData
-Methode meines Services, aber in meiner Antwort wird immer noch die "405-Methode nicht zulässig" angezeigt. Was ist der richtige Ansatz hier?
Das ist meine Schnittstelle:
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
}
}
und den Servicecode:
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();
}
}
Und zum Schluss noch die config:
<?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>
Das hat für mich besser funktioniert als die Web.config-Version:
Erstellen Sie einen Global.asax
Fügen Sie diese Methode dem Global.asax.cs
hinzu:
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();
}
}
}
}
Fügen Sie diese Knoten zu Ihrer Web.config hinzu:
<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>
Das Aktivieren von CORS für Nicht-GET-Anforderungen erfordert mehr als nur das Festlegen des Access-Control-Allow-Origin
-Headers. Außerdem muss mit preflight -Anfragen gearbeitet werden. Hierbei handelt es sich um OPTIONS
-Anforderungen, mit denen der Server gefragt wird, ob Operationen ausgeführt werden können, die möglicherweise Daten ändern können (z. B. POST, PUT, DELETE), bevor die aktuelle Anforderung gesendet wird.
Ich habe einen Blogbeitrag über das Hinzufügen von CORS-Unterstützung für WCF geschrieben. Dies ist nicht die einfachste der Implementierungen, aber hoffentlich kann der Code im Beitrag einfach in Ihr Projekt kopiert/eingefügt werden. Der Beitrag kann unter http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx - gefunden werden.
Der folgende .NET-Code (global.asax) hat den wichtigen Unterschied, dass es anstelle von * besser ist, die Ursprungsdomäne zurückzusetzen, da dies die Authentifizierung über CORS (z. B. NTLM/Kerberos) sowie das Preflight ermöglicht.
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" , "*");
}
}