Inconspicuous SharePoint Quirks #3

Mystery of the missing Content Type column

Is there something called “Over-architecting a solution”? Or do some people get carried away too much by Object Oriented Concepts that a simple if-else condition is enshrined into a dazzling hierarchy of classes, interfaces and er.. content types? SharePoint’s answer to creating a class/type or pseudo-interface is the Content Type. While a powerful feature, there are times even the Microsoft Team gets confused what to do with it, unconsciously bury a feature and consciously let it go undocumented.

There was a requirement to show different banners with different styles based on items in the “Banner List”. The different banner types were represented as “Content Types” and so the end user will create Banner Type 1, Banner Type 2 etc; set it to active and it would appear on the web page. The solution was designed in such a way that a calculated column in that list was populated based on the content type of the banner. That is, the calculated column had a formula in the BannerText sitecolumn:


=IF [Content Type] == "Banner Type 1" Then BannerText = "Red Banner" ELSE IF [Content Type] == "Banner Type 2" Then BannerText = "Blue Banner" ELSE IF...

The site column was relying on the Content Type of the list, that will be known at runtime. And that was working perfectly fine. In SharePoint 2007, that is.

Over to 2010. When I was trying to add a new item in that list, the calculated column Text would populate with a value “#NAME?” indicating that there is something wrong with the formula. Going back the site column, initially said the formula is fine, but when I tried to update it, errored out saying invalid column. Upon inspection, I see that Content Type is missing in the “Insert Columns” list.

First I thought my migration was wrong. Looked back at the SharePoint 2007 implementation, the “Content Type” column is there (see above image from MOSS 2007)! So Microsoft Team couldn’t handle the power the Content Types and removed it, I guess. But why was it removed? (see image below, from SharePoint 2010)

The _layouts/fldnew.aspx page inherits from Microsoft.SharePoint.ApplicationPages.BasicFieldEditPage. The method that creates the Insert Columns is WriteFieldNamesForFormulaColumnPicker(), so I loaded the .Net Reflector and inspected the code.

protected internal static void WriteFieldNamesForFormulaColumnPicker(TextWriter output, SPFieldCollection fields, string currentDisplayName)
 {
 SortedList list = new SortedList(new Comparer(fields.Web.Locale), fields.Count);
 foreach (SPField field in fields)
 {
 if ((((!(field is SPFieldText) && !(field is SPFieldCalculated)) && (!(field is SPFieldNumber) && !(field is SPFieldDateTime))) && (!(field is SPFieldChoice) || (field is SPFieldWorkflowStatus))) && (!(field is SPFieldBoolean) || (field is SPFieldAllDayEvent)))
 {
 continue;
 }
 if (((field.InternalName != "_UIVersionString") && !field.Hidden) && (field.Title != currentDisplayName))
 {
 list.Add(field.Title + "_" + field.InternalName, field);
 }
 }
 bool flag = true;
 foreach (SPField field2 in list.Values)
 {
 string title = field2.Title;
 SPHttpUtility.NoEncode("<option value=\"[", output);
 SPHttpUtility.HtmlEncode(title, output);
 SPHttpUtility.NoEncode("]\"", output);
 if (flag)
 {
 SPHttpUtility.NoEncode(" selected=\"selected\"", output);
 flag = false;
 }
 SPHttpUtility.NoEncode(">", output);
 SPHttpUtility.HtmlEncode((title.Length > 20) ? (title.Substring(0, 20) + "...") : title, output);
 SPHttpUtility.NoEncode("</option>", output);
 }
 }

So if the field is only one of text, calculated, number, datetime, choice, workflowstatus, boolean it is available for formulas. So what type is the Content Type column anyway? Using Powershell, we can determine that —

PS C:\Users\spfarmadmin> $w.Fields["Content Type"]

EnableLookup                : False
FieldRenderingControl       : Microsoft.SharePoint.WebControls.ComputedField
FieldRenderingMobileControl : Microsoft.SharePoint.MobileControls.SPMobileComputedField
FieldTypeDefinition         : Microsoft.SharePoint.SPFieldTypeDefinition
TypeDisplayName             : Computed

So since the field is Computed type, it does not appear in the insert column list. The same code in SharePoint 2007 didn’t have this restriction. So there is no way to find content type from within a site column. So I had to redesign the list now. Instead of multiple content types, I just added a new dropdown column which contain a list of values which was exact same as the content type. That way the functionality still worked without changing the underlying custom code. So a list with several content types and calculated columns to determine a text could be replaced with a simple dropdown list! Instead of multiple content types and formulas.

