Reputation: 133
I'm trying to make a WCF service with CORS calls, so far, I have my server with the classes indicated here: http://enable-cors.org/server_wcf.html
I was able to make a call with a jQuery ajax call using the verb GET without any parameters, the problem comes when I try to pass parameters to my request, here's my code:
Interface markup:
[OperationContract]
[WebInvoke(Method = "*",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetData(TestClass value);
Method markup:
public string GetData(TestClass value)
{
return value.Id.ToString();
}
js markup:
var value = {
Id : "2",
Name: "qwe"
};
$.ajax({
url: "http://localhost:38733/Service1.svc/GetData",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ value: value }),
success: function(result) {
console.log(result);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
But if I debug, I always get null, meaning that the parameter is not being passes to the method, I also got POST http://localhost:38733/Service1.svc/GetData 400 (Bad Request)
on Chrome console.
What am I doing wrong?
UPDATE
Web.config markup:
<behavior name="jsonBehavior">
<webHttp />
<crossOriginResourceSharingBehavior />
</behavior>
<extensions>
<behaviorExtensions>
<add name="crossOriginResourceSharingBehavior"
type="WCFSecureService.EnableCrossOriginResourceSharingBehavior, WCFSecureService, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
<services>
<service name="WCFSecureService.Service1">
<endpoint address=""
binding="webHttpBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
On the Google Chrome Console I'm getting the following:
OPTIONS http://localhost:38733/Service1.svc/GetData?value=5
UPDATE
It works if I make a request to a method without any parameters
UPDATE
Fiddler 2 is showing me this, so I don't know what I'm doing wrong...
UPDATE
TestClass markup:
[DataContract]
public class TestClass
{
private int id;
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
[DataMember]
public int Id
{
get { return id; }
set { id = value; }
}
}
UPDATE
If I use JSON.stringify({ value: value })
and BodyStyle = WebMessageBodyStyle.Bare
I reach the server, but I got all properties with 0, check the next image:
Upvotes: 2
Views: 239
Reputation: 133
I've found a solution for my case. At the end this was a test, so I'm gonna be using more that just one parameter so this is what I've learn:
WebInvoke
has to be BodyStyle =
WebMessageBodyStyle.WrappedRequest
.On the client side, for just one parameter, using JSON.stringify(value)
it's ok, but for more than one, you have to be more specific, for example:
data: JSON.stringify({
value: value,
text: "any text"
});
On the link I provide on my question, I have to included two clases
CustomHeaderMessageInspector
and
EnableCrossOriginResourceSharingBehavior
, it seems that they are
not longer needed if you can make use of a global.asax file, you
just have to add the following code to Application_BeginRequest:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
And my web.config
end it up like this:
<bindings>
<webHttpBinding>
<binding name="Binding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="corsBinding" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<services>
<service name="WCFSecureService.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="bs" binding="basicHttpBinding" contract="WCFSecureService.IService1" />
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration="corsBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="jsonBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
Thanks for your helps and I hope it helps someone else out there.
Upvotes: 1
Reputation: 15185
In your service contract you might want to put an optional WebGet
directive.
[WebGet(UriTemplate = "GetData/{value}")]
string GetData(int value);
Another thing to look for is that you have a json
behavior defined for your enpoint in the web.config.
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
<behavior name="xmlBehavior">
<webHttp defaultOutgoingResponseFormat="Xml"/>
</behavior>
</endpointBehaviors>
NOTE: If you are using behaviors and then you need to specify the format in the following manner
http://localhost:38733/Service1.svc/json/GetData/5
or
http://localhost:38733/Service1.svc/xml/GetData/5
Also, could you try this js instead:
var _data= {
value:5
};
$.ajax({
...
data: _data,
success: function(data) {
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
Or conversely:
$.ajax({
url: "http://localhost:38733/Service1.svc/json/GetData/5",
});
Upvotes: 1