Nik Patel's SharePoint World

An adventure in SharePoint and Microsoft in general.

Archive for February, 2012

Step by Step – Building and Consuming Custom WCF Services hosted in SharePoint

Posted by nikspatel on February 29, 2012

If you are developing enterprise level custom solutions based on SharePoint framework, you would come across scenarios where you have to expose and access SharePoint data from remote applications like CRM, ASP.NET, Silverlight, or other SharePoint applications. SharePoint 2010 Out of box allows multiple ways to interact with SharePoint data from remote applications like Client Object Model, REST based API, ASP.NET SOAP web services etc. As we all come across, these options are not sufficient in real world scenarios and it would require writing custom WCF Services.

As you can read from earlier article, one of the great things about WCF services are they can be hosted and deployed multiple ways. One of the options are SharePoint 2010 allows custom WCF service hosted in SharePoint Root ISAPI directory. In this article, I will walkthrough step by step process of setting up custom WCF service project as SharePoint Solution, how it can be deployed to the SharePoint 2010, and how it can be consumed from the SharePoint web parts.

The Custom WCF Service built in this article returns list of documents name and title information from the Shared Document Library in the root site collection web site and displays on the SharePoint Site using web parts interface.

Step 1 => Setup WCF Service Project to host in SharePoint

Create New Empty SharePoint Project – Niks.SP2010.SPHostedWCFService and Select “Deploy as a Farm Solution”. This approach will deploy WCF service in SharePoint Root, ISAPI directory.

Add WCF Service Project Item by right clicking on Project and Add New Item.

From the Add New Item window, select C# and select WCF Service. Specify SPHostedWCFService.cs and Add item to the project.

This should add three files in the project – web.config, ISPHostedWCFService.cs, and SPHostedWCFService.cs. Please note that ISPHostedWCFService is service interface and SPHostedWCFService is class implementation.

App.config should look like this.

<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="Niks.SP2010.SPHostedWCFService.SPHostedWCFServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="Niks.SP2010.SPHostedWCFService.SPHostedWCFServiceBehavior"
                name="Niks.SP2010.SPHostedWCFService.SPHostedWCFService">
                <endpoint address="" binding="wsHttpBinding" contract="Niks.SP2010.SPHostedWCFService.ISPHostedWCFService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="<a href="http://localhost:8732/Design_Time_Addresses/Niks.SP2010.SPHostedWCFService/SPHostedWCFService/">http://localhost:8732/Design_Time_Addresses/Niks.SP2010.SPHostedWCFService/SPHostedWCFService/</a>" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>

Next step is to compile the Project and find the PublicKeyToken using sn.exe from command prompt. This is required for next steps for full assembly reference in WCF Service file. Running this command prompt, would return public key token – 9a823b7ed0a910a2 for this WCF Web Service

Unfortunately there is no ”WCF Service” SharePoint Project Item available in Visual Studio. You can download CKSDEV codeplex solution which would ease adding WCF Service SPI in Visual Studio.

Since I wanted to go with manual way (which is easy by the way), To host WCF Service in SharePoint ISAPI folder, right click on project and Add SharePoint Mapped folder – ISAPI. Within ISAPI folder, add SPHostedWCFService folder to host custom WCF web service and add two text files and rename them as SPHostedWCFService.svc and web.config

Add following lines in SPHostedWCFService.svc, Specify correct PublicKeyToken derived from earliar step.

<%@ Assembly Name="Niks.SP2010.SPHostedWCFService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a823b7ed0a910a2"%>
<%@ ServiceHost Service="Niks.SP2010.SPHostedWCFService.SPHostedWCFService" %>

Add following in web.config in ISAPI folder

<configuration>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <bindings>
      <basicHttpBinding>
        <binding name="customBasicHttpBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Ntlm"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="customBasicBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="customBasicBehavior"
        name="Niks.SP2010.SPHostedWCFService.SPHostedWCFService">
        <endpoint address="" binding="basicHttpBinding"
        bindingConfiguration="customBasicHttpBinding"
        contract="Niks.SP2010.SPHostedWCFService.ISPHostedWCFService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="<a href="http://localhost/_layouts/WorkflowDemonstration">http://localhost/_layouts/WorkflowDemonstration</a>" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>


Step 2 => Implement Business Logic in WCF Service

Once basic project is setup, next logical step would be implementing business logic in WCF Service. Each WCF Service has to define two steps – Interface and Implementation.

Define the Service Contract and Data Contract in ISPHostedWCFService.cs

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

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

Implement the Service Contract – SPHostedWCFService.cs

In this WCF Service, since I am hosting WCF Service on the SharePoint farm, I am using Server Side Object Model to access Shared Documents document library from the root site collection web site and return documents information in the business object collection.

Since SharePoint is ASP.NET web application, please ensure to set each service method – AspNetCompatibilityRequirements to either Required or Allowed for ASP.NET compatability as shown in following code snippet.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SPHostedWCFService : ISPHostedWCFService
{
    public List<DocumentData> GetLists()
    {
        List<DocumentData> docData = new List<DocumentData>();

        string siteURL = "<a href="http://sp2010vm/">http://sp2010vm</a>";
        string documentListName = "Shared Documents";

        using (SPSite spSite = new SPSite(siteURL))
        {
            SPDocumentLibrary spLibrary = (SPDocumentLibrary)spSite.RootWeb.Lists.TryGetList(documentListName);
            foreach (SPListItem listitem in spLibrary.Items)
            {
                docData.Add(new DocumentData() { Name = listitem.Name, Title = listitem.Title});
            }
        }

        return docData;
    }
}

Step 3 => Deploy WCF Service in SharePoint

Once WCF Service logic is implemented, next logical step is to package the WCF service solution and deploy it to the SharePoint. This step is similar to any other SharePoint WSPs. This step requires packaging WCF SharePoint solution and deploys it through Visual Studio or Solutions & Features Framework API as Farm level solution. Deploying solution would provision Niks.SP2010.SPHostedWCFService.dll into GAC and Niks.SP2010.SPHostedWCFService folder wtih WCF endpoint in SharePoint Root ISAPI directory.

To Test the WCF Service Interface, Click on the URL – http://SP2010VM/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc

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. Click on the Link – http://sp2010vm.niks.local/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc?wsdl to see the service contract information.

Step 4 => Consume 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.SPHostedWCFServiceClient

Reference the WCF Service by right clicking project and Add Service Reference. Enter WCF Service Address  – http://SP2010VM/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc and and Click Go to discover. Add Proper Namespace and click OK to add WCF Service Proxy in Visual Studio

Adding reference to the WCF Service, would add app.config file in the project which needs to be copied to the SharePoint Web Application Web.Config file. To Consume WCF Service from SharePoint User Inteface, 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.SPHostedWCFServiceClient.SPHostedWCFService.SPHostedWCFServiceClient client
        = new Niks.SP2010.SPHostedWCFServiceClient.SPHostedWCFService.SPHostedWCFServiceClient();
    client.ClientCredentials.Windows.AllowedImpersonationLevel =
        System.Security.Principal.TokenImpersonationLevel.Impersonation;

    Niks.SP2010.SPHostedWCFServiceClient.SPHostedWCFService.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 ttp://sp2010vm.niks.local/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc.

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ISPHostedWCFService" 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/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc">http://sp2010vm.niks.local/_vti_bin/SPHostedWCFService/SPHostedWCFService.svc</a>"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISPHostedWCFService"
                contract="SPHostedWCFService.ISPHostedWCFService" name="BasicHttpBinding_ISPHostedWCFService" />
        </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 name & title in Grid View

Important Notes regarding Updating WCF Service Interface & Implementation

  • If you are changing any logic in WCF Service contract implementation, you don’t have to refresh Service Reference from the Client.
  • If you have changed WCF Service Contract Interface or Business Objects Definitions, you don’t have to refresh Service Reference from the Client using Visual Studio

Additional References – Hosting WCF Services in SharePoint

Posted in Dev General | Leave a Comment »

Hosting Custom WCF Services in IIS vs SharePoint

Posted by nikspatel on February 29, 2012

Please note that this article refers to Custom WCF Services built to access SharePoint data or extend SharePoint Operations and what items needs to considered while making decision of hosting in IIS or SharePoint environment.

With SharePoint 2010, Microsoft has allowed SharePoint developers an option of hosting Custom WCF Services in SharePoint 2010 environment. Additionally, WCF Services can be hosted in IIS as well. As with many other Microsoft technologies, developers and administrators faces decision making process whether to deploy custom WCF Services in SharePoint or IIS. Unfortunately, I haven’t come across any official guidance in this matter from Microsoft and most of the articles on TechNet or MSDN demonstrate custom WCF service hosted in SharePoint 2010.

In this article, I will try to list high level items needs to consider while making decision on deploying WCF Service in IIS or SharePoint.

Hosting WCF Service in IIS

  • Can be deployed to dedicated IIS web servers, non-SharePoint servers to utilize dedicated RAM
  • WCF Service would run in its own worker process or application pool
  • WCF Service can have separate authentication and authorization mechanism than SharePoint Implementation.
  • WCF Service can be configured with impersonate = false to run WCF Service logic as application pool service account.
  • If you are accessing or processing SharePoint data from WCF services, you must use REST based API or client side object model to integrate with SharePoint implementation unless you are deploying WCF services as dedicated IIS web site on SharePoint Servers.
  • Needs to deploy WCF service on multiple IIS servers with load balancer to provide high availability
  • WCF Service hosted on separate IIS server wouldn’t interfere with SharePoint processes and chew up RAM required by SharePoint operations

Hosting WCF Service in SharePoint

  • Runs in SharePoint Web Application’s worker process
  • Deployed to SharePoint servers in the farm using SharePoint solutions framework
  • WCF Service would have to use same authentication and authorization mechanism as SharePoint Implementation.
  • WCF Service can’t be configured with impersonate = false since impersonation is enabled by default in SharePoint 2010. This allows calling application to run WCF service in user context and return security trimmed data.
  • If you are accessing or processing SharePoint data from WCF services, it provides best performance because it runs under SharePoint worker process and can use Server Side Object Model
  • WCF Service is already deployed to all the WFE servers and provides high availability by using SharePoint inbuilt load balancer
  • WCF Service hosted in SharePoint worker process would share RAM with SharePoint operations and it may degrade SharePoint performance and scalability
  • If your web application is configured with claims based authentication, it is important to remember that IIS website is configured to have anonymous access. Since your WCF endpoints would be hosted in SharePoint web application, it may receive requests from anonymous users. It is always best practice to check if user is authorized user in WCF service implementation.

Based on above items, hosting WCF Services on dedicated IIS servers would make great case for centralized enterprise services library especially when performance, security, scalability, authentication, and authorization model matters most. This would allow hosting all the custom WCF Services in single environment managed by single team whether they are based on SharePoint or not.

Best use case to deploy WCF Service in SharePoint is to extend SharePoint capabilities and run WCF Services in User Context like out of box WCF Services hosted in ISAPI directory (e.g. Client.svc or ListData.svc or ASMX files). Additionally, hosting WCF services would allow you to use Administrative SharePoint APIs which isn’t available in Client Object Model or REST based API. E.g. User Profile Services API are not available through client object model and if your WCF service is maintaining User Profiles, you have to use Server Side Object Model and hosting custom WCF Service in SharePoint would make more sense.

And, here is the Kicker. You can also host WCF Services as dedicated IIS web sites on the SharePoint Servers to use best of both worlds. This would allow performing Administrative SharePoint operations using Server Side Object Model with dedicated worker process, impersonation model, authentication model, and authorization model. Recently I wrote SharePoint Site Provisioning WCF web service which needed to run under farm account (impersonation = false), anonymous authentication disabled, and perform Administrative APIs using Server Side Object Model. This was perfect case where I needed to host WCF services on IIS servers on SharePoint Servers.

