Nik Patel's SharePoint World

An adventure in SharePoint and Microsoft in general.

Archive for the ‘Dev General’ Category

SharePoint Error while Creating Site Collections or Sites – Cannot complete this action

Posted by nikspatel on March 13, 2012

Yesterday I came across weird error while provisioning sites programmatically from the WCF service – Cannot complete this action. The reason why this error was weird because I was able to execute exact same code from console application to provision site collection by running code block as an user in farm administration group. Since my WCF service was running under farm admin account, I was running exactly same code using exact same identity.

In theory, this code should work but it seems like SharePoint doesn’t work same for WCF and Console Application.

After spending couple of hours troubleshooting usual service accounts settings, WCF services configuration, security permissions checks, and Google search, finally I stumbled upon MSDN Blog and KB article written in 2005 for WSS 2.o SP2.

Basically these articles suggests that even though accounts might have enough permission to execute code, explicit impersonation is required to make successful SharePoint actions. Apparently this kind of impersonation requires even at the sites, lists, and document libraries level.

After wrapping up my site collections provisioning code with impersonation, I was able to successfully execute code in the WCF service.

using System.Security.Principal
....
WindowsImpersonationContext wic = WindowsIdentity.GetCurrent().Impersonate();
//implement OM code here
wic.Undo();

I was really surprised that ages old articles helped me to resolve SharePoint 2010 programmatic issues without much explanation by KB article. Since farm account has sufficient rights to perform farm level operations, it simply doesn’t make sense to explicitly impersonate with farm account again in code. I am still trying to figure out what exactly required impersonation, what exactly enhanced security in framework means, and why farm account explicit impersonation required even though WCF service was running under same account which has full privileges to perform farm level actions. My search for correct explanation continues.

Hope this really helps someone. It took me while to figure it out and stumble upon correct solution or I should rather say, peculiar situation. ;)

Posted in Dev General | Leave a Comment »

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

Posted by nikspatel on March 7, 2012

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

Posted in Dev General | Leave a Comment »

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 »

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 »

Custom SharePoint Pages – Site Pages vs Application Pages

Posted by nikspatel on January 20, 2012

Although I have been building custom applications on SharePoint Platform since MOSS 2007 days, when it comes to making decision on whether to use application page or site page features for specific scenario, I typically have to go through basics and try to weight pros and cons of each characteristics especially on coding complexity, runtime performance, future upgrade maintenance, deployment and retraction.

In past, I have time and time again relied on the Ted Pattison’s Chapter 2 and Chapter 3 of “Inside Microsoft Windows SharePoint Services 3.0” for decision making process on application vs. site pages. Typically it required me to go through both chapters and perform additional home work to review every aspect of application vs. site pages functionality. As you may understand, it has been tiring process. Over the time, I end up building my own list of major differences between site pages and application pages to help me making decision faster if it’s needed.

Generally my rule of thumb is to go for custom application pages for administrative tasks like maintenance or system pages and go for custom site pages for end-user business functionalities to promote end-user customizations if needed. Here are major characteristics and differences between site pages and application pages categorized by major areas of architectural decisions.

  • Characteristics
    • An Application page is an ASP.NET content page hosted in the LAYOUTs directory on the WFEs and inherits from Microsoft.SharePoint.WebControls.LayoutsPageBase. Site Pages are stored in the virtual file system in the Content databases. SPFile and SPFolder objects represents Site Pages in WSS object model.
    • As Name Suggest, An Application Page is application or farm scoped and A site page is  site/web scoped.
    • Site Pages consists of two compoents => Site Page Templates vs Site Page Instances
      • Site Page Templates are .aspx pages stored in the file system in the FEATURES directory.
      • Site Page Instances are provisioned through Module and File elements and resides in content database. They are created inside the context of the particular site. WSS treats Un-customized Site Page Instances as a reference pointer to the Site Page Template. You can use SharePoint Designer to customize or view site page instances. Both customized or un-customized site pages exposed through the virtual file system.
  •  Coding
    • An application page can have code behind and inline code but site page can’t have code behind or inline code. Using PageParserPaths for site pages is not best practice. Workaround for this problem is to create the site pages with web part pages and add web parts which has codebehind during feature activation.
    • An application page doesn’t support web parts or web part zones (they are ghosted pages) but Site Pages supports web parts. It means application pages would support only server controls or user controls and cannot be personalized by end-users.
  • Customization
    • An application page typically requires Visual Studio to customize the page, while Site Page can be easily customized through SharePoint Designer. First time you change the site page template or site page instance through SharePoint designer, it creates a customized copy and stores in the virtual file system. Use “Reset to Site Definition” to reset customized site page to the non-customized site page.
    • An application page doesn’t support customization per site by site basis but site page supports different Site Pages per Site
  • Deploy
    • An application page is available to all the sites, while site page can be deployed only specific sites
    • An application page is deployed in LAYOUTS directory when solution is deployed to the web application or farm, while site pages are deployed to content database when feature is activated for specific web. Site page templates gets deployed in FEATURES directory same way as application page when solution is deployed.
    • An application page must requires a farm solution, while SitePage can be deployed using a sandbox solution. It means, application pages requires farm administrative privileges to deploy the changes while site pages can be deployed by site       collection administrators/end-users.
  • Runtime
    • URL – An application page stored in the _layouts directory on each WFEs which would add “_layouts” in URL, while site page URLs can have fully customized business URLs. This can be go-no go decision with application pages in most cases.
    • Performance – Because application pages are parsed and compiled as classic ASP.NET pages, they run faster than site pages. SPPageParserFilter parses and compiles the page into DLL. Customized Site Pages impact performance and scalability since they are rendered, runs in no-compile mode, and retrieved from the virtual file system.
  • Upgrade
    • Maintaining or deploying updated Application page is much faster than maintaining Site Page because deployment method requires retracting/re-deploying site page on each site compare to application page on each application. This can be go-no go decision with site pages in thousands of sites deployment.
  • Cleanup
    • Application pages are removed from the file system from the LAYOUTs folder when the solution is retracted but Site Pages requires Feature Receiver to delete the folder containing site pages in the content database during feature deactivation process. Site page templates gets retracted from FEATURES directory same way as application pages when solution is retracted.

Additional References:

  • Chapter 2 and Chapter 3, Inside Microsoft Windows SharePoint Services 3.0, MS Press, Ted Pattison. This is still one of the best books on SharePoint and applicable to SharePoint 2010.
  • Sahil Malik’s Apress Book – Microsoft SharePoint 2010 Building Solutions for SharePoint 2010, Jun 2010, Page 95. Sahil has demonstrated design pattern of how to build Site Pages with Web Parts to support code-behind in his book.
  • Brilliant resource, Most complete I have found so far, App page vs Site pages => http://srisharepointdevelopment.blogspot.com/2011/07/app-page-vs-site-pages.html

Posted in Dev General | Leave a Comment »

What really happens during SharePoint 2010 Solution Deployment/Retraction and Feature Activation/Deactivation Process?

Posted by nikspatel on December 5, 2011

Have you ever wondered what really happens when you deploy/retract SharePoint WSPs and Activate/Deactivate site collection or sub site level features at the farm level? As you execute different PowerShell commands or activate/deactivate features from browser interface, SharePoint 2010 makes several changes at the different places on the servers and databases.

This article provides high level overview of what really happens when you execute different farm level PowerShell commands. Hopefully it will be helpful. 

  Central Admin Site/Web Level Features GAC Web.Config 14-Root Features SharePoint Config DB, Objects Table – Solutions SharePoint Config DB, Objects Table – Features Web App Content DB, Features Table
Add-SPSolution Solution Added but Not Deployed N/A N/A N/A N/A Yes – Solution Definition Added N/A N/A
Install-SPSolution Deployed to Web App Installed Feature Yes – DLLs Added Yes – Safe Control Entries Added Yes – Features Added Yes – Solution Definition Still Exists Yes – Feature Definition Added N/A
Enable-SPFeature Solution Still Deployed Activated feature to Site/Web Yes – Still Exists Yes – Still Exists Yes – Still Exists Yes – Solution Definition Still Exists Yes – Feature Definition Still Exists YES – Feature Activation Link Added
Disable-SPFeature Solution Still Deployed Deactivated feature from Site/Web Yes – Still Exists Yes – Still Exists Yes – Still Exists Yes – Solution Definition Still Exists Yes – Feature Definition Still Exists NO – Feature Activation Link Deleted
UnInstall-SPFeature Solution Still Deployed Uninstalled feature Yes – Still Exists Yes – Still Exists Yes – Still Exists Yes – Solution Definition Still Exists No – Feature Definition Deleted N/A
UnInstall-SPSolution Retracted from Web App Uninstalled feature No – DLLs Deleted No – Safe Control Entries Deleted No – Features Deleted Yes – Solution Definition Still Exists No – Feature Definition Deleted N/A
Remove-SPSolution Solution Deleted N/A N/A N/A N/A Yes – Solution Definition Deleted N/A N/A
 
 
 

