In this blog post I will explain how to add and deploy a custom WCF service as a part of a SharePoint 2013 farm solution using Visual Studio 2012.
Back in the SharePoint 2010 days we all learned to love and use the Community Kit for SharePoint Development Tools (CKSDev), the king of Visual Studio add ons for SharePoint developers which extended the Visual Studio 2010 with numerous SharePoint related options and project item templates, making SharePoint development so much easier.
One of these templates was the Custom WCF Service template which made it easy to add a custom WCF service to your SharePoint 2010 solution. At the time of this writing, the CKSDev Tools were upgraded to the version 1.1 which made them compatible with Visual Studio 2012. However, many of the features from the 2010 version - most notably the SharePoint related project item templates such as Custom WCF Service - are missing from this release. The missing features will most certailnly be re-added in the coming versions, but if you’re in a hurry, this article will show you how to add a custom WCF service to your SharePoint 2013 project in Visual Studio 2012 per hand, without any add ons at all.
Before you begin, make sure to update your version od the Microsoft Office Developer Tools for Visual Studio 2012 the Visual Studio 2012 itself to the latest versions. This is especially important if you are still using the pre-RTM version of the Office Developer Tools, since this version has a many problems when developing against the RTM version of SharePoint 2013.
Begin by creating a new SharePoint 2013 empty project. In the Visual Studio 2012 menu select File>New>Project and select the “SharePoint 2013 – Empty Project” template from the SharePoint Solutions template group:
I named the project VS2012WcfService but you can name it what you want.
The SharePoint Customization Wizard will display asking you to select the deployment options for your new solution. Select a valid SharePoint URL to be used for deployment and F5 debugging from Visual Studio 2012 and select the “Deploy as a farm solution” option:
Please note that the URL you select here must point to the local SharePoint installation. If you are using Host Names Site Collections in your dev environment, it is likely that Visual Studio 2012 will not recognize the site URL as a local URL and throw the following error:
If that happens, simply open your hosts file under C:\Windows\System32\drivers\etc, add the following line to it and save it:
127.0.0.1 team.contoso.com
Replace team.contoso.com with the URL of the site you want to use for the debugging. After that the above error should disappear and you should be able to use your Host Named site for debugging.
First add the necessary references to yourt project. You need to add the reference to the following two dlls:
- Microsoft.SharePoint.Client.ServerRuntime 15.0.0.0
- System.ServiceModel 4.0.0.0
The next step is to add the ISAPI SharePoint mapped folder to the project. The ISAPI folder is the special folder within the SharePoint hive where all WCF services should be deployed. This folder is mapped to the “_vti_bin” alias in the IIS, so that services deployed to this folder can be accessed through http://{SiteUrl}/_vti_bin/{ServiceName}.svc.
Right-click on the project node in the solution explorer and select Add>SharePoint Mapped Folder… menu option:
On the next dialog select the ISAPI folder and click on OK:
Once you did that, right-click on the ISAPI folder in the Solution Explorer and add a subfolder to store files for your custom WCF service. This is technically not necessary, but as a best practice I suggest to always separate all your custom files being deployed in the SharePoint hive in subfolders named after your solution and/or company. In this example I added the “MyService” subfolder:
Keep in mind that the name of the subfolder will also impact the URL of your custom service after it is deployed to SharePoint. In this case, my service(s) deployed in the ISAPI\MyService folder will be accessible under http://{SIteUrl}/_vti_bin/MyService/{ServiceName}.svc URL.
Next, we’ll add the custom service svc file to the ISAPI\MyService folder. Since we don’t have the project item template to add a WCF service directly, we’ll add a simple text file and change its extension to svc. Right-click on the MyService subfolder, select Add>New Item… menu:
On the next dialog, select the Text File template under the General template group and name the file MyService.svc (or anything you want but make sure it has the .svc extension):
Next, add the Interface for our new service. Right-click again on the MyService folder in the solution exporer, select Add>New Item and select the Interface template under the Code template group:
Name the new interface I{ServiceName}.cs, in my case it is IMyService.cs. Later we will add code to this interface that will describe the Operation Contract of our new service, but let’s first add the last file we need, the {ServiceName}.svc.cs – in my case MyService.svc.cs - which will contain the implementation of the service interface we just added.
Right-click on the MyService folder in the solution explorer, select Add>New Item… menu option and add a new class making sure to name it like {ServiceName}.svc.cs:
Time for a quick check. If you did everything right, your project structure in the solution explorer should look something like this now:
So far we added:
- MyService.svc – the service file itself that will be deployed to SharePoint hive and served by IIS
- IMyService.cs – the interface file that will contain the service operation contract
- MyService.svc.cs – the code file that will contain the service interface implementation
Let’s now fill the files with content.
First open the IMyService.cs file and define your Operation Contract. For the purpose of this example I will use the following simple contract:
using System.ServiceModel;
namespace VS2012WcfService
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
string HelloWorld();
}
}
As you can see, we only have one service operation called HelloWorld returning a string. Let’s implement this interface. Open the MyService.svc.cs file and paste the following code:
using Microsoft.SharePoint.Client.Services;
using System.ServiceModel.Activation;
namespace VS2012WcfService
{
[BasicHttpBindingServiceMetadataExchangeEndpoint]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyService
{
public string HelloWorld()
{
return "Hello World from WCF and SharePoint 2013";
}
}
}
The next step ist to connect everything together in the MyService.svc file. Open MyService.svc and paste the following XML into it:
<%@ ServiceHost Language="C#" Debug="true"
Service="VS2012WcfService.MyService, $SharePoint.Project.AssemblyFullName$"
CodeBehind="MyService.svc.cs"
Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressBasicHttpBindingServiceHostFactory,
Microsoft.SharePoint.Client.ServerRuntime,
Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Make sure that the namespace and the class name of your service (in my case VS2012WcfService.MyService) and the CodeBehind file name (in my case MyService.svc.cs) entered above match those in your project.
Pay attention to the following line in the above XML:
Service="VS2012WcfService.MyService, $SharePoint.Project.AssemblyFullName$"
See the $SharePoint.Project.AssemblyFullName$ token? Visual Studio should replace this token the actual assembly name and version during the packaging of the solution. However, per default Visual Studio does that only for some file types. If you check the Microsoft.VisualStudio.SharePoint.targets MSBuild target file under C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\SharePointTools (which is used by Visual Studio to build SharePoint projects) you will find the following line:
<TokenReplacementFileExtensions>$(TokenReplacementFileExtensions);xml;aspx;ascx;webpart;dwp;bdcm</TokenReplacementFileExtensions>
This line basically tells Visual Studio to replace tokens such as $SharePoint.Project.AssemblyFullName$ in .XML, .ASPX, .ASCX, .WEBPART, .DWP and .BDCM files. In addition, there is an extension point $(TokenReplacementFileExtension) that makes it possible to register additional file types either by passing them to MSBuild command line or by modifying the Project (.proj) file.
So this is what we need to do in order to add the .SVC files to the list of file types whose tokens will be replaced by Visual Studio during pacaking. Save your project and then right-click on the project name in the Solution Explorer and select Unload Project option:
After the project was unloaded, right click again on the project name and select the “Edit VS2010EcfService.csproj” option:
This will open up the .csproj XML file in the editor. In the first <PropertyGroup> section on the top of the file, right below the line where it says
<SandboxedSolution>False</SandboxedSolution>
add the following line, save the file and close the editor:
<TokenReplacementFileExtensions>svc</TokenReplacementFileExtensions>
This will effectively tell Visual Studio to include .svc files to the list of files for token replacement.
The last step is to reload the project, compile and deploy it.
Right-click on the project name in the solution explorer and select the Reload Project option:
That’s it! Compile and deploy your project. If you did everything correctly, you should be able to access your custom WCF service under http://{SiteUrl}/_vti_bin/MyService/MyService.svc (replace the {SiteUrl} with the URL of the site you selected for the debugging when you started this tutorial):
Checking in the 15 hive, you should see your MyService.svc file deployed in 15\ISAPI\MyService folder:
If you open the MyService.svc file with the notepad, you will see that the $SharePoint.Project.AssemblyFullName$ token was replaced with the correct assembly name and version:
The dll itself was, of course, deployed to GAC. Because this is a .NET 4.5 dll compiled for Any CPU, it is not stored in the “old” .NET 2.0/3.5 GAC under C:\Windows\assembly, but under the new .NET 4.x GAC found at C:\Windows\Microsoft.NET\assembly\GAC_MSIL: