Add to My Yahoo! | Google Reader or Homepage | Add to Windows Live | Add to Windows Live Alerts

Wictor Wilén

Microsoft Certified Master (MCM) - SharePoint 2010 | Microsoft Most Valuable Professional (MVP) - SharePoint Server MVP | Author

Calling a WCF Service using jQuery in SharePoint - the correct way

Posted at 2011-02-22 11:12 by Wictor Wilén in SharePoint 2010 with 9 comments.

Today an article was published on the SharePoint Developer Team Blog called Calling a WCF Service using jQuery. The content and purpose of the article is good and interesting but the way it is implemented can not be considered best practice and is definitely not the way we (I) teach SharePoint 2010 development. For instance this article manually registers assemblies in the Global Assembly Cache! Something that we never should do! It tells you to copy files to the virtual directory bin folder and into the Layouts folder! Ouch! Also, the article contains some plain ol' errors.

Since the content of the article is relevant I will show you how to do it - the correct way. I'll be using exactly the same code and sample but using the SharePoint 2010 Visual Studio templates and a WSP package to deploy the solution. So let's get going doing it the correct way:

1) Create the Visual Studio 2010 project

Instead of splitting this up into several (non-SharePoint) projects we would like to make the whole solution deployable as a WSP file.

We start this by creating a new Visual Studio 2010 project by using the Empty SharePoint project template. The project must be deployed as a Farm solution, since we're going to deploy stuff into the SharePoint Root.

2) Create the Data Access Layer

This is just as in the original article. Add a simple class to the project and implement the DAL. (You don't need to have a backing database, just make some objects when testing this solution).

3) Create the WCF Service

WCF ServiceTo create the WCF service we'll do it in a different way, compared to the original article. Add a new WCF Service project item to the project and name it ProductService.cs. This will add three files to the project; IProductService.cs, ProductService.cs and app.config. You can safely remove the app.config, we don't need it in this case.

Then implement IProductService.cs and ProductService.cs just as in the original article. Add references to Microsoft.SharePoint.Client.ServerRuntime.dll (found in GAC) and System.ServiceModel.Web.

The .svc file is added to the project by first adding a new SharePoint "Layouts" Mapped folder. Then add a simple text file project item to the layouts folder with the name ProductService.svc. We'll come back to this one in a bit. First we need to make sure that we can use the Visual Studio 2010 replaceable tokens in svc files. Unload the project file and add a new PropertyGroup to the project file like this:

Replaceable tokens

Load the project file once again and Visual Studio will during your next packaging parse the .svc files for replaceable tokens. Next go to the ProductService.cs file and add a Guid attribute to the ProductService class (don't forget to add the namespace System.Runtime.InteropServices). The class should look like this:

Guid attribute

Now head on over to the .svc file in the Layouts folder and edit the file so it contains the following (note that the code snippet below contains line breaks in the attributes which your code should not do):

<%@ ServiceHost Language="C#" 
    Service="$SharePoint.Type.dc339fb8-7f69-4fdd-b2c6-d3586dfa6337.FullName$,
        $SharePoint.Project.AssemblyFullName$" 
    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, 
        Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, 
        PublicKeyToken=71e9bce111e9429c"%> 

As you can see the Service attribute consist of two replaceable tokens; the class name and the assembly full name.

Tip: If you think that there is to much manual configurations going on here then just download the latest release of CKS:Dev -it has a project item template for just this: WCF Service (CKSDev).

4) Create the JavaScript stuff

The JavaScript file which contains the custom JavaScript functions and classes should be added to the Layouts folder. And while your there add the jQuery JavaScript file as well. The JavaScript should look like in the original article, except that there is a typo in the CallWCFService() method. The call to the jQuery ajax method should have the dataType property set to "json":

typo

5) Add a Web Part to test it

The easiest way to test this solution is to add a Web Part to the project. Do that and implement the CreateChildControls method as follows:

protected override void CreateChildControls() {
    ScriptLink.Register(this.Page, "jquery-1.4.2.min.js", false);
    ScriptLink.Register(this.Page, "ProductsService.js", false);
    string url = SPContext.Current.Web.Url + 
        this.ResolveUrl("~/_layouts/ProductService.svc/GetProducts");
    ScriptManager.RegisterStartupScript(this.Page, typeof(ProductsWebPart), 
        "ShowMeHeaven", 
        String.Format("CallWCFService('{0}')", url), true);
}

As you can see from the snippet above the jQuery and the custom JavaScript file is registered using the ScriptLink control and then we register a startup script which invokes the custom JavaScript method which calls the WCF service.

6) Test it

Your solution should now look like this:

The correct project

Now, just go ahead click F5 and watch the solution deploy. Then add the Web Part to a page and see the alerts popping up with the data from the WCF service.

Summary

What I wanted to show with this article is a best practice approach to building SharePoint 2010 solutions by using WSP files and avoid all manual configuration of the SharePoint Root, virtual directories and GAC. If you do that you will end up with an inconsistent farm and you have to pay sooner or later for that, and it will cost!

Happy SharePointing!

Comments and trackbacks

#  limo by nkjn
Sources?
#  Sources by Wictor
Screenshot from websnpr You will find the source code in the original article, referenced multiple times in this post
#  [ICC-423] As a Point 2.0 developer, I want to be able to implement a team site hierarchy search across farms, so that that the data can be delivered for (end-user) consumption by Trackback
Screenshot from websnpr null There are technically at least two notable options in implementing the data retrieval logic of multiple site collections. The "standard method" would be to use the out-of-the-box Content Query Web Part if only a single site collection was involve...
#  Input parameters by Nat
Screenshot from websnpr What if we need input parameters for our service. how will this work?
#  My endpoint points to '_vti_bin' not '_layouts' by Mark Pitts
Screenshot from websnpr I used the CKS Visual Studio extension to generated my SharePoint WCF. The endpoint specifies '_vti_bin' and not '_layouts'. Should I try to change that? Also, I am getting a 404 error in my browser when testing the endpoint. http://myurl/_vti_bin/LRGService/LRGWCFService.svc/FetchYearMakeModel I noticed my interface was missing the 'webget' attribute, so I added it as follows: [OperationContract] [WebGet(UriTemplate = "/FetchYearMakeModel", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] LRGYMMExt[] FetchYearMakeModel(); Can you suggest what I might be missing? Cheers! mark
#  Solved one of my above issues... by Mark Pitts
Screenshot from websnpr I neglected to change the factory to "MultipleBaseAddressWebServiceHostFactory". I can now access the endpoint form the browser.
#  How to package all dlls in one wsp by ScarePoint365
Screenshot from websnpr I have several class libraries along with default SP Web app project. I am adding dlls generated from project output into the package so that they get GACed when I deploy on dev machine. My question is will this approach work on production environment with several farms in the picture. Would it require central admin to take these dlls along the WSP solution? IS that what you were saying would cost us or something? or my approach of adding DLLs to package itself solves the problem?
#  Summing up the year of 2011 and embracing 2012 by Trackback
Screenshot from websnpr It's that time of the year, when you're thinking about what you've done and accomplished the last twelve months. I've been writing a summary for the last five years (2006, 2007, 2008, 2009 and 2010) a...
#  Summing up the year of 2011 and embracing 2012 by Trackback
Screenshot from websnpr It's that time of the year, when you're thinking about what you've done and accomplished
Make a comment on this post:
Subject:  

Your name:  
Your Url:  
Note: submissions may have to be approved before being visible, so don't submit your comment multiple times.