Wednesday, April 4, 2012

Hide Site Action and Site Settings link

We know there is a straight way to add a Custom action under a Site Actions menu or in a Site settings page. You just need to develop a feature with a custom action and deploy it.

I got a requirement to hide a custom action under the Site Actions menu. I initially thought of doing it in using my familiar JQuery hack and hide dirty way. Then something I found that there is a straight way available in SharePoint. Just develop a feature with a element file and add the below code.

<HideCustomAction
  GroupId = "SiteAdministration"
  HideActionId = "DeleteWeb"
  Id = "HideDeleteWeb"
  Location = "Microsoft.SharePoint.SiteSettings">
</HideCustomAction>
Here in the above code:

GroupId: Self explanatory for a developer. You can find the group id herehttp://msdn.microsoft.com/en-us/library/bb802730.aspx
HideActionId: The id of the custom action that needs to be hidden. This can be found if you search in the features folder(in element file).
Id: Some Unique id(optional).
Location: From Where is should be hidden.
Hope this helps someone.

Wednesday, August 31, 2011

Error updating User Profile property on commit

Error: Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb.


I saw many people has came across this is error when updating user profile property values, but I couldnt find a solid solution to this issue. So thought of posting a article on this one. The error may be misleading. Many think web.AllowUnsafeUpdates=true will solve the issue. But it wouldn't because this update will not have any impact on the User Profile Service application. 

Try the below code, it should solve the issue.





The difference here is SPContext.Current.Web.AllowUnsafeUpdates=true will update the current user profile to allow updates. Also make sure that there is no context given when Instantiating UserProfileManager object as it gets populated automatically when run on a personal site context. 

Tuesday, August 30, 2011

Hide Any Site template in Create Site section- SharePoint 2010

We may need to block creation of sites based on certain templates. For example my organisation does not like the employees to create blog site of their own in their personal mysite. 

There is a quick and dirty way to modify the webtemp.xml file to hide the template we dont want to show up. Its never a good approach to modify the default SharePoint config files. Also webtemp.xml file modification will affect farm level settings.

In SharePoint 2010 we can hide the templates of desired nature from the Create site page so no one can create site based on the particular template. This can by achieved by creating a new feature with a event handler code.

1. Create a new Empty SharePoint project.
2. Add a new feature element.Scope it to Web
3. Add a new event receiver to that feature element.
4. Paste  the below code(this code will hide the blog template at the site level)

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = properties.Feature.Parent as SPWeb;
SPWebTemplateCollection existingWebTemps = web.GetAvailableWebTemplates(1033); ;
Collection<SPWebTemplate> newWebTemps = new Collection<SPWebTemplate>();
for (int i = 0; i < existingWebTemps.Count; i++)
{
if (!existingWebTemps[i].Title.ToLower().Contains("blog"))
{
newWebTemps.Add(existingWebTemps[i]);
}
}
web.SetAvailableWebTemplates(newWebTemps, 1033);
web.Update();
}

5.Deploy the solution and activate the feature. You will no longer see the blog template visible to the user in the Create site page.

6. To revert back and to show all the templates use the below code at Feature deactivating event.

 web.AllowAllWebTemplates() ;

Saturday, August 6, 2011

Get User profile using Console App- Object reference error at Server context

Today I was trying to retrieve user profiles properties using a console application. Its a very simple application just pulls some metadata from the userprofilesmanager. Previously I have get and set profile properties in my SharePoint application many times. Thought it would be a piece of cake for me. Not though.

This is the code I have written in the program.cs. But to my surprise I was getting object reference error. I was thinking that url might be the wrong thing. But its not.


            SPSite site = new SPSite("http://suresh-pc:100/default.aspx");
            ServerContext context = ServerContext.GetContext(site);
            UserProfileManager upm = new UserProfileManager(context);
            UserProfile profile = upm.GetUserProfile("moss/suresh");

This error is a misleading one. You dont have permission to pull data from User Profile Service application basically.

