Showing posts with label SharePoint 2010 API. Show all posts
Showing posts with label SharePoint 2010 API. Show all posts

Monday, August 27, 2012

Tips to change SharePoint 2010 behavior without change out of box UI - Part II SPCustomLayoutsPage

Modifying the files that are installed by SharePoint is not supported to change the behavior of the SharePoint. As we discuss before, one of the best practices is to use the tagmapping functionality to instruct the parser to substitute a different derived type implementation whenever it encounters the type being mapped. It is quite useful to redirect SharePoint Out of box to customized one. However, this mechanism will be difficult if you need to customize the behavior of out of box application pages such as AccessDenied, Confirmation, Error, Login, RequestAccess, Signout and WebDeleted. In this blog, we will introduce the new SharePoint 2010 Powershell Set-SPCustomLayoutsPage that will replace application pages in layouts directory that is supported by Microsoft.

Here is the user case for our company - users want to customize the access denied page to have the following behavior and we also prefer to apply the same company branding to the page.

Include the following sentence You are requesting access to highly sensitive company content, which requires a business justification, and in some situations, approval from your supervisor(s). In order for your request to be properly and quickly assessed, please specify what project you are working on, the specific content in which you are interested, and (most importantly) why you need it.”
  
The solution provided by SharePoint 2010 is very simple and here are the steps. We use RequestAccess page as example.

1. Copy the access deny application page from layout folder and copy/modify to incorporate the change required including the branding
2. Deploy the custom Request Access page to custompages folder under layouts directory
3. Set custom page for SharePoint to use instead

Set-SPCustomLayoutsPage -Identity "RequestAccess" -RelativePath "/_layouts/custompages/reqacc.aspx" -WebApplication "{replace with web app url}"

Now the access denied page will use the custom one instead of the OoB one. You could verify what custom page SharePoint is using by typing the powershell Get-SPCustomLayoutsPage command.

You might also change it pro grammatically through IHttpModule or event receiver that might be fit into your use cases. If you need to have a different access denied page for different site collection, you might add logic to the custom page or createdifferent folder each site collection

In addition, if you need to display more information to the customized access denied page such as owner list, you could use server object model API.



Thursday, June 16, 2011

Feature with Id is not installed in this farm error when using Client Object Model to activate features

We have a situation that we have to enable a site collection feature from Client Object Model (OM) instead of server side API. We run into the error when feature is been activated. Here is the summary to reproduce the issue.

After setting up SharePoint 2010 Client Object Model Console Application with 64 bit platform and .Net 3.5,  we run into the error when feature is been activated.

Here is the Error Message: Feature with Id '859d22a7-0c7b-476e-afd4-420fd2955260' is not installed in this farm, and cannot be added to this scope.

E:\Harry\DEV\Student\ClientOM\ClientOM\bin\Debug>ClientOM.exe
Unhandled Exception: Microsoft.SharePoint.Client.ServerException: Feature with Id '859d22a7-0c7b-476e-afd4-420fd2955260' is not installed in this farm, and cannot be added to this scope.
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
   at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()
   at ClientOM.Program.Main(String[] args) in E:\Harry\DEV\Student\ClientOM\ClientOM\Program.cs:line 28


Here is the source code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Client;


namespace ClientOM
{
    class Program
    {
        static void Main(string[] args)
        {

            // Get the client context
            using (ClientContext clientContext = new ClientContext("http://sbx01/sites/Harry/"))
            {
                // Load the features
                Site clientSite = clientContext.Site;
                FeatureCollection clientSiteFeatures = clientSite.Features;               

                Guid FeatureId = new Guid("859d22a7-0c7b-476e-afd4-420fd2955260");
                clientContext.Load(clientSiteFeatures);
                //clientContext.ExecuteQuery();
                // Activate the feature
                clientSiteFeatures.Add(FeatureId, false, FeatureDefinitionScope.Site);
                //clientSiteFeatures.Remove(FeatureId, false);
                clientContext.ExecuteQuery();
            }

        }
    }
}


We can activate the feature through the UI and Powershell on the same server running the code. In addition, We can use the same code to deactivate the feature by commenting out the add method and uncommenting the remove method. Someone has also raised similar issue here.

We also noticed another similar code but have not test it. Many people also reported the same issue here.

We are wondered how can a site or web feature be activated using the Client Object Model?



Please let me know if you have solution. Thanks.

Tuesday, April 26, 2011

“Save Conflict" error when creating list or document library with "List Added Event Handler"

After adding "List Added Event Handler" to our SharePoint 2010 feature to update the list properties after listed created, we run into major issue during any list or document library creation by choosing below templates. The issue is we are getting "Save conflict" unexpected error. It is not consistent but happens much more frequently on “Calendar list”. The following list template will have such issue.
  • Document library
  • Form library
  • Wiki page library
  • Picture Library
  • Reports library
  • Calendar list


Users will get the error as indicated int he screen shot.

The error log is identical to the error people reported.

Microsoft.SharePoint.SPException: Save Conflict
Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.



This is a very typical error occurs in SharePoint 2007 for asynchronous event handler. Due to SharePoint and the event receiver code trying to update the item at the same time. After debugging this issue and working with Microsoft, we have finally resolved it on SharePoint 2010. Here are the three changes you should try.

1.  Disable Event Firing when update the list. Please note this.EnableEventFiring() has been deprecated and the code for SharePoint 2010 is:
     EventFiringEnabled = false; 
     // Business logic here  
     EventFiringEnabled = true;

2. Use new SPWeb object for each list modification. The code should look like this if you apply #1 and #2 roles.

try
{
       // Use new SPWeb object for each list modification.
       SPWeb web = null;
       base.ListAdded(properties);

       //Disable Event Firing when update the list
       EventFiringEnabled = false;  
       properties.List.ParentWeb.AllowUnsafeUpdates = true;
       web = properties.Web.Site.OpenWeb(properties.Web.ID);
       SPList list = properties.List;
       list.Title = "Correlation Id- Save Conflict error";
       // Other actions to add policy to the list
       // Action to add tagging to the content
       list.Update();
       properties.List.ParentWeb.AllowUnsafeUpdates = false;
       EventFiringEnabled = true;
}


3. If you still have save conflict issues like we did, in SharePoint 2010, we have the option to make these kind of events Synchronous by adding this in the Element.xml file of the event receiver while we are registering it.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers >
      <Receiver>
        <Name>MyCompanyListReceiverListAdded</Name>
        <Type>ListAdded</Type>
        <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
        <Class>mycompany.com.sp.features.mycompanyListReceiver.mycompanyListReceiver</Class>
        <SequenceNumber>10000</SequenceNumber>
        <Synchronization>Synchronous</Synchronization>
      </Receiver>
  </Receivers>
</Elements>


After doing adding these changes, we are able to resolve the issue and enjoy the list event.