Step by Step – Building and Consuming Custom WCF Services Hosted in IIS using WCF Application Approach

Note: Download Code discussed in this article from Here

If you are building WCF Services to extend, consume, or deliver SharePoint data, one of the biggest decisions as a SharePoint Architect you have to make is where you would host WCF Services. As I have shown in one of my previous articles, two most popular approaches are hosting WCF services in SharePoint and IIS and it requires high level architectural decisions. There are several different ways you can create IIS hosted WCF Services using several Visual Studio templates like WCF Service Application, WCF Service Library, WCF Service Project Item, or WCF Service Web Site templates. One of the reasons I like WCF Service Application approach is it provides clear separation and methodological approach to organize source code in specific code library and deploy WCF services in separate IIS Inetpub directory to facilitate team based development.

This article will demonstrate creating WCF Services using Visual Studio WCF Service Application template, host WCF services in the IIS by publishing from Visual Studio, and consume WCF services in SharePoint Web parts to display Shared document library data.

Step 1 => Create WCF Service using Visual Studio as WCF Service Application
Create New Project – Visual # -> WCF -> WCF Service Application – Niks.SP2010.IISHostedWCFService

By default, WCF Service Application would add four items – web.config, service1.svc, service1.svc.cs, and Iservice1.cs. Iservice1 is service interface and service1.svc.cs is service class implementation.

Delete default service1.svc and Iservice1.cs. Remove all the service1 references from the web.config file especially service behavior configuration.

Add New WCF Service Project Item by right clicking on Project and Add New Item. From the Add New Item window, select Web and select WCF Service. Specify IISHostedWCFService.svc and Add item to the project.

This would add three items – IISHostedWCFService.svc, IISHostedWCFService.svc.cs, IIISHostedWCFService.cs

Implement business logic in IIISHostedWCFService.cs and IISHostedWCFService.svc.cs. Since this type of service will be hosted in IIS, you need to use Client Side Object Model unless it’s deployed to the IIS on SharePoint Servers. If IIS hosted service is hosted in IIS on SharePoint box, it can use Server Side Object Model.

Since this WCF service will be hosted on dedicated non-SharePoint IIS web servers, it would use Client Side Object Model to  access SharePoint data from remote machines. You can standardize client object model installation using the client object model redistributable on non-SharePoint Servers. This will install three DLLs on the GAC – Microsoft.SharePoint.Client, Microsoft.SharePoint.Client.Runtime, and Microsoft.SharePoint.Client.Runtime.Resources DLLs.

Reference Client Object Model DLLs in the Project

Define the Service Contract and Data Contract in IIISHostedWCFService.cs


[ServiceContract]
public interface IIISHostedWCFService
{
[OperationContract]
List<DocumentData> GetLists();
}

[DataContract]
public class DocumentData
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Title { get; set; }
}

Implement the Service Contract – IISHostedWCFService.svc.cs


public List<DocumentData> GetLists()
{
List<DocumentData> docData = new List<DocumentData>();
string siteURL = "<a href="http://sp2010vm/">http://sp2010vm</a>";
string documentListName = "Shared Documents";

using (ClientContext clientContext = new ClientContext(siteURL))
{
NetworkCredential credentials = new NetworkCredential
(ConfigurationManager.AppSettings["SvcAccountId"],
ConfigurationManager.AppSettings["SvcAccountPassword"],
ConfigurationManager.AppSettings["SvcAccountDomain"]);
clientContext.Credentials = credentials;

List list = clientContext.Web.Lists.GetByTitle(documentListName);
var camlQuery = new CamlQuery { ViewXml = "<View/>" };

ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();

foreach (ListItem listitem in listItems)
{
docData.Add(new DocumentData() { ID = Convert.ToInt32(listitem["ID"]), Title = listitem["Title"].ToString() });
}
}

return docData;
}

Update Your Web.Config as following for WCF service security mode, bindings, service behaviors, and endpoints. Additionally, it enables windows authentication, disables impersonation, and allows all users to access web service.


