Access WCF Service with jQuery in SharePoint2010


 I described how to develop a custom WCF service. Today I’ll cover how you can invoke the SharePoint WCF Service from jQuery. In my last post I described to develop a SOAP web service but for using WCF service from jQuery I’m going to use REST web service. For the list of service types and factories supported in SharePoint you can visit the link in MSDN. You can download source code from the link given at the end of the post.

Prepare the service to call from jQuery

Consider developing a service as described in Create Custom WCF Service in SharePoint2010 with the following changes:
  • For  using json I’ve used REST service factory ‘Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory’ as shown below. You can use SOAP factory but you then need to parse data in different way.
    <%@ ServiceHost Language="C#" Debug="true"
        Service="AccessSPServiceFromJQuery.MyService, $SharePoint.Project.AssemblyFullName$"  
        CodeBehind="MyService.svc.cs"
        Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory
    Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0,     Culture=neutral, 
    PublicKeyToken=71e9bce111e9429c" %>
    
  • Next you need to specify the return type to json in the service interface as shown below. I’ve specified both request and response type to json in WebInvoke attribute:

    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, 
    ResponseFormat = WebMessageFormat.Json)]
        List<Product> SearchProduct(string productName);
     
     
        [OperationContract]
        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, 
    ResponseFormat = WebMessageFormat.Json)]    bool Save(Product product);
    }
One thing to notice here is that you can’t access the service in browser with mex endpoint. For example if you service is http://myserver/myservice.svc, then the url http://myserver/myservice.svc/mex will not work for service created with MultipleBaseAddressWebServiceHostFactory.

Call Service with jQuery

The next step is to call the service with jQuery. The url of the service to be used in jQuery will be service url and method name. For example if you service url is‘/_vti_bin/AccessSPServiceFromJQuery/MyService.svc’ and the method name you want to invoke is ‘Search’ then the full url will be ‘/_vti_bin/AccessSPServiceFromJQuery/MyService.svc/Search’. As shown in the code below, you can invoke the service Search by passing the parameter in data field of ajax call of jquery
function getProductFromService(searchText) {
    try {
        $.ajax({
            type: "GET",
            url: '/_vti_bin/AccessSPServiceFromJQuery/MyService.svc/SearchProduct',
            contentType: "application/json; charset=utf-8",
            data: { "productName": searchText },
            dataType: 'json',
            success: function (msg) {
                WCFServiceGetSucceeded(msg);
            },
            error: WCFServiceGetFailed
        });
    }
    catch (e) {

        alert('error invoking service.get()' + e);
    }
}
function WCFServiceGetSucceeded(result) {
    alert('success');
}
function WCFServiceGetFailed(error) {
    alert('Service Failed.');
}

Download and use code

I’ve uploaded the code for this post in my skydrive. You can download the code from the link below. To use the code please ensure you have internet connection as I’ve used jqery from Microsoft CDN. The search functionality get all products matching name. You can try to search just by typing a single character. You can debug and test the code. In save I’ve just shown you can pass value from browser to service using POST method.

Create Custom WCF Service in SharePoint2010


In SharePoint 2007, creating a custom Web Service was not so easy. However, asp.net web services are obsolete in SharePoint 2010. Rather new and recommended approach is to develop WCF Service. So the question comes up, “How much difficult it is to create a custom WCF service in SharePoint 2010?”. I’m going to answer the question just right in this blog.

Install CKS development tools edition

For showing how easily you can develop your own Custom WCF Service in SharePoint 2010, I’m going to use a open source Visual Studio 2010 extension know asCommunity Kit for SharePoint: Development Tools Edition. This tool will make the WCF service development much easier. It’ll automate tasks that you would have to do manually. There are two version of the extensions: One for SharePoint Foundation and another one is for SharePoint Server. Download the appropriate version and install.

Create WCF Service

Once you installed the CKSDev Visual Studio extension, you can open a SharePoint Project. In the SharePoint Project, right click on the project and try to add a new item. In the “Add New Item” dialog, you will find some new items added by CKSDev Visual Studio extension. Please select the option “WCF Service (CKSDev)” for new item as shown below:
image
Figure 1: ‘Add New WCF Service’ option ‘add new item’ dialog

