I'm trying to write a WCF service to respond to ajax requests, but I'm getting a strange error when it tries to deserialize.
Here's the jQuery:
$.ajax({
type: 'POST',
url: 'http://localhost:4385/Service.svc/MyMethod',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({folder:"test", name:"test"})
});
Here's the WCF service definition:
[OperationContract]
[WebInvoke(UriTemplate = "/MyMethod",
Method = "*", //Need to accept POST and OPTIONS
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string[] MyMethod(string folder, string name);
I get a SerializationException
saying: "The OperationFormatter could not deserialize any information from the Message because the Message is empty (IsEmpty = true)."
It occurs in method System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.DeserializeRequest
on instruction 00000108 mov dword ptr [ebp-18h],0
I don't see what I'm doing wrong, but it refuses to work for me. Been fighting this all day. Any ideas?
Got it--the answer was staring right at me in the only comments in my code. I needed to accept both POST and OPTIONS (for CORS). The OPTIONS request was coming first, and of course the OPTIONS request comes with no data attached. That was what was causing the parse exception; and the POST never even happened.
The workaround: separate out the POST and OPTIONS into two separate methods, with the same UriTemplate, but with different C# names (WCF requires this).
[OperationContract]
[WebInvoke(UriTemplate = "/MyMethod",
Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string[] MyMethod(string folder, string name);
[OperationContract]
[WebInvoke(UriTemplate = "/MyMethod", Method = "OPTIONS")]
void MyMethodAllowCors();
That actually cleans up the code a bit because you don't have to litter all your functions with
if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS") {
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, POST");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, User-Agent");
return new string[0];
} else if (WebOperationContext.Current.IncomingRequest.Method == "POST") { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With