But a fundamental feature was removed. May be the next release of SharePoint 2014 will not have content databases?

Upgrading to SharePoint 2010 look and feel

Problem

After a recent SharePoint 2007 to 2010 upgrade (via database attach method) to one of our medium-sized web application, we were stuck with the old MOSS 2007 look and feel for SharePoint functionality. Moreover pretty much all our sites use several custom master pages. Doing a Visual Upgrade would reset all the sites to v4.master and would completely remove the custom master pages.

The task was to find an easy way to switch the look and feel for SharePoint functions to v4, but still retain our custom master pages for our sites. Yes we could have done it individually and manually, but why fret if the mighty PowerShell handy-man is around.

Solution

Iterate over the sites, remember the old master pages, reset the UI version and reset the old master pages.

Before running the scripts, it is useful to take a look at the web page for changing master page layouts http://sharepoint-web-app/<site>/_layouts/ChangeSiteMasterPage.aspx. There are two fields Site Master Page and System Master Page. The former is for publishing pages and the later is for forms and views (think AllForms.aspx and Views.aspx).


$rootSite = get-spsite("http://sharepoint-web-app")
$webs = $rootSite.AllWebs
foreach($w in $webs) {
 Write-Host
 Write-Host $w
 Write-Host "       " -Separator ": " $w.CustomMasterUrl $w.MasterUrl

 # CustomMasterUrl is the Site Master Page
 $oldCustomMasterUrl = $w.CustomMasterUrl
 # MasterUrl is the System Master Page
 $oldMasterUrl = $w.MasterUrl
 $w.UIVersion = 4
 $w.UIConfigurationVersionEnabled = $false
 # At this point, the CustomMasterUrl is set to v4.master
 $w.Update()
 # Reset to old master pages
 $w.CustomMasterUrl = $oldCustomMasterUrl
 $w.MasterUrl = $oldMasterUrl
 $w.Update()
}
$rootSite.Dispose()

The script iterates over all the sites and sub-sites, remembers their old master pages, switches to v4.master and resets the sites to old master pages. In effect, the Site Settings and other pages will have the SP 2010 look and feel.

Could not load file or assembly

Problem

FatalError: Could not load file or assembly ‘KWizCom.Foundation, Version=13.2.40.0, Culture=neutral, PublicKeyToken=30fb4ddbec95ff8f’ or one of its dependencies. The system cannot find the file specified.
Debug:    at KWizCom.SharePoint.FieldControls.DualLookupType.FieldSettings.GetFieldSettings(String fieldSettings)
at KWizCom.SharePoint.FieldControls.DualLookupType.DualLookupField.OnUpdated()

When

During content deployment.

Why

The above error happens when a content database still uses an older version (eg 13.2.40.0) of Kwizcom.Foundation, but the installed assemblies in your GAC are of later versions (13.2.50.0). .Net provides a cool dependentAssembly redirect feature, using which any older version of dll’s can automatically be redirected to use a newer version. This happens during the import phase and not during the export phase. So you have to check the target server content deployment import logs to verify the error.

During KwizCom upgrade or installation, the web.config, it automatically updates the dependent assembly redirection. But this will not help for Content Deployment. Because the web.config redirections are used by w3wp processes, while content deployment is run by a timer job, which is a Windows Service called “SharePoint 2010 Timer” and runs the file $hive14/bin/owstimer.exe which uses its own config file owstimer.exe.config.

Solution

When I inspected the bin directory, the owstimer.exe.config file was already there and Kwizcom had created one with the following content:

<?xml version=”1.0″ encoding=”utf-8″?>
<configuration>
<runtime>
<assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″>
<dependentAssembly xmlns=””>
<assemblyIdentity name=”KWizCom.SharePoint.Foundation” publicKeyToken=”30fb4ddbec95ff8f” culture=”neutral” />
<bindingRedirect oldVersion=”1.0.0.0-20.0.0.00″ newVersion=”13.2.50.0″ />
</dependentAssembly>
<dependentAssembly xmlns=””>
<assemblyIdentity name=”KWizCom.Foundation” publicKeyToken=”30fb4ddbec95ff8f” culture=”neutral” />
<bindingRedirect oldVersion=”1.0.0.0-20.0.0.00″ newVersion=”13.2.50.0″ />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Just in case, I restarted the timer service, but I was still getting the error, inspite of the above configuration. Now I turned to the next possible solution: google.

