Saturday, October 6, 2012

Problems with upgrading claims based site from Sharepoint 2010 to Sharepoint 2013 Preview

Recently we upgraded several sites which were implemented for Sharepoint 2010 to Sharepoint 2013 Preview. Upgrade was done according to MS guides. Existing SP2010 sites use claims based authentication. So we made backup of existing content database from SP2010 farm, copied them to SP2013 farm and restored on database server. After that we created web applications on SP2013 farm also using claims based authentication (we created them from UI and as you probably know in SP2013 claims based authentication is the only option when you create web application from Central administration. If you want to create web application with classic Windows authentication you have to use PowerShell).

After that we used Test-SPContentDatabase cmdlet in order to check restored SP2010 content database against SP2013 web application (at that moment SP2010 database was not mounted yet to SP2013 web application. The last one used its own content database which was created with web application). Test-SPContentDatabase gives several messages about missing assemblies which was Ok because custom wsp packages were not deployed to SP2013 farm yet. The most interesting was the last message:

Category Configuration
Error False
UpgradeBlocking False
Message

The [web_app_name] web application is configured with claims authentication mode however the content database you are trying to attach is intended to be used against a windows classic authentication mode.

Remedy

There is an inconsistency between the authentication mode of target web application and the source web application. Ensure that the authentication mode setting in upgraded web application is the same as what you had in previous SharePoint 2010 web application. Refer to the link "http://go.microsoft.com/fwlink/?LinkId=236865" for more information.

Locations  

So it says that target web app on SP2013 farm is configured to use claims based authentication, but source content database from SP2010 supposed to be used with classic Windows authentication. It is not correct, because as I said migrated SP2010 web sites use claims based authentication as well.

Ok, but as you can see UpgradeBlocking property was false for this message, we ignored this message and mounted content database to the web application using Mount-SPContentDatabase cmdlet. As you probably know this command also performs actual upgrade of content database schema from SP2010 to SP2013. Command ran successfully, but number of site collections for mounted content database was shown as 0 (while actually there should be 1 site collection) and site didn’t work.

After that I thought that if it says that content database should be used with classic Windows authentication, we should try to create such web application in SP2013 farm and run Test-SPContentDatabase again. So we created web application with classic Windows authentication using PowerShell, restored SP2010 content database again (it was upgraded to SP2013 schema during previous run of Mount-SPContentDatabase cmdlet) and ran Test-SPContentDatabase. Now it showed opposite error:

Category Configuration
Error False
UpgradeBlocking False
Message

The [web_app_name] web application is configured with windows classic authentication mode however the content database you are trying to attach is intended to be used against a claims authentication mode.

Remedy

There is an inconsistency between the authentication mode of target web application and the source web application. Ensure that the authentication mode setting in upgraded web application is the same as what you had in previous SharePoint 2010 web application. Refer to the link "http://go.microsoft.com/fwlink/?LinkId=236865" for more information.

Locations  

This message is actually correct, but the fact that it is opposite to the message which we got for the same database first time makes me think that this is a bug in Test-SPContentDatabase.

We ignored this message again and ran Mount-SPContentDatabase for claims based database from SP2010 farm and Windows classic authentication web application from SP2013 farm. This time number of site collections was set to 1 which was correct. But web application used Windows classic mode, so the last step was migrating it to use claims based authentication as described in the article which link was in the messages shown above: Migrate from classic-mode to claims-based authentication. After that upgraded sites were opened successfully. This is so-called hybrid mode when sites work in SP2010 mode on SP2013 farm (for this purpose folder “14” is included into SP2013 installation).

This is how we performed upgrade of claims based authentication sites from SP2010 to SP2013. It may be so that these problems are caused by Preview version of Sharepoint 2013. If you will face with similar problems in would be great if you will share them in comments here.

Friday, October 5, 2012

Analyze code in Sharepoint projects with NDepend

In this post I will show how you may use NDepend tool for analyzing the code in your Sharepoint projects. When refer to Sharepoint I will mean Sharepoint 2010 mostly, but of course NDepend can be used with any version of Sharepoint, because it can analyze .Net assemblies v1.0 v1.1 v2.0 v3.0 v3.5 v4.0 v4.5 and Silverlight. I wanted to try it on some real task for a long time and recently had a chance to do that. Especially it is worth to mention that authors of NDepend give free license if you are MVP awarded, so I had everything I needed for starting using it :).

NDepend is very powerful tool, it contains many nice looking graphic reports and analysis statistics, and one article is not enough for showing all its features. I won’t describe all features here, instead I will show one particular use case in this article which however shows how useful it can be. There is one great feature called CQLinq (Code Query LINQ) which allows you to write LINQ queries to the codebase by the same way as you do when write LINQ query to objects, Sql or other data. The only difference is that codebase plays role of database.

Returning to the use case. On one of my projects I needed to analyze the code and find all custom classes which inherit standard Page and Control classes from System.Web.UI namespace and which contains static fields (no matter public or private). Static variables in codebehind class of the pages or controls may lead to potential problems with concurrent access, because they are shared across all instances of the class. Especially it will be hard to catch such errors in Sharepoint web applications where we often have several WFEs and code may be executed on different servers (it may hide problem even deeper). But of course it is just a warning. It is not necessary that static variables will cause such errors. Anyway we needed to review all of them, so I decided to use NDepend for that.

Let’s start with launching NDepend and creating new project:

image

It shows Project properties window where we can select VS project, solution or separate assembly which we want to analyze. For example if we want to analyze whole solution we should select “Add assemblies of VS solutions” button:

image

Convenient thing that NDepend will show you list of recently used solution in VS, so you don’t have to browse for them if you worked with them recently. It supports the following VS versions: 2005, 2008, 2010 and 2012.

After that all found assemblies are shown in the Project properties window (so solution should be compiled first). Important thing: by default NDepend uses target framework set to 4.0 or 4.5 versions. It means that if e.g. you are opening solution for Sharepoint 2010 (which is built on top of .Net 3.5), standard Microsoft assemblies like Microsoft.SharePoint.dll won’t be loaded and analyzed. You will see the following error:

image

In turn it means that when you will use CQLinq, types defined in this assemblies won’t be shown. E.g. if you have custom application layouts page which class inherits LayoutsPageBase class from Microsoft.SharePoint.ApplicationPages.dll, then its base class will be shown as null in NDepend.

In order to fix it at first you need to change target framework to 3.5. You can do it if will click “View folders that contain .Net assemblies to analyze” button:

image

Unfortunately after that Microsoft.SharePoint.* assemblies are still remain unresolved. I used the following workaround: copy necessary assemblies from C:\Windows\Assembly\GAC_MSIL to temp folder, and then select it in “Add .net assemblies in folder” window which is opened from the same Project properties window. After I specified my temp folder all Sharepoint assemblies became resolved. The last step was selecting necessary Microsoft.SharePoint.* assemblies for analysis by clicking “Move selected to application assemblies” on each of them.

At this point you have everything ready for analysis. Click “Run analysis on current project” button on top of Project properties window or press F5. NDepend will analyze codebase and will show you a lot of statistics. For us it is important that after analysis it will allow you to write CQLinq queries to the codebase. When analysis will be done it will show you the following window where you can choose the next steps:

image

In our case we need to select “Browse NDepend interactive code rules”. After that in the left doc window choose “Queries and rules edit” and write the following query:

   1: let page = ThirdParty.Types.WithFullName("System.Web.UI.Page").FirstOrDefault()
   2: let control = ThirdParty.Types.WithFullName("System.Web.UI.Control").FirstOrDefault()
   3:  
   4: from t in JustMyCode.Types
   5: where (t.DeriveFrom(page) || t.DeriveFrom(control)) &&
   6:     t.FullNameLike("MyNamespace") &&
   7:     t.StaticFields.Any(f => !f.IsGeneratedByCompiler)
   8: orderby t.Name
   9: select new { t, t.FullName, StaticFields =
  10:     string.Join(";", t.StaticFields.Where(f => !f.IsGeneratedByCompiler)
  11:         .Select(f => f.Name).ToArray()) }