Hopefully this article would help making intelligent decisions while hosting custom WCF Service based on SharePoint Framework.

Posted in Dev General | Leave a Comment »

Decision Time – Deactivate SharePoint Foundation Web Application Service on Central Admin or Deploy Custom Solutions from Central Admin

Posted by nikspatel on February 24, 2012

Note: This article only applies to central admin server used for Application Tier in SharePoint Farm.

I recently came across very interesting error while deploying solutions and activating features using powershell on one of our farm’s central admin server. What surprised me that we were using same approach to deploy our code from central admin server since last couple of months and suddenly it’s stopped working while activating features and throwing error.

Enable-SPFeature : The Feature is not a Farm Level Feature and is not found in a Site level defined by the Url. At D:\Deploy\SPSolutionDeploymentScript.ps1:287 char:22 + Enable-SPFeature <<<<  –identity $webFeatureName -URL $spWeb.url -Confirm:$false + CategoryInfo: InvalidData: (Microsoft.Share…etEnableFeature:SPCmdletEnableFeature) [Enable-SPFeature], SPCmdletException + FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletEnableFeature

Looking at the error, it was clear that PowerShell wasn’t able to find SharePoint Features and Solutions framework API on the server. What I didn’t know was what would or which SharePoint Service application would enable this framework on the server. My first guess was to reach out to our SharePoint admin to see if he is aware of any recent changes on the central admin server configuration. Additionally, I tried to deploy and activate features through one of the WFE servers and it worked fine. As I was waiting for admin response, I have reached out to greater SharePoint community via twitter. My good friends from SharePoint Twitter communities, both Dan Usher (@usher) and Clayton Cobb (@warrtalon) came to rescue right away and first clue was SharePoint Foundation Web Application Service may not be running. While I was trying to confirm whether this service was running earlier and stopped recently causing feature activation issues, I received response from Admin that this service was indeed stopped and he may have stopped recently.

Well, problem is solved and resolution is clear. We just needed to activate the SharePoint Foundation Web Application Service to resolve the issue. But, as we were exchanging information on twitter, I have realized that this could be major SharePoint release management decision. As an Admin, we would like to disable the SharePoint Foundation Web Application Service on the central admin server. Disabling SharePoint Foundation Web Application Service on central admin server seems one of the best practices since it isn’t used to serve pages to the end-users and disabling this service would conserve server memory for other dedicated SharePoint application tier services enabled on Central Admin/Application Server.

In General, here are the guidelines I have came to conclusion whenever I come across similar situation in future.

  • It is still best approach to deploy code and activate features from central admin. This would allow central admin server as a main administrative consoles for both configurations and custom deployment.
  • It is still best practice to disable the SharePoint Foundation Web Application Service on the Central Admin Server to avoid additional performance overhead by running less SharePoint Web Application IIS worker processes
  • Since you have to activate SharePoint Foundation Web Application Service on the Central Admin Server to deploy code from the Central Admin Server, It would be great practice to enable the Service during deployment process and disable during normal runtime. It would be nice to have a deployment tasks to enable the service, deploy custom solutions, and disable the service.
  • One last point, there is nothing written on stone or as a best practice to deploy code from central admin, it is just my preferred method to centralize administrative tasks in one place. If your situation is different and able to deploy custom solutions from the WFE servers running SharePoint Foundation Web Application Service, you are covered.

Here is another great article recommendaed by Dan Usher and it provides same architectural insights faced by SharePoint Architects and IT Pros in real world – http://blogs.technet.com/b/speschka/archive/2010/11/27/beware-of-default-solution-deployments-for-custom-claims-providers-in-sharepoint-2010.aspx

Posted in Admin General | Leave a Comment »

Enable ASP.NET Session State on SharePoint 2010 Application

Posted by nikspatel on February 12, 2012

ASP.NET Session state is disabled by default in SharePoint 2010 installation. Although it may not require in typical SharePoint 2010 installations, there may be need in custom solutions & web parts built on top of SharePoint 2010 framework where developers required persisting information per user session.

How ASP.NET Session State really works in SharePoint?