Shai Petel has written a blog about how to fix this via a wsp solution. While it is a good solution to keep that in wsp, in our case, I could not afford to change the wsp as the problem was happening in production. I noticed in Mr. Petel ‘s blog where the code replaces xmlns=”” with empty string. So I just went ahead and removed the xmlns=”” string in the above config and restarted the timer service.

Now the content deployment worked fine. The advantage is no need to restart website, so there is no downtime. The disadvantage is this has to be done in every WFE server of the farm.

This problem is probably only until the version of 13.2.62.0. In the current version (13.2.71.0) the xmlns=”” issue is fixed (I have not verified it though).

Twas the nightmare before content deployment

A lot of things have been written on +,-,*,/ and ^ of content deployment. Recently I had to go thru the seemingly-simple-stuff-called-content-deployment, but came out a bit wise. There are definitely some excellent resources, for eg this Spence’s blog. Though I do not agree with the view that Content Deployment is simple. It may be simple for someone who has been working with SharePoint for 12 years. In my view, content deployment either is so simple that everyone has trouble understanding its simplicity, or every one is just stupid. Some errors are cryptic and some rectifications are just not that obvious. This blog describes the woes of both migration to 2010 and a subsequent content deployment.

Abbreviations

  • CD (Content Deployment)
  • CDB (Content DataBase)
  • FCD (Full CD)
  • ICD (Incremental CD)
  • SPS 2010 (SharePoint Server 2010)
  • WTF (you know what)

Premises

  • There exists a Server-A, with a 2007 SP site pointing to CDB2007-A;
  • The CDB2007-A needs to be migrated to a new Server-B (Dev server) and upgraded to SPS 2010 via db-attach method, the new CDB will be called CDB2010-B
  • There is another Server-C (QA server). This will also have a new CDB, lets call it CDB2010-C

Problem

Do a FCD from CDB2010-B to CDB2010-C. This is where the fun begins.

Solution (Kinda)

Wisdom #1: You cannot do a FCD or ICD from a MOSS 2007 CDB to SPS 2010 CDB.

Can I… ?

No, you cannot.

So after you do your upgrades to all these servers, and if your CDB2007-A has changed, you cannot move your content from CDB2007-A to CDB2010-B or CDB2010-C. You have to do db-attach again. Because of the schema changes between MOSS 2007 and SPS 2010.

Wisdom #2: Make sure your Language Packs are installed in both Server-B and Server-C (as it was in Server-A)

We missed this due to Microsoft’s ingenious policy of naming all SPS language pack downloads as “ServerLanguagePack.exe”. Yes, whether you download an English or Spanish or Arabic language pack, they will all be called “ServerLanguagePack.exe”. So if you download multiple language packs, it is your responsibility to rename the downloaded file name in order to avoid overwriting it. Only when you run it and you find the actual information is in that language, you know that you are installing the correct language pack. The default download url will download the English language pack. Use Change language dropdown to download the language pack of your choice. Surely ServerLanguagePack-en-US.exe, ServerLanguagePack-es-es.exe would have been helpful. But Microsoft’s, and in general .Net’s naming conventions are nothing to rave about. Site vs Web vs WebSite vs WebApp vs Page vs SitePage vs Application Page anyone?

Wisdom #3: Once the language pack is installed, goto 14 HIVE and check if a directory with language code exists (Eng – 1033, Spanish – 3082 etc). You can also verify that looking in the Control Panel > Programs and Features which would say that the language pack is installed. Another way is goto Registry Editor, under Hive, check for InstalledLanguages key which would contain the language pack code.

If you do not install the Language packs, you will get errors. This error when translated to plain English means Spanish Lang Pack is missing:

[2/28/2011 10:45:05 AM] [File] [picture.png] Progress: Exporting File /_catalogs/masterpage/es-es/Preview Images/picture.png.
[2/28/2011 10:45:05 AM] [File] [picture.png] Error: Cannot open file “_catalogs/masterpage/es-es/Preview Images/picture.png”.
[2/28/2011 10:45:05 AM] [File] [picture.png] Debug: at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
at Microsoft.SharePoint.Library.SPRequest.GetFileAsStream(String bstrUrl, String bstrWebRelativeUrl, Boolean bHonorLevel, Byte iLevel, OpenBinaryFlags grfob, String bstrEtagNotMatch, String& pEtagNew, String& pContentTagNew)