Syntax of CQLinq expressions is described here. On lines 1 and 2 we define variables for page and control types which we will use in query. Then on lines 4-9 we write actual query to the codebase. So we select all custom types (from t in JustMyCode.Types) which inherit Page or Control class from specified namespace (t.FullNameLike("MyNamespace")) which has at least one non-compiler generated static field (t.StaticFields.Any(f => !f.IsGeneratedByCompiler)). Then we just select new anonymous object with convenient properties representation: we join names of all static properties using semicolon (select new { t, t.FullName, StaticFields = string.Join(";", t.StaticFields.Where(f => !f.IsGeneratedByCompiler).Select(f => f.Name).ToArray()) }). As result we will have list of all classes which inherit Page or Control with list of static variables for each class. It will show you also classes which have const strings because it is treated as static field, I didn’t find a quick way to get rid of it, because it was not crucial. Already this report contained almost everything I needed. Report can be exported to html, excel, text or even graphics representation.

As you can see NDepend may be very helpful in such task where you need to analyze codebase for some specific usages. It uses LINQ queries familiar to most .Net developers, so you won’t have big problems with writing them if you worked with LINQ before. Hope this post will help you if you will want to use NDepend with Sharepoint and will be good starting point for using NDepend in your work.

Saturday, September 29, 2012

Speaking on Finland Sharepoint user group

On this week I spoke on the Finland Sharepoint user group. Theme of the speech was “Using of advanced C# features in Sharepoint development”, where I combined posts from the blog which are related with C# somehow and showed how with some creativity you may solve problems, which can’t be solved by only standard ways. Presentation is uploaded on SlideShare here. As always it was interesting to meet colleagues and listen to other speakers. Especially presentation of Gunnar Peipman (ASP.Net/IIS MVP), who spoke about optimization of Sharepoint sites for internet. Thanks to Jussi Roine, organizer of these meetings in Helsinki, and everyone who came to this event.

Saturday, September 22, 2012

Write C# code in powershell scripts

Powershell is powerfull sciprting language which allows you to automate many administrative tasks. However in addition to own language, it allows you to embed C# code inside script and execute it with other script instructions. This feature is not used very often, and although it will be good that you will teach powershell syntax, knowledge of this technique may help you in different scenarios. In this post I will show how to use C# inside powershell.

Lets move the following simple C# function to powershell and call it from ps1 file:

   1: public static class ScriptExample
   2: {
   3:     public static void EnumerateWebs(string url)
   4:     {
   5:         using (var site = new SPSite(url))
   6:         {
   7:             foreach (SPWeb web in site.AllWebs)
   8:             {
   9:                 Console.WriteLine(web.Url);
  10:                 web.Dispose();
  11:             }
  12:         }
  13:     }
  14: }

It opens SPSite object using passed url and enumerates all sub sites in this site collection. It is quite easy to write the same code in powershell, but our purpose is to show how to embed it into ps1 file and execute it from here. Here is the code:

   1: $assemblies = (
   2:     "Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
   3:     )
   4:  
   5: $source = @"
   6: using System;
   7: using Microsoft.SharePoint;
   8:  
   9: namespace Test
  10: {
  11:     public static class ScriptExample
  12:     {
  13:         public static void EnumerateWebs(string url)
  14:         {
  15:             using (SPSite site = new SPSite(url))
  16:             {
  17:                 foreach (SPWeb web in site.AllWebs)
  18:                 {
  19:                     Console.WriteLine(web.Url);
  20:                     web.Dispose();
  21:                 }
  22:             }
  23:         }
  24:     }
  25: }
  26: "@
  27:  
  28: $url = "http://example.com"
  29: Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language CSharp 
  30: [Test.ScriptExample]::EnumerateWebs($url)