Go to Central Admin- Manage Service applications- Click User Profile Service Application(click the row not the link).- In the ribbon select Manage Permmissions


Provide full permission for the user trying to access the User profile manager.

Build the application and run again.

Saturday, July 16, 2011

SharePoint 2010 Content Editor webpart

I am a very big fan of Content Editor Webpart in Moss 2007. I have done many site customization's using CEWP in SharePoint 2007. Place a new html file, hack DOM elements using JQuery and modify the html elements, javascript etcs., I almost love it. Even I have developed a complete site using few CEWP's in SharePoint 2007.

I was hoping SharePoint 2010 would offer much more functionality to CEWP. But to the sad part it has worsened it usability. When I first tried inserting a CEWP in my SharePoint 2010 site, I virtually struggled to use it. I was trying to figure our how to insert my custom html. There was no Source editor in WebPart editor panel.

Edit Html source has been moved to the Ribbon. You have to click the "HTML-EditHTMLSource" and place your html.


And the worst part is now you cannot place any javascript code in the source editor(edit html source).

To place a javascript code you need to create a text file or html file and put your code there. Save it to some document library and link the file as show below in the editor pane


I like it in one way. We can checkin the code in Source control and deploy the text file or html file to the layouts folder and we can link it in our webpart so that we can have a backup of the code.

Friday, July 15, 2011

Custom Workflow Activity for SharePoint Designer 2010

Back in Moss 2007 we had the feature of creating a new custom activity for SharePoint designer. I never tried that. Yesterday I had to present a POC to a customer on Custom activity for SharePoint designer 2010. The requirement is pretty simple.

User will be presented with a simple list. On creating of a new item, a approval workflow will be triggered. On approval, a new subsite has to be created. So I thought creating a custom activity in designer and using that to create a designer workflow would to do the trick.

I will describe with steps to create a custom activity for a SharePoint designer 2010 below. Since creating a approval workflow is simple I m not going to cover it :-)

