4
votes

I have a WPF application that exposes a REST WCF service (via WebServiceHost) with a contract that looks something like this (simplified):

[ServiceContract]
public interface IItemServiceContract
{
    [WebGet(UriTemplate = "Items/{id}")]
    Item GetItem(string id);

    [WebGet(UriTemplate = "Items")]
    IEnumerable<Item> GetItems();

    [WebInvoke(UriTemplate = "Items", Method = "PUT")]
    IEnumerable<Item> CreateItems(IEnumerable<Item> list);
}

When I navigate to http://localhost:8070/Contoso/Services/Items/ItemService/Items with a browser, I get a response that looks something like this:

<ArrayOfItem xmlns="http://schemas.datacontract.org/2004/07/Contodo.Services.Items" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <ItemState>
      <Comment i:nil="true"/>
      <DeactivationTime>0001-01-01T00:00:00</DeactivationTime>
      <Id>18f1a5e4-a94a-4f37-a533-3a75a10e7373</Id>
      <IsSpecial>false</IsSpecial>
    </ItemState>
    <ItemTypeId>10</ItemTypeId>
    <HelpInfo/>
    <Identity>Ident1</Identity>
    <AdditionalInfo>
      &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;
      &lt;Content&gt;
        &lt;SpecialContent /&gt;
      &lt;/Content&gt;</AdditionalInfo>
    <TextParameter>kjhdfsjh kj dkfjg kj</TextParameter>
    <UserName i:nil="true"/>
  </Item>
</ArrayOfItem>

What would be an easy and friction-free approach to consume this service with JavaScript? How can a client quickly build the http requests and the appropriate XML for it?

I am fairly in the Html5/javaScript world but in a C# I would have an API in place that is centered around the Item object that gets serialized to XML. But is that the way to go for here?

Update:

Based on the first comments and answers, it seems that XML is not the ideal format for a JavaScript/webbrowser consumer but I can't just change the format to JSON because that would probably break existing clients that already rely on this XML format. So ideally I would do REST content type negotiation and put/get JSON or XML. But can this be done with WCF REST services?

5
That example describes how to do it in JSON, but I have the XML problem. - bitbonk
It looks like you can change the source of the webservice. So why don't you add the JSON response to it as it is done in the tutorial I've linked (WebInvoke(Method="POST",ResponseFormat=WebMessageFormat.Json)? - Andreas
That would break existing clients. I either need to find a way to do content type negotiation or I guess I'd have to add new URLs for JSON. - bitbonk
@bitbonk: You don't commented my answer. Do you use .NET 4.0/4.5? Do you tried to use automaticFormatSelectionEnabled setting? Do you have success or some problems in usage of WCF RESTful service which provides both XML and JSON depend on client requests? Do you need additional help? - Oleg

5 Answers

4
votes

I suppose that you use ASP.NET 4.X.

WCF 4 supports automatic format selection based on HTTP "Accept" and "Content-Type" headers of requests. One specify automaticFormatSelectionEnabled="true" attribute in web.config file:

<configuration>
  <system.serviceModel>
    <standardEndpoints>
      <webHttpEndpoint>
        <!-- the "" standard endpoint is used for auto creating a web endpoint. -->
        <standardEndpoint name=""
                          helpEnabled="true"
                          automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>

See "Message Format Selection" part of the article and the article for more information. You can combine automaticFormatSelectionEnabled attribute with defaultOutgoingResponseFormat (which you can set to "xml" or "json", default is already "xml"). You can specify the attributes only for one specific endpoint instead of usage standardEndpoint as in the example above.

So your existing WCF service will just provide JSON data for JavaScript requests and still returns XML data for other client if you would use the corresponding WCF configuration.

1
votes

Try this

For Json Type result

In InterFace

         [WebInvoke(Method = "POST", UriTemplate = "/ItemGetItem?id={id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        void  ItemGetItem(string id);

In Script

self.GetItem= function () {

         try {

             $.ajax({
                 type: "POST",
                 url: "Your Url",
                 contentType: 'application/json',
                 async: false,
                 dataType: 'json',
                 cache: false,
                 success: function (response) {




                 },
                 error: function (ErrorResponse) {


                 }

             });

         }

         catch (error) {


         }

     }

put endpoint of client application to consume this service

1
votes

Check out WcfRestContrib. Also this answer might help you.

0
votes

Fist of all did you look at http://www.codeproject.com/Articles/33234/A-beginner-s-guide-for-consuming-a-WCF-service-in

But the easiest way in my opinion is to change format to Json. There is also a good article on code project:http://www.codeproject.com/Articles/327420/WCF-REST-Service-with-JSON

0
votes

If you are using jQuery, you can use the $.get function (http://api.jquery.com/jQuery.get/) and specify "xml" as datatype:

$.get('http://.../', params, function(data) {
 //process data
}, 'xml');

If not, you need to use xmlHttpRequest directly (from http://www.w3schools.com/xml/xml_parser.asp) :

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
  }
  else
  {// code for IE6, IE5
     xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.open("GET",url,false);
  xmlhttp.send();
  xmlDoc=xmlhttp.responseXML;

Then traversing the xml node is fairly easy using the native javascript xml parser.

But JSON would be more appropriate. You could add a route for http://localhost:8070/Contoso/Services/Items/ItemService/Items.json which would return the result in JSON format. Or also add a parameter in the url. Both method will return JSON only if you explicitly ask for it. So the existing code which is using the xml response will still work fine.