At first we created list of imported assemblies (lines 1-3). In this case we need only Microsoft.SharePoint. If you will run this script from Sharepoint management shell, it is not needed, because this assembly is loaded automatically there, i.e. it is needed only if you run the script from regular powershell context. Then we write C# code and assign it to the local variable $source as string (lines 5-26). This is exact copy of our C# program shown above (it is important to add “using” directives there. Without them code won’t be compiled). After that we define url in local variable, load our C# code using Add-Type cmdlet with all additional assemblies which should be loaded into the context and call our function with parameter defined in powershell (lines 28-30). After running this scipt will print all sub sites of specified site collection.

As you can see it is quite easy to call C# managed code inside powershell. It may be helpful if you need to write some complicated code in ps1 file and don’t know how to move it to powershell syntax completely. Also it may be useful for developers who know C# and recently started working with powershell, although of course you anyway should teach powershell syntax in order to create more efficient code.

Saturday, September 8, 2012

Max number of nesting forests in cross-forest membership in AD groups

Some time ago we needed to determine what is the maximum number of nesting forests in cross-forest AD groups membership. There are 3 types of AD group scopes:

  • Universal
  • Global
  • Domain local

Group scope determines what members group may have and to what domains in the forest/tree you may assign permissions to this group. In the following technet article there is a summary table which describes possible members for each group scope, target domains where you can set permissions and to what group scope each of them can be converted:

Group scope Group can include as members…

Group can be assigned permissions in…

Group scope can be converted to…
Universal

Accounts from any domain within the forest in which this Universal Group resides

Global groups from any domain within the forest in which this Universal Group resides

Universal groups from any domain within the forest in which this Universal Group resides

Any domain or forest

Domain local

Global (as long as no other universal groups exist as members)

Global

Accounts from the same domain as the parent global group

Global groups from the same domain as the parent global group

Member permissions can be assigned in any domain Universal (as long as it is not a member of any other global groups)
Domain local

Accounts from any domain

Global groups from any domain

Universal groups from any domain

Domain local groups but only from the same domain as the parent domain local group

Member permissions can be assigned only within the same domain as the parent domain local group Universal (as long as no other domain local groups exist as members)

Based on this table we may make interesting conclusion: cross-forest membership is possible for one level of nesting only (one hop). Only Domain local groups may have members from another forest: user accounts, Global and Universal groups, but not Domain local groups. Domain local groups may have as members another Domain local groups only if these child groups are from the same domain as parent group. At the same time Global and Universal groups may have members only from their own domain/forest. So maximum number of different nesting forests in cross-forest membership is 1. You may add groups from many forests into Domain local group, but nesting level is not greater than 1. Probably MS did it consciously in order to limit the complexity of maintenance and avoid circular dependency problems (e.g. if it would be possible to add into Domain local group from forest A as members Domain local groups from forest B then there will be possible that groups have each other as a member). This information may be useful if you work with multi-forest environments and need to plan security membership.

Content editor web part’s menu is not opened in Sharepoint site