Once you add the WCF Service, two files will be added by the dialog. One is the service interface and another is the Service itself.

Modify Service Types

As defined in MSDN, there are three different service types. Most of the time you need SOAP service. But if you need REST or ADO.NET Data service you can modify the service types by modifying the service factory as sown in the figure 2. The following table shows the three service types and their service factory name.
Service TypeService FactoryDescription
SOAP serviceMultipleBaseAddressBasicHttpBindingServiceHostFactoryBasic HTTP binding must be used, which creates endpoints for a service based on the basic HTTP binding.
REST ServiceMultipleBaseAddressWebServiceHostFactoryThe service factory creates endpoints with Web bindings.
ADO.NET Data ServiceMultipleBaseAddressDataServiceHostFactoryA data service host factory can be used.
When you create service with CKSDev tool, the default service generated is SOAP service. If you want to change the service type, please modify the factory in .svc file as shown below:
image
Figure 2: Service Factory defined in SVC file.

Deploy the Service

Once you are done with the service development, you are ready to deploy. But where you want to deploy the service? By default SharePoint service are kept in ISAPIdirectory. However, CKSDev deploy the service in ISAPI\ProjectNameSpace path as shown below:
image
Figure 3: Service deployment location
Once you define the service deployment location as shown in the figure 3, you can deploy the solution.

Access the Custom WCF Service

After Service deploy, you need to use the service in another projects. First try to access the service in browser. But remember you need to access the MEX endpoint either you will not get the service accessible in browser. To access the MEX endpoint, you should add “/MEX” at the end of the service name as shown below:
image
Figure 4: Access WCF Service MEX endpoint.

Finally try to add the service reference in a project using Visual Studio’s ‘Add Service Reference’ dialog as shown below:
image
Figure 5: Add Service Reference


Conclusion

So the steps described in this post are pretty simple:
  • Make sure you have downloaded and installed CKSDev Visual Studio extension.
  • Create a WCF Service (CKSDev) in the project. And if necessary, modify the service type
  • Deploy the solution and if necessary, change the deployment path.
  • Access the service MEX endpoint.

Get Full or Relative Url of web using EcmaScript in SharePoint2010


Sometimes from client side, you need to know the current web url. And for this little information you don’t want to call EcmaScript’s load function to get information from server side. Actually the information can be found without any server call. You can access the information from ClientContext as shown below.
var context = new SP.ClientContext();
var relativeWebUrl = context.get_url();
Remember the get_url method will only return relative url of the site. As shown in the following table:
Site Collection UrlSite Urlcontext.get_url() response
http://moss2010.comhttp://moss2010.com/
http://moss2010.comhttp://moss2010.com/site1/site1
http://moss2010.com/siteshttp://moss2010.com/sites/site1/sites/site

So if you need to know the full url of the site you can do so easily with the following script:
function getFullWebUrl() {
    var context = new SP.ClientContext();
    var relativeWebUrl = context.get_url();
    var fullWebUrl = window.location.protocol + '//' + window.location.host + relativeWebUrl ;
    alert(fullWebUrl);
}

Configure Kerberos Authentication in SharePoint 2010


SharePoint 2010 supports two authentication mode: Classic mode and Claims based. Today I’m going to explain how to configure Kerberos authentication for an web application with classic mode Authentication. I’ll try to explain how to configure Kerberos for an web application with Claims based authentication later.

Step 1:  Create/Configure Web Application

In this step you need to create an web application with required configurations. However, you can convert an existing web application to use Kerberos authentication if the web application app pool user is a domain user. But as mentioned already, the configuration explained in this post applies for an web application with Classic Mode Authentication.
Create a new web application
In creating new web application for using Kerberos Authentication you need to consider the following options:
  • Use classic mode Authentication as shown below (You can use Claims Based Authentication but then the steps described in this post might not work. For Claims Based Authentication you need different sets of configuration):

    image
    Figure 1: Create site with ‘Classic Mode Authentication’
  • Use Negotiate (Kerberos) as Authentication Provider in ‘Create Web Application’ page as shown below:

    image
    Figure 2: Create site with Negotiate (Kerberos) Authentication provider selected. 
  • Use domain username for app-pool account. Don’t use Predefined (like Network Service, Local System etc) user account. This is important to use domain user name as you will configure Kerberos against this app-pool username.

    image
    Figure 3: User domain user name for App-pool account.
  • One recommendation. Make the site url to be Fully Qualified Domain Name. For example, my server name was sohel-server and domain name was sohel.com. I’ve modified my full site name from default http://sohel-server:5000 to http://sohel-server.sohel.com:5000. This will help you identifying if the Only Kerberos is used for authentication instead of NTLM. 

