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=".Services.Items" xmlns:i="">
<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>
<?xml version="1.0" encoding="utf-16"?>
<Content>
<SpecialContent />
</Content></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 ments 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?
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/2004/07/Contodo.Services.Items" xmlns:i="http://www.w3/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>
<?xml version="1.0" encoding="utf-16"?>
<Content>
<SpecialContent />
</Content></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 ments 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?
Share Improve this question edited May 6, 2013 at 9:20 bitbonk asked May 3, 2013 at 21:32 bitbonkbitbonk 49.7k39 gold badges198 silver badges282 bronze badges 5- jQuery AJAX calls to a WCF REST Service – Andreas Commented May 3, 2013 at 21:40
- That example describes how to do it in JSON, but I have the XML problem. – bitbonk Commented May 3, 2013 at 21:43
-
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 Commented May 3, 2013 at 21:49 - 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 Commented May 6, 2013 at 7:50
-
@bitbonk: You don't mented 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 Commented May 13, 2013 at 8:14
5 Answers
Reset to default 4 +250I 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 bine 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.
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
Check out WcfRestContrib. Also this answer might help you.
Fist of all did you look at http://www.codeproject./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./Articles/327420/WCF-REST-Service-with-JSON
If you are using jQuery, you can use the $.get function (http://api.jquery./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./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.