Posted in Dev General, Dev PowerShell | Leave a Comment »

Make Custom Landing Page As Default Page of the SharePoint Team Site same as Wiki Home Page

Posted by nikspatel on October 24, 2011

Have you ever looked at how Microsoft has implemented SharePoint 2010 team site default home page as wiki home page? Whenever end-user provisions new site based on team site template, Microsoft not only creates the new team site but activates the web level feature called “Wiki Page Home Page”, which would provision two new document libraries called “Site Pages” and “Site Pages”, deploys the new home page called “Home.aspx”, and sets the “/SitePages/Home.aspx” as a default home page.

What if you ever wanted to use same pattern? Say you have requirements where you would need to provision new sites and site landing pages, and automatically redirect users to new landing page as a home page. To implement similar pattern, follow following steps.

Step 1 = Create New visual Studio Empty SharePoint Solution for Custom Site Landing Page – CustomHomePage and create New Custom Site Landing Page as a site level page using Module element – Home/Home.aspx.

Step 2 = Implement feature receiver for the feature deploying custom landing page. Add following code in both feature activated and feature deactivating events. During activation process, you can use WelcomePage property of the SPFolder object to set new page as home page. During deactivation process, you can rollback and set the default.aspx as landing page.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    using (SPWeb spWeb = (properties.Feature.Parent as SPWeb))
    {
        //Make custom landing Page as Site Home Page             
        SPFolder rootFolder = spWeb.RootFolder;
        rootFolder.WelcomePage = "Home/Home.aspx"; //custom landing page    
        rootFolder.Update();
    }
}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    using (SPWeb spWeb = (properties.Feature.Parent as SPWeb))
    {
        //Make default site page as Site Home Page
        SPFolder rootFolder = spWeb.RootFolder;
        rootFolder.WelcomePage = "default.aspx"; //standard team site default page
        rootFolder.Update();
    }
}

Step 3 – Deploy the CustomHomePage solution and activate the Custom Home Page feature. This feature would deploy the Home/Home.aspx page to the site and set custom page as a default page.

Step 4 – Accessing root URL of the site where custom solution deployed should take you to the Home/Home.aspx as landing page. It’s that easy.

Additional References

 - http://stackoverflow.com/questions/1649833/replace-the-default-page-in-a-sharepoint-website
 - http://attis.org/blogs/dan/archive/2008/10/29/how-to-change-the-default-page-of-a-sharepoint-site-using-a-feature.aspx

Posted in Dev General | Leave a Comment »

Master List of SharePoint 2010 Custom Development Best Practices

Posted by nikspatel on June 22, 2011

If you are new to SharePoint 2010 development, building custom solutions based on the SharePoint 2010 framework is never easy. Sometimes list of types of custom components you can build on top of SharePoint 2010 Foundation framework is overwhelming. For the novice or even for the experienced SharePoint developers, it would be easy to get lost into specifics of the SharePoint 2010 development. Every kind of custom SharePoint components like web parts, visual web parts, application pages, site pages, master pages, page layouts, content types, list definition, site definitions, workflows, event receivers, lists, content types, field types, etc. brings their own special challenge.

As a developer, as we focus on solving business problems with custom SharePoint solutions, sometimes it’s too late to realize that it would be great if you have known some of the best SharePoint development practices  and hoping to assure that you are following industry best practices and building upgradable solution.

