Monday, April 29, 2013

WCF, Ajax and jQuery Mobile with code example

Few days back I started working in jQuery mobile and HTML. Although not new to coding (have good experience in asp.net, javascript, css, etc.) but jQuery is something new to me as I have been working for many years now on silverlight. Anyway, I started jquery mobile and noticed it's not a piece of cake to make my code work. Here are few problems and solution that I found to make my jquery work with my WCF service.

I am using visual studio 2010 to create WCF service and using standard HTML page to communicate with WCF service. I will start with the WCF Service:
Service contract:

[OperationContract]

[WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]

bool HelloWorld(string message);


Some of the code will look familiar if you know WCF (which I am hoping you know), like OperationContract, ServiceContract, etc..

WebInvoke defines that your service operation is an invoke operation that could be called through your WCF REST. WebInvoke allows any type of method, that is, GET/POST/PUT/DELETE. There are other properties like RequestFormat, ResponseFormat which are self explanatory. 
BodySyle defines how data should be sent back to client, either it should be wrapped (in XML) or bare.

Open up the markup of your service (.svc file) and add factory attribute to it
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
This will automatically add endpoints to your service. This should be all at your service end.

Let's get started with jQuery ajax call. Create any HTML page and write this code:


           $(function () {
                $('#btnCallService').click(function () {
                     Type = "POST";
                     Url = "http://localhost/BlogService/Service1.svc/HelloWorld";
                     DataType = "json";
                     ContentType = "application/json";
                     $.ajax({
                           type: Type,
                           url: Url,
                           contentType: ContentType,
                           dataType: DataType,
                           processdata: false,
                           success: function (msg) {
                                if (msg.d != "") {
                                     $("#dvReturnData")[0].innerHTML = msg.d;
                                }
                           },
                           error: ServiceFailed
                     });
                });


Please note, i am using code directly from my code example so button name and service call are hard coded. 

Deciphering this code shouldn't be a problem if you know jQuery. Here, i am making a simple ajax call using POST method and REST method. Most of the code is pretty simple and self explanatory. For call to service that is all you need.

Soon enough you will be facing this error: 405 Method Not Allowed. This error is related to CORS, i will not go into details of what and why. Overcoming this issue in IE is pretty simple, just add these lines in your jquery:



           $('document').ready(function () {
                jQuery.support.cors = true;
           });


Unfortunately, this doesn't resolve the issue in other browser, like Chrome and FF, they still spew their "405 Method not found" error. The simplest way to resolve was to add support through web.config (since i am using WCF). 

     <system.webServer>
           <httpProtocol>
                <customHeaders>
                    
                     <add name="Access-Control-Allow-Origin" value="*" />
                     <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization, Accept, X-Requested-With" />
                     <add name="Access-Control-Allow-Methods" value="OPTIONS, TRACE, GET, HEAD, POST, PUT" />
                </customHeaders>
           </httpProtocol>
     </system.webServer>

This should get your WCF service working with your jquery Ajax. You can find the complete code sample here. Sample code has calls through POST method and calls are made to both param and without param methods.

Please note, if you run my sample code host the webservice in IIS otherwise it wouldn't work.

No comments: