Calling Service Operations Using POST

As you may know, OData enables you to define service operations that can be invoked by using either GET or POST requests. The topic Service Operations (WCF Data Services) shows how to define both kinds of service operations using WCF Data Services. Consider the following POST service operation that returns customer names as a collection of strings:

[WebInvoke(Method = "POST")]
public IEnumerable<string> GetCustomerNames()
{
// Get the ObjectContext that is the data source for the service.
NorthwindEntities context = this.CurrentDataSource;

    var customers = from cust in context.Customers
orderby cust.ContactName
select cust;

    foreach (Customer cust in customers)
{
yield return cust.ContactName;
}
}

As we mention in the topic Calling Service Operations (WCF Data Services), you can’t use the WCF Data Service client methods to access such an endpoint because POST requests are only sent by the client library when saving changes. This means that we need to use another web client API to call this service operation and manually consume the response in our application.

The following example uses HttpWebRequest/HttpWebResponse to call the GetCustomerNames service operation using a POST request and XDocument to access elements in the response document:

HttpWebRequest req =
(HttpWebRequest)WebRequest
.Create("https://myservice/Northwind.svc/GetCustomerNames");

// Use a POST to call this service operation.
req.Method = "POST";

// We need to set to this zero to let the service know
// that we aren't including any data in the POST.
req.ContentLength = 0;

using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
{
// Load the response into an XDocument.
XDocument doc = XDocument.Load(resp.GetResponseStream());

    // Get each child 'element' in the root 'GetCustomerNames' element,
// which contains the returned names.
foreach (XElement name in doc.Root.Descendants())
{
Console.WriteLine(name.Value);
}
}

Cheers!

Glenn Gailey

Comments

  • Anonymous
    June 23, 2011
    I have a service method that uses [WebInvoke(Method = "POST")] I am trying to post some form data to the method, how to I access the incoming post values form within the method body!

  • Anonymous
    July 03, 2011
    The comment has been removed

  • Anonymous
    July 05, 2011
    OK, I have a new post up that describes how to send data to a service operation (which paradoxically must be a GET request): Uploading Data to a Service Operation (blogs.msdn.com/.../uploading-data-to-a-service-operation.aspx). Thanks for asking the question. -Glenn

  • Anonymous
    August 07, 2011
    Why should I use POST to GET customer names? I'd rather call GET ~/Customers?$select=name. The difficulty we have in finding good examples for using service operations seems to indicate that we will rarely need them :-)

  • Anonymous
    August 08, 2011
    Yes, keeping the method name of a POST operation as "Get.." was probably a bad idea and confusing. Sorry for that. The point is that you can define service operations that are called by an HTTP POST request, but then you are probably trying to insert data anyway. I agree with you that service operations are not intended to be the primary OData APIs, but rather just to handler certain edge cases encountered when using the data service. (Also, the WCF Data Services client doesn't have good support for calling service operations.)  If you want to have operation-based instead of model-based access to your data, you might be better off with plain ol' WCF or WCF REST (HTTP) APIs. Cheers, Glenn.