<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="Niks.SP2010.IISHostedWCFService.IISHostedWCFServiceBehavior"
name="Niks.SP2010.IISHostedWCFService.IISHostedWCFService">
<endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="BasicHttpEndpointBinding" name="basicBindingConfig"
contract="Niks.SP2010.IISHostedWCFService.IIISHostedWCFService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Niks.SP2010.IISHostedWCFService.IISHostedWCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true" />
<authentication mode="Windows" />
<identity impersonate="false" />
</system.web>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="*" />
</authorization>
</security>
</system.webServer>
</configuration>

Step 2 => Deploy WCF Service in IIS 7
Once WCF Service logic is implemented, next logical step is to publish the WCF service application to the IIS.

In IIS 7, create new web site -> Site Name – IISHostedWCFService, ApplicationPool – IISHostedWCFService, Port-9999, Physical directory – C:\inetpub\wwwroot\IISHostedWCFService

In IIS, change the App pool identity to – Niks\Administrator from default AppPoolIdentity

In IIS, disable anonymous authentication and enable windows authentication. Allow all users in authorization section.

In VS, Publish WCF Service -> Web Deploy, service URL – http://localhost:9999, site/app name – IISHostedWCFService, Mark IIS as destination and Publish, it will copy SVC, BIN directory, and web.config to inetpub physical directory – IISHostedWCFService. Please note that when you are making changes in IIS authentication or authorization options, it would change web.config in IIS virtual folder, it wouldn’t change in visual studio web.config. Republishing from Visual Studio, may overwrite web.config in IIS virtual folder.

Step 3 => Test the WCF Service
To Test the WCF Service Interface, In IIS web site content view, right click and browse WCF file.

If your SharePoint Web Application IIS web site is not enabled for anonymous authentication or claims based authentication, it would ask you for the credential and should take you to the WCF interface – http://localhost:9999/IISHostedWCFService.svc. Click on the Link – http://sp2010vm.niks.local:9999/IISHostedWCFService.svc?wsdl to see the service contract information.

Step 4 => Consume the WCF Service from SharePoint
In real world scenarios, you would be consuming WCF services from the non-SharePoint remote applications like CRM, SQL Server SSIS Packages, ASP.NET, Silverlight, or Console Utilities. For the demonstration purpose, I will consume Custom WCF Service from the SharePoint web application. Create new empty SharePoint Project – Niks.SP2010.IISHostedWCFServiceClient

Reference the WCF Service by right clicking project and Add Service Reference. Enter WCF Service Address – http://sp2010vm.niks.local:9999/IISHostedWCFService.svc and Click Go to discover. Add Proper Namespace and click OK to add WCF Service Proxy in Visual Studio.

Addingt Service reference would add app.config file in the project and WCF binding’s entries for <system.serviceModel>. To Consume WCF Service from SharePoint User Interface, Add Visual Web Part.

In Visual Web Part Code, invoke the WCF Service proxy, pass the user credential to the service, and call service method to return list of documents by populating ASP.NET data grid. Following code would invoke service and run WCF Service under user context.


protected void Page_Load(object sender, EventArgs e)
{
Niks.SP2010.IISHostedWCFServiceClient.IISHostedWCFService.IISHostedWCFServiceClient client
= new Niks.SP2010.IISHostedWCFServiceClient.IISHostedWCFService.IISHostedWCFServiceClient();

Niks.SP2010.IISHostedWCFServiceClient.IISHostedWCFService.DocumentData[] docData = client.GetLists();
gvDocData.DataSource = docData;
gvDocData.DataBind();
client.Close();
}

Final step to call WCF Service properly during runtime, copy App.Config <System.ServiceModel> section to the SharePoint Web Application. By default, it’s using basicHttpBinding binding & NTLM as authentication method. Please note that WCF Service endpoint is http://sp2010vm.niks.local:9999/IISHostedWCFService.svc.


<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBindingConfig" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="<a href="http://sp2010vm.niks.local:9999/IISHostedWCFService.svc/basic">http://sp2010vm.niks.local:9999/IISHostedWCFService.svc/basic</a>"
binding="basicHttpBinding" bindingConfiguration="basicBindingConfig"
contract="IISHostedWCFService.IIISHostedWCFService" name="basicBindingConfig" />
</client>
</system.serviceModel>
</configuration>

Once web.config is properly configured, open the SharePoint Web Application and add Custom Web Part on the page. It should display list of all the documents title in Grid View

Additional Resources

This entry was posted in SP2010 DEV General. Bookmark the permalink.