1. Open Visual Studio
2. Select the “File->New->Project”
3. For template, select “Workflow->Workflow Activity Library” ( If you don't see this template, then target your environment to .Net 3.5.)
4. For Name, type “CustomActivities”
7. Rename Activity1.cs to CustomAction.cs
8. Right click the project, select “Add Reference”
9. Add the following references:
o C:\program files\common files\microsoft shared\web server
extensions\14\isapi\Microsoft.SharePoint.dll

I dont want to jump into full code directly. Lets go Step by Step.

Create a new function which creates new site




To make your custom code we need to override the Execute method of System.Workflow.Activities.
Call our CreateSite() function within the Execute method.



We have created a simple activity which is good enough to create a new SharePoint site. But if you notice I have hardcoded the siteTitle and siteURLRequested. Not good practice ah..

Lets create a new set of properties to get and set values for our title and url parameters. Before that to make the properties to be picked by the SharePoint designer we need to create Dependency properties as below.


   public static DependencyProperty TaskTitleProperty = DependencyProperty.Register("TaskTitle", typeof(string), typeof(CustomAction));

        [Category("Cross-Site Actions"), Browsable(true)]
        [DesignerSerializationVisibility
          (DesignerSerializationVisibility.Visible)]
        public string TaskTitle
        {
            get
            {
                return ((string)
                    (base.GetValue(CustomAction.TaskTitleProperty)));
            }
            set
            {
                base.SetValue(CustomAction.TaskTitleProperty, value);
            }
        }

Note that we need to prefix the DependencyProperty with the word "Property" else VS2010 is going to shout at you.

Now use the dependency property created in our CreateSite method. Overall code looks like below.


So create another dependency property for siteUrlRequested as well which i m not doing here. Sign the assembly and build it. Place the assembly in GAC using gacutil.exe(never  install manually).

We are done with the coding part. Now lets register our newly created activity with the SharePoint designer.

If you navigate to 14 hive folder under 1033/Workflows/ you will find MOSS.ACTIONS and WSS.ACTIONS.

As a good housekeeping we will create a new ACTIONS file. Say CustomAction.ACTIONS.

Place the below xml in it to register our custom activity.


<WorkflowInfo>
  <Actions Sequential="then" Parallel="and">
     <Action Name="Create Site"
    ClassName="CustomActivities.CustomActions"
    Assembly="CustomActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"
    AppliesTo="all" Category="Custom Site Actions">
        <RuleDesigner 
           Sentence="Create a Site titled %1">
           <FieldBind Field="TaskTitle" DesignerType="TextArea" 
              Id="1"/>
        </RuleDesigner>
         <Parameters>
            <Parameter Name="TaskTitle" Type="System.String, mscorlib" 
              Direction="In" />
         </Parameters>
     </Action>
  </Actions>
</WorkflowInfo>

Save the file and close.  We have a very last step that to register our dll as a Authorized type with my webapplication. Navigate to web.config in the file system and make the below entry.

<authorizedType Assembly="CustomActivities, Version=1.0.0.0, 
   Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"     
   Namespace="CustomActivities" TypeName="*" Authorized="True" />
Save the web.config. There you go..
Perform and IISReset and load the designer. You will see a new activity added under "Custom Site Actions"

Saturday, June 11, 2011

What does IISReset really do

IISReset- perhaps the first lesson every SharePoint developer and administrators learn.
But when we start to do extreme programming(really lol), we eventually forget to do this.. cool lemme come to the meat of the subject..

Last week I have to support from development side for a uat deployment of our new solution. Every thing worked well in my environment as always. My development environment is a standalone farm. testing, uat and prod are medium farms..

We deployed the code. loaded the site..Some code error..ahhh.. i could see clearly from the error that the new code is not referred by the page. We did redeployment as I insisted  confidently that Web hosting team didn't do the deployment as I specified in the install notes. Whenever something go wrong then its other mistake. lol...

So we deployed the solution..again same error. Now Web hosting team hit me back stating its my error.

on multiple refresh of the page, i saw the site loading correctly on few instances. ahhhh i caught the culprit. "DLL caching". I asked to do IISReset on all the WFE's. It worked.

So whats the issue.

Whenever we deploy a new code which has a dll we probably need to do a IISReset.
You know why, SharePoint when hosted in IIS caches the dll from GAC and renders the page from it. So we have to tell the GAC to take the new dll from GAC after new deployment of our code.

Do we need to do IISReset on all new deployment. Answer is no.

1. When we do partial trusted solution SharePoint automatically picks up the new dll from the bin. We dont need an IISReset.
2. When we deploy features, we dont need it unless and until it doesn't has any code.

Most of the prod servers doesn't allow us to do IISReset. Then how to tell my IIS to take the new dll from the GAC.

Use the below script to refresh the application pool.


Option Explicit
'*** spsapppoolrecycle.vbs
'*** Script to recycle Sharepoint Portal Server application pool
'*** For use when deploying updated version of Webparts in the GAC
'*** Author: Michael Christensen, mac@landscentret.dk
'*** Provided AS IS with no warranties
'*** Heavily based on this posting by David Wang:
'*** http://tinyurl.com/4k26n
Const WEBSITEID = 1
Dim objApp
Dim AppPoolId
Dim objAppPool
Set objApp = GetObject("IIS://localhost/w3svc/" & WEBSITEID  & "/root")
AppPoolId = objApp.AppPoolId
WScript.Echo "AppPoolID: " & AppPoolId
Set objAppPool = GetObject( "IIS://localhost/w3svc/AppPools/" + AppPoolId )
objAppPool.Recycle()
WScript.Echo "AppPool recycled."

The script assumes that Sharepoint is installed on the virtual server with ID 1. This will usually be the case, otherwise the actual ID could probably be determined programmatically.

Probably next time when you deploy the new code,,think whether is necessary to do an IISRESET after deployment.