Configure an existing web application
If you have an existing web application that you want to move to Kerberos from NTLM you need to make sure your site meets the following criterion:
  • The web application uses a domain user in application pool account instead of predefined account like Network Service, Local System. If your web application doesn’t use domain user then you can create a new web application with domain user name as application pool account. Changing the application pool account might make your web application malfunctioning.
  • If you existing web application uses Classic Mode Authentication then configuration in this post should work. However, if you are using Claims based Authentication then you need to configure Security Token Service (STS) which in not mentioned in this post. If you are using Classic Mode, then you can continue this post as this post describes Kerberos for an web application with Classic Mode Authentication.
If you meet the above mentioned criterion, then you can change the authentication of the site to Kerberos. To change the Authentication Provider to Kerberos, navigate to Central Admin site then click “Application Management” => Manage Web Applications => Select your web application => Click Authentication Provider from ribbon button as shown below:
image
Figure 4: Change Authentication Provider 
In the Authentication provider windows click on the zone you want to configure the Kerberos Authentication. Then you will be shown ‘Edit Authentication’ window. If your web application is using NTLM you can change the Authentication to Kerberos as shown below:

image
Figure 5: Change NTLM to Kerberos 
When you change the authentication type from NTLM to Kerberos you will be prompted with message saying “” as shown below. You don’t need to worry, we’ll configure other settings to use Kerberos. So just click ok button when the message appears and then save the settings.
image
Figure 6: Warning appears during Authentication changes from NTLM to Kerberos

Step 2: Configure Service Principal Name (SPN) in Active Directory

So your web application is configured for Kerberos Authentication but you need to configure Service Principal Name (SPN). Simply SPN is an unique identifier for each service (HTTP, SQL, AD etc) running in the server. An SPN is a combination of service name, host name and port name. The original format for SPN is
<Service Name>/<DNS Host>:Port
To know more about SPN, you can follow the link: http://technet.microsoft.com/en-us/library/cc961723.aspx. For our web application we need to create SPN. The SPN format for our web application is as shown below:
  • HTTP/<DNS Host Name>:Port
  • HTTP/<DNS FQDN>:Port
In my case the SPN are:
  • HTTP/sohel-server:5000
  • HTTP/sohel-server.sohel.com/5000
However, if you are using any port other than 80, you need to add four SPNs (two for 80 port and two for your non-80 web application port). Whether you use Kerberos for 80 port, you need to add SPNs for default portSo though I’m configuring Kerberos for HTTP port 5000, I need to configure Kerberos for 80 port also. The following SPNs are need to configured for my example.
  • HTTP/sohel-server
  • HTTP/sohel-server.sohel.com
  • HTTP/sohel-server:5000
  • HTTP/sohel-server.sohel.com:5000
How to set SPN?
  1. Make sure you installed ‘Active Directory Lightweight Directory Services’ from Server Role to get the ADSI Edit UI for editing SPN values. You can add the  ‘Active Directory Lightweight Directory Services’ from Server Manager => Add Roles  as shown below:

    image
    Figure 7: Install ‘Active Directory Lightweight Directory Services’ from ‘Add Server Role’
  2. To setup SPN, Run the command “adsiedit.msc” in either command prompt or from Run. You will get the ADSI Edit window.
  3. In ADSI Edit window, expand the ‘Default naming context’ and expand CN=Users and find the user you used for application pool in web application.
  4. Right click on the user entry CN=UserName and select properties window. Then find the property ‘servicePrincipalName’ and click edit as shown below:

    image
    Figure 8: Set SPN through servicePrincipalName
  5. Finally add the SPNs in the edit window as shown below:

    image
    Figure 9: Add SPN values as value of attribute ‘servicePrincipalName’.
  6. Press OK and then apply to close the dialog.

 