— Prepare the Server-B (Dev)

  • Back up CDB2007-A database using SQL Server-Backup
  • Restore CDB2007-A as a new CDB, and call it CDB2010-B
  • Provide security permissions (dbowner) to the new farm admin account/users/remove if any old users from CDB2010-B
  • Create a new WebApp-B on Server-B (only one site collection, but several subsites)
  • Mount CDB2010-B to WebApp-B
  • Mount-SPContentDatabase “CDB2010-B” -DatabaseServer “dbserver” -WebApplication http://WebApp-B

Wisdom #4: In Server-B and Server-C, activate the required Features, same as those that existing Server-A. Having required features not activated will result in CD failure. Typically this error is very clear expressing that a required feature is missing or not activated.

  • Deploy any WSP-s and update the web.config as required.
  • Verify WebApp-B is working fine.

— Prepare the Server-C (QA); FCD to this server is our target

  • Create a new WebApp-C on Server-C

Wisdom #5: The site collection on WebApp-C must have the SAME root site template as that of the WebApp-B.

This is the formula:

WebApp-B.SiteCollection.RootSite.SiteTemplate must be equal to WebApp-C.SiteCollection.RootSite.SiteTemplate
If this is not the case, on a FCD, you will get a Site template mismatch error, like this:

[2/28/2011 10:47:05 AM] [Web] [] Progress: Importing
[2/28/2011 10:47:05 AM] [Web] [] Error: Cannot import site. The exported site is based on the template SPS#0 but the destination site is based on the template STS#0. You can import sites only into sites that are based on same template as the exported site.
[2/28/2011 10:47:05 AM] [Web] [] Debug: at Microsoft.SharePoint.Deployment.WebSerializer.IsWebTemplateCompatible(String sourceWebTemplateName, String destinationWebTemplateName)
at Microsoft.SharePoint.Deployment.WebSerializer.SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
at Microsoft.SharePoint.Deployment.XmlFormatter.CallSetObjectData(Object obj, SerializationInfo objectData, ISerializationSurrogate surrogate, ISurrogateSelector selector)
[2/28/2011 10:47:05 AM] FatalError: Cannot import site. The exported site is based on the template SPS#0 but the destination site is based on the template STS#0. You can import sites only into sites that are based on same template as the exported site.
[2/28/2011 10:47:05 AM] Debug: at Microsoft.SharePoint.Deployment.WebSerializer.IsWebTemplateCompatible(String sourceWebTemplateName, String destinationWebTemplateName)

To find that, open powershell and execute the following command on Server-B:

$site = Get-SPSite(“http://WebApp-B&#8221;)
$site.allwebs[0].webtemplate

The result will be like SPS, STS#0, MPS, BLANK INTRANET etc. Complete list can be found in Microsoft’s site.

In our case it was SPS, which is actually, sigh, a SharePoint Portal Server 2003’s team site template. But we assumed it was STS#0. Some consultant had the wisdom of creating a SPS root site in MOSS 2007.

  • Anyway, created a new SPS team site on WebApp-C.
  • You can do it by GUI, Powershell or stsadm. Apparently, after searching several blogs and attempting to do it with GUI and Powershell, the conclusion is to use stsadm:

stsadm -o createsite “http://WebApp-C&#8221; -siteowner “yourname” -owneremail “yourname@yourcompany.com” -sitetemplate “SPS”

  • Mount the CDB2010-C to WebApp-C
  • Mount-SPContentDatabase “CDB2010-C” -DatabaseServer “sps2010sqlserver” -WebApplicatin http://WebApp-C
  • Now set up a FCD on Server-B from WebApp-B targetting WebApp-C and keep watching the report.

Wisdom #6: Make sure you Mount the CDB2010-C when you are logged in as Farm Admin Account. Also make sure none of your files are checked out in CDB2010-B using SPD 2010. Checked-out but Published files cause CD failures.

Now got the error:

System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint “FK_Dependencies1_Objects”. The conflict occurred in database “xxxxx” table “dbo.Dependencies”, column ‘ObjectId’. The statement has been terminated.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)

Wisdom #7: Exit PowerShell; Open new PowerShell; Unmount and Mount the CDB2010-C again; Start the FCD.

Yes, opening a new PowerShell seems to clear up some cache and do it correctly!

Now the we are progressing… to the next error!