Sometimes on the publishing pages with content editor web parts you may encounter with the problem, that menus of some web parts are not opened, while another web parts still work properly. I.e. if you need to add/edit/remove some content from web part the only way is to copy content from browser, then close or delete web part from maintenance page (which is opened if you add “?contents=1” to the url of the current page, e.g. http://example.com/pages/default.aspx?contents=1), add new web part and insert copied content there. However it may not fix the problem, i.e. when next time you will come to the page in order to edit it, you may face with the same problems. How to fix it?

In most cases such problems are related with content which is inserted to the web part. E.g. it may look Ok for end users, but not have correct html. In order to check it, run IE developer tools javascript console, start debugging and see whether or not there are any javascript errors when you open web part’s menu. If content is incorrect you may get the exception:

Error: 'style.display' is null or not an object.

which occurs in MSOWebPartPage_OpenMenu() function from ie55up.js file on the following line:

   1: if(minOption)
   2: {
   3:     minOption.style.display = (WebPart.getAttribute('allowMinimize')=='false' ||
   4:         WebPart.style.display=='none') ? 'none' : '';
   5: }

In order to fix the problem copy content without formatting (e.g. into notepad), then close problematic web part, add content to the new web part and re-apply formatting. Save changes and check web part’s menu after that. It should be opened successfully so you will be able to continue working with your web parts in regular way.

Sunday, September 2, 2012

Debug issues on production Sharepoint farm

In Sharepoint development it is not unusual when you have multiple working environments: development, QA, production. Development environment in most cases is single-farm environment, while QA is similar to production and has several WFEs, app and db server. Also in multi-vendors project it may be so that you as software provider don’t have access to QA and production: it is under control of another company responsible for IT infrastructure.

Such projects require more accurate development and quality assurance. However it still may happens that solution works properly on dev env, but after deploying it to QA problem occurs. What to do in such situation? How to troubleshoot issues if you even don’t have remote desktop access?

You need mechanism which is powerful and flexible enough to figure out where problem comes from and doesn’t require a lot of efforts from infrastructure maintenance company. One of the most efficient way to troubleshoot in such situation which I found during working over many multi-vendor projects is to create custom application layouts page, ask administrator from infrastructure company to copy it to 14/layouts subfolder on one of WFE and open it here in context of production site.

Page itself may have any logic implemented via server code. Code may be embedded into aspx page as server-side script:

   1: <%@ Page Language="C#" %>
   2: <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3: <%@ Import Namespace="Microsoft.SharePoint" %>
   4: <%@ Import Namespace="System.Web" %>
   5:  
   6: <%
   1:  
   2:     this.lbl.Text = SPContext.Current.Web.CurrentUser.Name;
%>
   7:  
   8: CurrentUser:&nbsp;<asp:Label ID="lbl" runat="server" />

By default you may use C# 2.0 in server-side scripts. In one of my previous posts I wrote how to enable C# 3.0 in application layouts pages: see Use C# 3.0 features in application layout pages in Sharepoint.

If you need to test a lot of code it may require time to embed the codebehind code to aspx page. There is another way to execute server code: with it you will have aspx page and separate .cs file with the logic. The method is based on CodeFile attribute for Page directive. In this case codebehind class will be compiled in runtime by ASP.Net. You need to specify path to .cs file in this attribute and then in Inherits attribute specify page class from this .cs file. Here is example:

   1: <%@ Page Language="C#" CodeFile="~/_layouts/test/Test.aspx.cs" Inherits="MyNamespace.Test" %>
   2: <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3: <%@ Import Namespace="Microsoft.SharePoint" %>
   4: <%@ Import Namespace="System.Web" %>
   5:  
   6: CurrentUser:<asp:Label ID="lbl" runat="server" />

In Test.aspx.cs you need to specify base class of the page:

   1: using System;
   2: using System.IO;
   3: using System.Web;
   4: using Microsoft.SharePoint;
   5:  
   6: namespace MyNamespace
   7: {
   8:     public partial class Test : LayoutsPageBase
   9:     {
  10:         public override void OnLoad(EventArgs e)
  11:         {
  12:             this.lbl.Text = SPContext.Current.Web.CurrentUser.Name;
  13:         }
  14:     }
  15: }

Note that there is no need to specify protected controls variables in page class. They will be added automatically in runtime by ASP.Net compiler in partial class (that’s why you need to make your custom page class partial as it is shown in example above). This is quite powerful technique which will allow to test existing application layout pages almost without changing them. Also it requires minimum actions from farm administrator from infrastructure maintenance company which in real life is very important advantage.