Thursday, 7 February 2013

Upgrade a feature with PowerShell

When you wnat to add new fields to an existing content type in SharePoint you make a new version of the feature - an upgraded version. You deploy the new wsp package with an SPUpdateSolution command.
But you are not done yet! It is only deplyed to the server. You must tell SharePoint explicitly too look for a new version of the feature, and upgrade the feature to this version.
Oddly you cannot do this through the interface - you must do it through code. This can be done in C#, (Visual Basic?), or in PowerShell.

To upgrade a feature in PowerShell you do this:

  • $s = Get-SPSite -Identity 'insert url of the web where the solution is deployed'
  • $features = $s.QueryFeatures('web',$true)
  • foreach($feature in $features){if($feature.DefinitionId -eq ‘72dc4341-4404-413c-b8ab-22e5723fdbec'){$feature.upgrade($true)}}

This will upgrade the feature with id "72dc4341-4404-413c-b8ab-22e5723fdbec".

Monday, 4 February 2013

Your Search Cannot Be Completed Because This Site Is Not Assigned To An Indexer

I had this very annoying error when trying to search my SharePoint Server 2010 single server development machine through code (using the KeywordQuery and FullTextSqlQuery classes).
The search crawler was running and searching from the SharePoint UI returned the expected results.

What you need to do is to...
  • Start the "SharePoint Foundation Search"service.
  • then go to the select "Manage Content Database Settings" page and select the server running the SahrePoint foundation search service at the drop down menu

Central Administration -> Application Management -> Manage services on server


Central Administration -> Application Management -> Manage Content Database -> (click on database name)



This was not intuitive to me as I was running SharePoint Server Enterpise. And the "SharePoint Server Search" service was already running. Also it strikes me as odd as you do not have the FullTextSqlQuery in SharePoint foundation - you need to have the Enterprise version.

Close and re-open web parts

If you wanna hide a web part for a while so that you can re add it to the page later without having to reconfigure all of it settings this is what you do:

Close the web part from the web part drop down menu (the arrow that appears in the top left cornor of the web part when you hover over it):




When you later wanna re enable it, you click add web part as normal,k however this time you click the "Closed webparts group" and add it from here:


Friday, 25 January 2013

Disable "Attach Security Warning" in Visual Studio 2010 when attaching debugger

In regedit change the following key from 0 to 1:


HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\Debugger\DisableAttachSecurityWarning

The annoying security warning when attaching the debugger

Set the "DisableAttachSecurityWarning" to "1" in the registry database


Thursday, 3 January 2013

Adding a new field to a content type by upgrading a feature

Working with content types that are already deployed can be tricky.
Working with feature upgrade is a pain in the b... as well. In fact I'm amazed how poorly it is handled in SharePoint taking into consideration how common a task it should be.

Quite often you need to add an extra field to a content types which has already been deployed and associated with a list.

After a lot of trying I finally found a solution that is working for me.


Vesa Juvonen has made a very good blog on the subject here:

WebTemplate training materials – Lab 4 - Upgrading existing sites with feature versioning


It's a fairly big and complex thing, so will not rewrite it all here.
But in short terms the things you have to do and be aware of is:

  • Make a new Elements.xml for your new field.
  • Do NOT add the field to the existing content type Elements.xml file!
  • In the xyz.Template.xml file for your feature that deploys your content type (= the feature you want to upgrade), add UpgradeActions, ApplyElementManifests, CustomUpgradeAction (see snippet below)



  <UpgradeActions>
    <VersionRange BeginVersion="0.0.0.0" EndVersion="3.0.0.0">
     
      <ApplyElementManifests>
        <ElementManifest Location="FieldsV2\Elements.xml" />
      </ApplyElementManifests>

      <CustomUpgradeAction Name="AddFieldToContentType">
        <Parameters>
          <Parameter Name="FieldId">58757B21-3BDD-4AC7-BCE5-ACFC025735E2</Parameter>
          <Parameter Name="ContentTypeId">0x0100906acb18801a416680c0017602a462d7</Parameter>
          <Parameter Name="UpdateChildren">true</Parameter>
        </Parameters>
      </CustomUpgradeAction>
     
    </VersionRange>


  • Add an event reciever for the feature and implement the FeatureUpgrading method. Here programmatically add the new field to the content type.


        public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        {
            SPWeb web = ((SPSite)properties.Feature.Parent).RootWeb;
            switch (upgradeActionName)
            {
                case "AddFieldToContentType":
                    string fieldId = parameters["FieldId"];
                    string contentTypeId = parameters["ContentTypeId"];
                    bool updateChildren = true;
                    bool flag;
                    updateChildren = bool.TryParse(parameters["UpdateChildren"], out flag);
                    UpdateManager.AddFieldToContentType(web, contentTypeId, fieldId, updateChildren);
                    break;

                default:

                    break;
            }

        }


        public static void AddFieldToContentType(SPWeb web, string contentTypeId, string siteColumnId, bool updateChildren)
        {
            try
            {
                SPContentType type = web.ContentTypes[new SPContentTypeId(contentTypeId)];
                type.FieldLinks.Add(new SPFieldLink(web.Fields[new Guid(siteColumnId)]));
                type.Update(updateChildren, updateChildren);
            }
            catch (Exception ex)
            {
                // TODO write to log
                //throw;
            }
        }

  • Now implement the FeatureActivating method in a similar manner in order to make the upgraded functionality of the feature available for new installations of the feature as well (else it will only get added when the feature is upgraded).
  • Now deploy your wsp package. After it is deployed you must programmatically upgrade the feature. This is done by first making a query on features that needs upgrading, and then calling the Upgrade methode on the feature. This can be done with C# code or in PowerShell.

In this approach the CustomUpgradeAction tag was used in the fefature template.xml file. There is also a out of the box tag for adding a feature to an existing content type which can be used. It is called: "AddContentTypeField". However I have not have any success with using this. I have read that it should not work reliably with all culumative updates of SharePoint. Mayby trhis is why? I'm not sure. However I can not work with it. You could have a scenario where it works in your development environment, but not in production.