Here is a complete example of using wcf and ajax via JQuery, the configuration for wcf under ssl is also included.
Client : javascript code
<script type="text/javascript"> $(document).ready(function () { var userid = { 'id': 1 }; $.ajax({ type: 'GET', //GET or POST or PUT or DELETE verb url: 'Service.svc/GetPerson', // Location of the service data: userid, //Data sent to server contentType: 'application/json; charset=utf-8', // content type sent to server dataType: 'json', //Expected data format from server processdata: true, //True or False success: function (data) {//On Successfull service call alert(data.Name); }, error: function (msg) {// When Service call fails alert(msg); } }); var user = { id: 2, name: 'John Smith' }; $.ajax({ type: 'POST', //GET or POST or PUT or DELETE verb url: 'Service.svc/SavePerson', // Location of the service data: JSON.stringify(user), //Data sent to server contentType: 'application/json; charset=utf-8', // content type sent to server dataType: 'json', //Expected data format from server processdata: true, //True or False success: function (data) {//On Successfull service call alert(data); }, error: function (msg) {// When Service call fails alert(msg); } }); }); </script>
It is using JQuery.ajax, when using POST, it must be stringfied as JSON string, rather than javascript object, when it is sent as an object you will get error:
The server encountered an error processing the request. The exception message is ‘The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation ‘xxxxx’. Encountered unexpected character ‘x’.’.
Try not to use JQuery.get() or JQuery.post() as they are special cases of JQuery.ajax, and does not allow you change content type or add error handlings. As default the content type for JQuery.post is “application/x-www-form-urlencoded; charset=UTF-8″
Server: service code
[ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] [ServiceBehaviorAttribute(IncludeExceptionDetailInFaults = true)] public class Service { [OperationContract] [WebInvoke( Method = "GET", ResponseFormat = WebMessageFormat.Json)] public Person GetPerson(int id) { return new Person { ID = id.ToString(), Name = "John Smith" }; } [OperationContract] [WebInvoke( Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)] public string SavePerson(int id, string name) { return name + "-" + id.ToString(); } } [DataContract] public class Person { [DataMember] public string ID { get; set; } [DataMember] public string Name { get; set; } }
When using POST method, BodyStyle should use WrappedRequest only, otherwise the result could be wrapped by method name.
Enable logging using diagnostics
<configuration> <system.diagnostics> <sources> <source name="System.ServiceModel" switchValue="Error"> <listeners> <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData= "Traces.svclog" /> </listeners> </source> </sources> </system.diagnostics> </configuration>
switchValue can enable logging on different level
initlializeData is the file name
Choose which binding of wcf to use for ajax
webHttpBinding : is the REST-style binding, where you basically just hit a URL and get back a truckload of XML or JSON from the web service
This is used by Ajax calls, as other two types are SOAP based
basicHttpBinding and wsHttpBinding are two SOAP-based bindings which is quite different from REST.
Services of these two bindings cannot be consumed by ajax
For WCF through none ssl aka http:
<system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="EndPointBehavior"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <services> <service behaviorConfiguration="ServiceBehavior" name="Service"> <endpoint address="" binding="webHttpBinding" contract="Service" behaviorConfiguration="EndPointBehavior"/> </service> </services> </system.serviceModel>
So ajax will get an object like:
{“ID”:”1″,”Name”:”John Smith”}
You might use
{“d”:{“__type”:”Person:#”,”ID”:”1″,”Name”:”John Smith”}}
Eanble ssl between wcf and ajax
<system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <bindings> <webHttpBinding> <binding name="TransportSecurity"> <security mode="Transport"> </security> </binding> </webHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpsGetEnabled="true" /> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="EndPBehavior"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <services> <service name="Service" behaviorConfiguration="ServiceBehavior"> <endpoint address="" binding="webHttpBinding" behaviorConfiguration="EndPBehavior" bindingConfiguration="TransportSecurity" contract="Service"/> </service> </services> </system.serviceModel>
This will enable wcf to be hosted on https, and client side does not need any change to just consume them.
Enable SSL on localhost@IIS
Create a server certificate under IIS server/ IIS
Create a site under the root ‘Sites’ IIS server/Sites
Site binding: https, port:443, and SSL certificate : select a certificate
SSL settings for this site: enable require SSL
Have fun.