As many of you are aware, ASP.NET allows persisting session states in three different medium – on server memory as a inproc which would require server & load balancer affinity, on SQL Server to persist session in database, or on Session State Server to persist session on dedicated server memory. Both SQL Server and Session State Server would support server farm environment and because SharePoint is the multi-server farm environment based on ASP.NET framework, by default, it can be enabled to use SQL Server and SqlSessionStateStore provider to persist session state using ASP.NET Session State Service Application.

Should I really worry if ASP.NET Session State is enabled on my SharePoint farm?

ASP.NET Session State Service as SharePoint Session State Management depends on many factors including how many concurrent users will be accessing site, or heavy vs. average vs. low usage of session objects. If you really need to persist user session information and if you can store them in other mediums like cookies, ASP.NET Session state may not be necessary. Since SharePoint is built on top of ASP.NET framework, ASP.NET Session State Service would be ideal place to persist user sessions. Since ASP.NET Sessions gets stored in the SQL Server, heavy usage of session state may require detailed database planning, regular truncating/maintenance/cleanup of expired session state data, or fine tuning of default 60 minute session expiration time. Great thing about this service is even though it’s enabled on whole farm, it’s not used unless specific application is activated to use session state and you have full control & visibility of how ASP.NET sessions gets stored in SharePoint.

How do I enable ASP.NET Session State in SharePoint?

ASP.NET Session state is available to the SharePoint environment by enabling “SharePoint Server ASP.NET Session State Service” service application on the SharePoint farm. You can’t enable this service application using central administration browser interface. You must enable it using PowerShell command.

Step 1: Enable ASP.NET Session State Service

To enable ASP.NET session state, log on the Central Admin Server using Farm Admin Account, and

  • Either Run PowerShell command “Enable-SPSessionStateService –DefaultProvision” to create service application with default state. By default, this will create service application database with “SessionStateService_<GUID>”, on the same database server where farm configuration database is located using windows credentials of the logged in user.
  • Or Run PowerShell command “Enable-SPSessionStateService -DatabaseServer YourDBServerName -DatabaseName YourDBName” to create service application with specific database name on non-SharePoint configuration database server. For more details and additional parameters, please visit Enable-SPSessionStateService http://technet.microsoft.com/en-us/library/ff607857.aspx.

By enabling Session State Service on your farm,

It would create database on specified server – SessionStateService_<GUID>

It would create SharePoint Server ASP.NET Session State Service in Manage Service Applications

It would add module in all web applications on farm – <add name=”Session” type=”System.Web.SessionState.SessionStateModule” />

It would add sessionstate entry in all web applications on farm

<sessionState mode=”SQLServer” timeout=”60″ allowCustomSqlDatabase=”true” sqlConnectionString=”Data Source=SP2010VM;Initial Catalog=SessionStateService_1079ab25364440b0b38b15ad2392b6d0;Integrated Security=True;Enlist=False;Connect Timeout=15″ />

Step 2: Activate ASP.NET Session State on SharePoint Web Application

By enabling ASP.NET session state service in the SharePoint farm, every SharePoint web application in the farm ready to use ASP.NET session framework. To ensure SharePoint web application gets activated to persist ASP.NET sessions, you have to manually update Web.Config file for the specific SharePoint web application on all servers in the farm.  - <pages enableSessionState=”true”

Step 3: Although this may not be necessary, performing IISReset on all the servers would help resetting all the sessions.

How would you use ASP.NET Session State Service in Code?

This is straightforward. You can access ASP.NET session state object using HTTPConext.Current.Session and use the ASP.NET session state same as typically ASP.NET Session Management. Here is the sample code which would create new ASP.NET session object called “SampleSessionKey”, if it doesn’t exists.

After above code runs, this is what you would see in the ASP.NET Session State Service Application database. By default, it would create session for 60 minutes. If you want to increase or decrease session expiration, you have to pass “SessionTimeout” parameter while creating ASP.NET Session State Service using Enable-SPSessionStateService command.

Additional References

Posted in Dev General | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.