1

How do I invoke a Service Operation in WCF from iOS?

I have a Service Operation defined in my WCF Data Service (tied to a stored procedure in my DB schema) that I need to invoke from iOS. Say I've got the following declaration in my .svc.cs file:

[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public IQueryable<Foo> GetFoos(int param1, DateTime param2, string param3)
{
  return CurrentDataSource.GetFoos(param1, param2, param3).AsQueryable();
}

And I've got it set up with the proper rights in InitializeService:

config.SetServiceOperationAccessRule("GetFoos", ServiceOperationRights.AllRead);

When I try to invoke this via HTTP POST from iOS, I get back an error wrapped in JSON:

Bad Request - Error in query syntax.

It seems like it doesn't like how I'm passing my parameters. I'm passing them JSON-encoded (using NSJSONSerialization to turn an NSDictionary into a JSON string) in the request body of a POST request. The same method works on another web service (.svc) not connected to WCF that has operations annotated the same way.

An answer to another question of mine in a similar vein suggests that data formats can be negotiated between client and server, and I've read that dates are a pain to format, so maybe it's my DateTime parameter that's a problem. But I've tried both the JSON format (\/Date(836438400000)\/ and /Date(836438400000)/) and the JSON Light format (1996-07-16T00:00:00) to no avail.

So my question is this: what is the proper way to invoke this operation? If I need to have my app tell the server what format to expect, how do I do that?

Update: I tried using the format datetime'1996-07-16T00:00:00' as mentioned in this question. Same error.

Update 2: The MSDN page for Service Operations seems to suggest that nothing besides Method = "POST" is supported when annotating the WebInvoke for a Service Operation. I tried removing everything from what is quoted in the above code and setting the method to POST. Same error.

Update 3: On Pawel's suggestion, I made a new Service Operation on my Data Service just like this:

[WebInvoke(Method = "POST")]
public IQueryable<string> GetFoos()
{
    List<string> foos = new List<string>();
    foos.Add("bar");
    return foos.AsQueryable();
}

I was able to make it work in Fiddler's Composer pane by setting the method to POST, adding accept:application/json;charset=utf-8 and Content-Length:0 to the headers. Then I added a single int parameter to the operation (called param1). I set the body of my request in Fiddler to {"param1":"1"} and ran it (and Fiddler automatically updated my content-length header), and got the same error. I changed the type of my parameter to string and ran my request again and it worked. So my problem seems to be non-string types.

Community
  • 1
  • 1
Tom Hamming
  • 10,577
  • 11
  • 71
  • 145
  • I would try invoking an operation that does not take any parameters to isolate whether this is a general problem or a problem caused by DateTime parameters... – Pawel Sep 27 '12 at 21:37
  • @Pawel - I'll try that. Should WCF Service Operations work the same way as operations on vanilla WCF services would in general? – Tom Hamming Sep 27 '12 at 21:55
  • It's been a couple years since I looked at it but you are using POST and parameters will be sent in the request body. Therefore I suspect Content-Length cannot be 0 but has to be the actual length of the request. – Pawel Sep 27 '12 at 22:26
  • @Pawel - When you put something in Fiddler's request body, it automatically changes the content-length parameter for you. No worries there. – Tom Hamming Sep 27 '12 at 22:27
  • Actually taking it back - can you send parameters in the URL? I found this thread http://social.msdn.microsoft.com/Forums/en-AU/adodotnetdataservices/thread/40a1d8a2-c0d7-45ff-88a0-ce8697b37155 (it just showed up when searching not a self promotion ;) ) – Pawel Sep 27 '12 at 22:29
  • @Pawel - Interesting. I had hoped to do it in the body because then `NSJSONSerialization` handles the formatting for me. I'll try passing them in the URL. Though, given that post, it shouldn't have taken my string argument from the body either... – Tom Hamming Sep 27 '12 at 22:32
  • @Pawel - Changing the `WebInvoke` to `WebGet` and putting my parameters in the URL worked, using the date format `datetime'1996-07-16T00:00:00'`. I'll just go that route. Though I'm still curious why WCF Data Services takes string parameters and nothing else from POST request bodies, while plain WCF services are happy to take whatever from the body. Probably an issue not visible to an armchair engineer like me. :-) If you post a quick explanation and a link to that answer on MSDN, I'll mark you as the answer. – Tom Hamming Sep 27 '12 at 22:48

1 Answers1

0

You need to send parameters in the Url and not in the request body.

Pawel
  • 31,342
  • 4
  • 73
  • 104