I am going to use this blog entry to compile some of the SharePoint 2010 development best practices I try to follow whenever I am customizing SharePoint environments using solutions and features framework. I am planning to update this page over the time.

  1. Don’t ever change the files in the out of the box SharePoint Root (14-Hive) directory.
  2. Never build your SharePoint development environment on the host machine. Use the Virtual Machine instead. Virtualized environment promotes portability, playground as sandbox, and allows quick and easy way to snapshot the development environments.
  3. Leverage WSPs (solutions and feature framework) while deploying and packaging code from development to staging to production environment.
  4. Make sure solutions have proper consistent naming convention e.g. OrganizationName.BusinessSolution.<ProjectName>
  5. Make sure solutions have proper feature name and description. Feature name and description would be visible on the site collection and site features page.
  6. Make sure custom code is compiled and packaged in release mode.
  7. Use SPUtility, SPUrlUtility, and HttpUtility if you can. e.g. Use SPEncode to encode the HTML and URL encoding.
  8. Since URLs can change between different environments, use site.serverrelativeurl instead of site.url to build the URL in code.
  9. Don’t forget to dispose the newly created SPWeb and SPSite objects. If you create an object using “new”, you must dispose it. (e.g. SPSite site = new SPSite(url) or SPWeb web = site.OpenWeb()). Although SPWeb and SPSite objects use minimal managed memory, it allocates substantial unmanaged memory. You must free up unmanaged memory allocated during creation of SPWeb or SPSite objects by disposing the objects. Best practice is to instantiate objects with “using” keyword in C#.  (e.g. using (SPSite spSite = new SPSite(url))).  Additionally, always run solution against SPDisposeCheck utility to ensure disposing all the objects properly before production deployment. (http://code.msdn.microsoft.com/SPDisposeCheck)
  10. Don’t dispose the SPContext.Current.Site or SPContext.Current.Web object. It will be disposed automatically by the runtime. e.g. Do not use “using” keyword with the object referenced through SPContext  (e.g. don’t use using(SPWeb spWeb = SPContext.Current.Web))
  11. Don’t use SPContext.Current.Site or SPContext.Current.Web objects in the Feature Receiver to access current instance of SPWeb or SPSite . If you ever try to activate/deactivate features using PowerShell, SPContext would fail because it’s available only in the browser context. Instead use properties.Feature.Parent to access current instance of SPWeb or SPSite object. For Site collection level feature, it would return SPSite and for web level feature, it would return SPWeb object. (e.g. use using (SPWeb spWeb = (properties.Feature.Parent as SPWeb)))
  12. Plan to install SharePoint Manager 2010 from the codeplex. It is a SharePoint object model explorer and enables you to browse every site properties on the local farm by browsing through SharePoint Internals.(http://spm.codeplex.com/)
  13. Use SharePoint Developer Dashboard to Investigate the Page Performance bottlenecks. It gives detailed information on resource usage, performance, user interactions and error trapping. Use SPMonitoredScope code block to generate the custom logged counters on the Developer Dashboard. Please note that you can enable the Developer Dashboard at the farm level and never enable it in production environment.
  14. Use SPGridView instead of standard ASP.NET Gridview to inherit the SharePoint CSS, Look and Feel, and Column filtering mechanism. On other side, Use standard ASP.NET Gridview instead of SPGridView to full control over the tabular design and functionality.
  15. Use the List Event Receivers to execute the code immediately. Workflows can perform similar function but it will run as a timer job which may delay the code execution.
  16. Use SharePoint Site Property Bag to classify the sites and persist site level metadata. You can either use SPWeb.Properties (Microsoft.SharePoint.Utilities.SPPropertyBag Object) or SPWeb.AllProperties (System.Collections.Hashtable Object) or Site      Property Bag Configuration Tool – http://pbs2010.codeplex.com/. SPWeb.Properties considered as legacy approach since it stores key and value in lowercase. SPWeb.AllProperties keeps casing of key and value intact. If you don’t care about the persisting case, plan to use older method SPWeb.Properties instead of newer method SPWeb.AllProperties. Here is the reason why – http://www.novolocus.com/2010/12/22/stupid-spweb-properties/
  17. Don’t build State Workflows in the SharePoint 2010 using Visual Studio 2010.  State workflows may NOT be upgradable because they are not available in the .NET 4.0 which might be foundation framework for the next version of SharePoint.
  18. Use field controls on the WCM sites instead of web parts because you won’t have page history with web parts.
  19. For the list data access using server side object model, Use LINQ if you can, CAML if you must. Another argument is – Use CAML for fastest performance and LINQ for object oriented development.
  20. Do not instantiate SPWeb, SPSite, SPList, or SPListItem objects within a list event receiver. It would cause significant performance overhead due to additional round trips to the database and fail other registered event receivers during subsequence update calls. Instead retrieve the SPWeb or SPListItem from SPItemEventProperties. (e.g. use SPWeb web = properties.OpenWeb() or SPListItem item = properties.ListItem)
  21. Do not use SPList.Items while accessing list items using server side object model and try to avoid SPList.Items in a loop expression. SPList.Items iterates through all list items from all subfolders and all fields in the list item. To retrieve the list items, instead use SPList.GetItems(SPQuery query).
  22. Avoid deploying DLLs to the GAC (this has risks because of security override), instead deploy it to the web application IIS bin directory and use custom CAS policies.
  23. Target farm level solutions to the specific web application instead of deploying to all web applications unless you are deploying new feature to all the applications in the farm. This way custom feature for the specific web application won’t available on site collection features page or site features page on all the web applications in the farm.
  24. Build Sandboxed solutions over farm level solutions for site collection specific custom solutions to balance business agility and IT stability. Understand the limitations of the sandbox solutions. Create site collection resource quota templates in the central administration. Another argument against sandbox solutions is it has resource quota points estimation issues for heavily collaborated sites.
  25. Plan to disable the SharePoint Designer at the farm level and enable at the web application and site collection level as needed.
  26. Instead of Custom Site Definition, use Web Template or Feature Stapling capabilities to add custom features on the out of the box site definition. I would also prefer Custom Coded Site Templates from scratch by creating site based on team or blank site template and activate features as needed. Also, word of caution – Never change out of the box site definition.
  27. Deployment discipline – During the deployment and retraction process while updating or upgrading custom solutions, please use the correct older version of WSPs to retract the solution before deploying or upgrading the custom code with newer version of WSPs. This would ensure activating or deactivating features reference correct version of WSPs.

Hope it will be helpful.

Posted in Dev General | Leave a Comment »

Use SPLongOperation to display SharePoint Processing Page for Lengthy Operations and avoid Timeout Issues

Posted by nikspatel on April 27, 2011

There are many great hidden features in SharePoint like Skewer Click in SharePoint Designer 2010 or Related Item Views in SharePoint Designer 2010, SPLongOperation is just one of those hidden features. SPLongOperation may be unknown for many SharePoint developers even though it exists since MOSS 2007 days but it’s part of daily end-user life. SPLongOperation is nothing but spinning wheel animated image screen shows up for many of lengthy SharePoint operations like site creation, site redirection, or site deletion.

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splongoperation.aspx

As a SharePoint Developer, you can wrap your lengthy operations code with the SPLongOperation to display the spinning wheel processing screen whenever you are executing long duration code-block to improve the user experience. After invoking SPLongOperation object, you can start and stop the long operation using Begin() and End() methods. Alternatively, you can use the LeadingHTML and TrainingHTML properties to customize the message on the processing screen.

protected void btnProvisionSites_Click(object sender, EventArgs e)
{
    //Long Operation Code
    using (SPLongOperation longOperation = new SPLongOperation(this.Page))
    {
        //Custom Messages on the Spinning Wheel Screen
        longOperation.LeadingHTML = "Provisioning Sites";
        longOperation.TrailingHTML = "Please wait while the sites are being provisioned.";

        //Start the long operation
        longOperation.Begin();

        //Your Long Operation Code Goes Here...
        // e.g. Site provisioning code

        //End the long operation
        string redirectURL = SPContext.Current.Web.Url + "/SitePages/SiteProvisioning.aspx";
        longOperation.End(redirectURL);
    }
}

Please note that SPLongOperation would require redirecting the user to the destination page. This destination page can be anything from confirmation page to the same page where execution process started. If you are performing error reporting during page post back, I would recommend that you use the HttpContext.Current.Cache to cache the error messages and display the error messages during page loading process.

Although it’s not documented anywhere, another major benefit of SPOperation is it resolves typical SharePoint timeout issues. As many of us knows, SharePoint requests would timeout after 6 minutes and these executionTimeout settings are set in the web.config file located at the <SharePoint Root>\Template\Layouts directory.

<system.web>
    <compilation batch="false" batchTimeout="600" maxBatchSize="10000" maxBatchGeneratedFileSize="10000" />
    <customErrors mode="On" />
    <httpRuntime executionTimeout="360" />
    <globalization fileEncoding="utf-8" />
</system.web>

http://geekswithblogs.net/DennisBottjer/archive/2009/04/13/increase-sharepoint-execution-timeout.aspx

Unlike above link, I wouldn’t recommend updating SharePointRoot web.config settings but I would suggest using SPLongOperation to execute lengthy operations. I was able to run very complex custom site provisioning request without timing out for more than 10 minutes using SPLongOperation. Without SPLongOperation, same code would timeout after 6 minutes.

References: There are multiple ways you can use the SPLongOperation as given in following articles -
http://blogs.inetium.com/blogs/bcaauwe/archive/2007/12/20/splongoperation-sharepoint-spin-wheel.aspx
http://howtosharepoint.blogspot.com/2010/04/how-to-programatically-show-processing.html

Enjoy..

Posted in Dev General | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.