Step 3: Enable delegation

In some cases you may need to enable delegation of credentials. To enable delegation, open the Active Directory users and Computers from ‘Administrative Tools’ menu. Find the user used in Application pool under ‘Users’ node. Right click on the user and click Properties to get the properties window. Then in the properties window go to ‘Delegation’ tab and select ‘Trust this user for…’ as shown below: 
image
Figure 10: Enable delegation

 

Step 4: Configure Internet Explorer

Finally you need to configure Internet Explorer (IE) to use current windows user to access the SharePoint site.
  1. Go to Tool => Internet Options. Then select ‘Local Intranet’ and click Sites as shown below:

    image
    Figure 11: Setup IE for adding the SharePoint site to local Intranet
  2. After ‘Local Intranet’ dialog select ‘Advanced’ and then you’ll find the way to add sites to local intranet. Add ‘*.yourdomain’ in the local intranet zone as shown below:
    image
    Figure 12: Adding my domain (sohel.com) to local intranet.
  3. Now close the Internet Options dialog. Then open the ‘Internet Options’ dialog from Tools => Internet Options. Then go to Security tab and select ‘Local Intranet’ and select ‘Custom Level’. Then At the end of the ‘Security settings’ window, select ‘Automatic login only in Intranet zone’ as shown below:
    image
    Figure 13: Enable automatic login for Intranet zone

Conclusion

Configuring Kerberos authentication may depends on many factors. So I can’t guarantee than each and every steps described here will work for everybody. But the overall sets of configurations are same. You need to configure SharePoint site, You need to configure SPN, You need to enable delegation (if required), you n need to configure Internet Explorer.  You can get elaborate description of configuring Kerberos Authentication with SharePoint 2010 from the link:http://www.microsoft.com/download/en/details.aspx?id=23176.

How to Iterate through All the webs in the site of SharePoint


Sometimes we need to process all webs in a site collection, as you want to do some quick fixes in the web. Few weeks back my manager asked me to do some fixes in the list items exists in all the webs in the site collection. There were about 30,000 webs in the site collection and I was looking for some kind of script that will be efficient. The usual way of looping through all webs might be using some recursive way, as shown below.
//Starting point
public void ProcessAllWeb(SPSite site)
{
    using (var web = site.RootWeb)
    {
        ProcessWebRecursive(web);
    }

}

//Recursive method
private static void ProcessWebRecursive(SPWeb web)
{
    //do some processing
    //web.Lists["listName"].ItemCount

    foreach (SPWeb subWeb in web.Webs)
    {
        using (subWeb)
        {
            ProcessWebRecursive(subWeb);            
        }
    }

}
Code Snippet 1: Recursive way of processing all webs in the site collection (Not optimized)
In the recursive way of processing all webs, there will be more than one SPWeb instance alive in memory. In the above code snippet, when the method ProcessAllWeb is invoked it’ll call the recursive method ProcessWebRecursive. The recursive method will keep calling the subwebs while keeping the parent web alive.

While I was writing the code, I was wonder if there’s any way of processing only one web non-recursively. So my intention was to open only one web in memory at once. And then I found it. You can get all web Url(including all subwebs at all level) using SPSite.AllWebs.Names. The following code snippet shows the efficient way of processing all webs in the site collection:
public void ProcessAllWeb(SPSite site)
{
    string[] allWebUrls = site.AllWebs.Names;
    foreach (string webUrl in allWebUrls)
    {
        using (SPWeb web = site.OpenWeb(webUrl))
        {
            //process web
        }
    }
}
Code Snippet 2: Process all webs one by one (Optimized for large number of webs)
Using the code snippet shown in figure 2, you just open one web at a time in memory for processing. The trick here is ‘SPSite.AllWebs.Names’ which will return all the (I mean it!) subwebs (including children and their children and so on) as a result. If you have thousands of webs under a site collection (and if it’s production), you should care about performance issue.