[2/28/2011 5:45:16 PM] [List] [fpdatasources] Progress: Exporting List fpdatasources.
[2/28/2011 5:45:16 PM] [List] [fpdatasources] Error: Object reference not set to an instance of an object.
[2/28/2011 5:45:16 PM] [List] [fpdatasources] Debug: at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
at Microsoft.SharePoint.Library.SPRequest.ExpandListSchemaForExport(String bstrUrl, String bstrTitle, Int32 lTemplateID, String bstrFeatureId, String bstrFields, String& pbstrFullSchema, String& pbstrIndexSchema)

Wisdom #8: Goto http://centraladmin/_admin/ServiceJobDefinitions.aspx. Find and Run the “Timer Service Recycle”.

Here is what happened: When trying to do FCD, we were getting the “Object reference not set” in relation to _catalogs/fpdatasources. We detached the CDB2010-C, reattached, ensure its mounted as Farm Admin, still this error didnt go away. Took a break, came in the next day morning and tried the FCD – it went past the above “Object reference not set” error, nothing was changed in between! (even though it did not fully succeed). I scouted the logs. We had set the FCD to Hourly. So this error was there in the 6 AM logs, but in the 7 AM logs this error was not there anymore. So there is some service that ran in between that cleared up stuff. I took a diff of all services between 5-6 AM and 6-7 AM and “Timer Service Recycle” was the only difference which was set to run at like 6:40 AM. Now I ran this manually, it took about 10 mts on our servers, gave it a few more minutes to settle down. Ran the FCD again, voila, the _catalogs/fpdatasources error is gone.

Ok Now the FCD export was smooth!

  • But the imports are failing. Lets look at the Server-C logs (target server).

[2/28/2011 6:29:21 PM] [Folder] [_catalogs] Progress: Importing
[2/28/2011 6:29:21 PM] [Folder] [_catalogs] Verbose: Source URL: _catalogs
[2/28/2011 6:29:21 PM] [Folder] [fpdatasources] Progress: Importing
[2/28/2011 6:29:21 PM] [Folder] [fpdatasources] Verbose: Source URL: _catalogs/fpdatasources
[2/28/2011 6:29:21 PM] [Folder] [fpdatasources] Error: Unable to import the folder _catalogs/fpdatasources. There is already an object with the Id 95ff96a8-e0c8-4f42-8d2f-6cf057b78e98 in the database from another site collection.
[2/28/2011 6:29:21 PM] [Folder] [fpdatasources] Error: Unable to import the folder _catalogs/fpdatasources. There is already an object with the Id 95ff96a8-e0c8-4f42-8d2f-6cf057b78e98 in the database from another site collection.
[2/28/2011 6:29:21 PM] [Folder] [fpdatasources] Debug: at Microsoft.SharePoint.Deployment.FolderSerializer.GetFolderFromDatabase(SPWeb parentWeb, Guid folderId, String sourceFolderUrl, Boolean restoreRecycleBinItems)
at Microsoft.SharePoint.Deployment.FolderSerializer.GetFolder(SPWeb parentWeb)

Wisdom #9: If you had multiple errors before, it is best to restart by recreating the WebApp-C in Server-C. That seems to take the above error away.

Finally we are left with these errors:

[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Progress: Importing
[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Verbose: Source URL: _catalogs/masterpage/Forms/mod-view.aspx
[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Verbose: Destination URL: /_catalogs/masterpage/Forms/mod-view.aspx
[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Verbose: pages\viewpage.aspx 4
[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Error: An unexpected error has occurred.
[3/1/2011 6:02:35 AM] [File] [mod-view.aspx] Debug: at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
at Microsoft.SharePoint.Library.SPRequest.SetGhostedFile(String setupPath, Byte setupPathVersion, Int32 iVersion, Guid& pguidListId, Guid& pguidDocId, Int32 lDoclibRowId, Int32 iAuthorId, String authorLogin, String serverRelativeUrl, String targetUrlWebRelative, Boolean isInDocLib, Boolean isMigration, Boolean isPublishing, Object varProperties)

[3/1/2011 6:03:10 AM] [List] [wfpub] Progress: Importing
[3/1/2011 6:03:10 AM] [List] [wfpub] ExtendedVerbose: Creating
[3/1/2011 6:03:10 AM] [List] [wfpub] Error: A list, survey, discussion board, or document library with the specified title already exists in this Web site. Please choose another title.
[3/1/2011 6:03:10 AM] [List] [wfpub] Debug: at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
at Microsoft.SharePoint.Library.SPRequest.CreateListOnImport(String bstrUrl, Guid& pguidListId, String bstrTitle, String bstrDescription, Int32 lTemplateID, String bstrFeatureId, Guid guidRootFolderId, Int64 llFlags, Int32 iVersion, Int32 iAuthor, String bstrFields, String bstrContentTypes, String bstrImageUrl, String bstrEventSinkAssembly, String bstrEventSinkClass, String bstrEventSinkData, Guid guidDocTemplateId, String bstrViews, String bstrForms, Boolean bCompressedSchema)

There are lot of the unexpected errors. As of writing this, we are not past this issue, not sure what’s the cause. The errors happen to be coming from the SPS’ internal files (AllItems.aspx etc). Some blog said to try Chris O’ Brien’s CD utility, we tried, didnt help. Some post said to match GUIDs of the List Default Pages (All Items, Edit Form etc) in the manifest.xml generated by CD utility. I haven’t figured that out yet.

Wisdom #10: We finally ended up with Backing up and Restoring the CDB2010-B on CDB2010-C, and doing an ICD instead of a FCD.

I know I didn’t use the WTF abbreviation at all, but it will be polite of you to add it after every error.

SP 2007 to SP 2010 Migration #3 – Lanap.BotDetect

Problem

Lanap.BotDetect 2.0.15.0 does not work after migrating to SharePoint 2010 from SharePoint 2007. The image does not appear on the screen or any validation handling does not work.

Solution

This is a similar problem to Issue #2 post.

First up, check if you have followed the instructions as in http://captcha.biz/doc/asp.net/2.0/asp.net-captcha-sharepoint.html

I deployed and use Lanap in GAC, no issues there.

In classic app pool mode, the http handlers are expected in <system.web><httpHandlers> section. In Integrated app pool mode, the handlers are expected in <system.webServer><handlers> section.

If the handlers are not added in the new section for Integrated mode, you will get a 404 error for invoking the handlers.

Similar to the solution in Issue #2, add the Lanap.BotDetect handler using the IIS7 Manager. Restart IIS and Lanap.BotDetect should work now.

SP 2007 to SP 2010 Migration #2 – Custom http handlers

Problem

Custom ASP.Net http handlers do not work in SharePoint 2010 after migration from 2007.

Premises

There are several ways one can write a custom http handler for use within a sharepoint environment.

Create .ashx file and a corresponding code behind .cs code and place it in _layouts folder. However that would not work if you dont want to expose the _layouts or you want to use a custom url mapping too (eg MyCustomHttpHandler.logon instead of MyCustomHttpHandler.ashx). So an alternative way is to create a .cs (that implements IHttpHandler) and a custom url mapping and place it in the <httpHandlers> section in web.config.

Solution

  1. Open IIS 7 and select the SharePoint site
  2. Open Handler mappings
  3. Add Managed Handler
  4. Provide a name and use the same type as used in the web.config section for httpHandlers
  5. Restart IIS

Now the http handler will work.

Reason

When migrating to 2010, one of the changes was using the Integrated app pool instead of classic app pool. If your new site is using Integrated app pool, IIS 7 expects the handlers to be in a different section – specifically <system.webServer><handlers> section. In classic mode, the handlers are used from <system.web><httpHandlers> section.

Adding the custom http handlers within this section allowed IIS 7 to map the handler to the code.

SP 2007 to SP 2010 Migration #1 – System.Web.Extensions not found

Problem:

We were migrating a sp 2007 project to sp 2010. The web.config between the two environments were very different (mainly the version numbers). After the merging the two web.config, I was getting a plain Error 500 on the site, with no further details.

Solutions:

First up, open IIS, select the site, double click on the Configuration icon. If this opens, at least the web.config is fine. In my case even this did not open up, and gave an error 0x8007000D and very helpful error of empty string.

Scouting around on several websites, (the most helpful was stackoverflow.com) finally tried installing the IIS7 rewrite module (rewrite_2.0_rtw_x64.msi) and restarted IIS. Now I was able to open the Configuration Editor from IIS7.

Now hitting the site gave atleast a readable error “System.Web.Extensions not found”. The dll is installed in GAC for sure. This is for AJAX ASP.Net and apparently this has to be turned off for SharePoint 2010 which relies on .NET 3.5.

So commented out the following line:

<add name=”ScriptModule” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />

The site is up and running now.