SharePoint: Error when adding a new page based on a customized (broken) page layout

Exception:

No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)  

image

Some interesting bits in the stack trace:

... at System.Activator.CreateInstance(Type type)

... at Microsoft.SharePoint.WebPartPages.SPWebPartSerializer.get_DefaultControl()

... at Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPart(WebPart webPart, String zoneId, Int32 zoneIndex)

snipped remaining massive stack trace.

What had happened was that we had a stuffed up Page Layout with a web part zone that contained invalid HTML.

I had detected this and deleted the entire web part zone, but SharePoint must have it in the database, so each time I re-open the PageLayout it was resurrecting all the broken code.

The fix wasn't at all glamorous:

  1. Check out the page layout
  2. Fix it enough in the code view so that the designer will load the designer view
  3. Delete the webparts in the designer view
  4. Switch back to the code view - there's now a few remaining bits of broken HTML left around the web part zone - fix those.
  5. Save everything
  6. Close file, re-open it
  7. Check the file is now clean HTML

We can now use the page layout to create new pages again.

jliu

Didn't know it could be this difficult to pull something out of the GAC

So, a few days ago, one of my favorite TFS/Outlook add-on stopped working.

Exception:
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.TeamFoundation.Client, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

image

Puzzled, I figure there's something odd with the Fusion loader.  Popping into the GAC I saw this horror!

image

I must have installed something that upgraded all the library to version 9.0.  OK, no problems, let me uninstall the old version 8...

Exception:
Assembly 'Microsoft.TeamFoundation.WorkItemTracking.Client' could not be uninstalled because it is required by other applications.

image

A bit of reading lead me to this article.

GAC Assembly Trace Reference
http://blogs.msdn.com/junfeng/archive/2004/09/13/228651.aspx

 

Hitting gacutil to see what's referencing it...

c:\Program Files\Microsoft Visual Studio 9.0\VC>gacutil /lr Microsoft.TeamFoundation.WorkItemTracking.Client

Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  Microsoft.TeamFoundation.WorkItemTracking.Client, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86
              SCHEME: <WINDOWS_INSTALLER>  ID: <MSI>  DESCRIPTION : <Windows Installer>
  Microsoft.TeamFoundation.WorkItemTracking.Client, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86
              SCHEME: <WINDOWS_INSTALLER>  ID: <MSI>  DESCRIPTION : <Windows Installer>

Number of items = 2

Taking great care not to uninstall both versions, I'm being ultra cautious:

c:\Program Files\Microsoft Visual Studio 9.0\VC>gacutil /l "Microsoft.TeamFoundation.WorkItemTracking.Client, Version=8.0.0.0"

The Global Assembly Cache contains the following assemblies:
  Microsoft.TeamFoundation.WorkItemTracking.Client, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86

Number of items = 1

Ok... go crazy!

c:\Program Files\Microsoft Visual Studio 9.0\VC>gacutil /u "Microsoft.TeamFoundation.WorkItemTracking.Client, Version=8.0.0.0"
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Assembly: Microsoft.TeamFoundation.WorkItemTracking.Client, Version=8.0.0.0, Cul
ture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86
Unable to uninstall: assembly is required by one or more applications
Pending references:
              SCHEME: <WINDOWS_INSTALLER>  ID: <MSI>  DESCRIPTION : <Windows Installer>
Number of assemblies uninstalled = 0
Number of failures = 0

Not knowing the keys to run gacutil /ur, I turned and did more research:

This one is from the Fusion guys

http://blogs.msdn.com/alanshi/archive/2003/12/10/42690.aspx

I found two of the reference keys in the registry.  And exported them just to be safe.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Assemblies\Global]
"Microsoft.TeamFoundation.WorkItemTracking.Client,Version=\"8.0.0.0\",PublicKeyToken=\"b03f5f7f11d50a3a\",Culture=\"neutral\",RuntimeVersion=\"v2.0.50727\",processorArchitecture=\"X86\""=hex(7):65,\
  00,45,00,65,00,2b,00,48,00,25,00,65,00,30,00,78,00,40,00,45,00,59,00,7a,00,\
  4b,00,4c,00,2c,00,70,00,71,00,5e,00,41,00,3e,00,2e,00,32,00,2a,00,7d,00,66,\
  00,7b,00,40,00,35,00,49,00,3f,00,69,00,4a,00,68,00,67,00,78,00,59,00,7a,00,\
  7a,00,4c,00,2c,00,00,00,00,00
"Microsoft.TeamFoundation.Common,Version=\"8.0.0.0\",PublicKeyToken=\"b03f5f7f11d50a3a\",Culture=\"neutral\",RuntimeVersion=\"v2.0.50727\",processorArchitecture=\"X86\""=hex(7):65,\
  00,45,00,65,00,2b,00,48,00,25,00,65,00,30,00,78,00,40,00,45,00,59,00,7a,00,\
  4b,00,4c,00,2c,00,70,00,71,00,5e,00,41,00,3e,00,66,00,6c,00,45,00,37,00,36,\
  00,72,00,3f,00,47,00,34,00,3d,00,59,00,49,00,29,00,41,00,4c,00,71,00,5f,00,\
  5f,00,58,00,54,00,00,00,00,00

Then I dropped these trace references from the registry.

Head back to the GAC, uninstall the two offending Assemblies.

Pop back to Outlook.  Hey, my favorite addon works again.

:-)

Hope this helps someone out there.

jliu

SharePoint, WCF Service, .NET full/partial trust

Security Exception: That assembly does not allow partially trusted callers

Scenario:

  1. We wanted our SharePoint webpart to do some complex logic that took time.
  2. We decided to implement it as an AJAX call to an AJAX WCF Service (see earlier post)
  3. To avoid cross-domain issues, we decided to host the WCF Service under SharePoint root.

The bigger picture looked like this:

  • SharePoint root: http://server/
  • WCF hosted on http://server/wcf.service/service.svc 
    Which we configure as a Web Application in IIS.
  • We build the WCF service separately and tested it to be working.
  • When we deployed to the SharePoint box however, we hit a snag when our WCF service calls an underlying API:

    Security Exception: That assembly does not allow partially trusted callers.

The cause:

What we understood of the problem basically was that the web.config for SharePoint http://server/web.config specified trust policies that mean anything under http://server/... was running with partial trust.

This isn't necessarily a bad thing, but because the API's we were calling demanded full trust, we couldn't proceed without granting the service full trust.

The fix:

There are many ways to grant the service full trust, we decided to do this by placing the service assembly into the GAC on the SharePoint server.

  1. Put assembly (strong-named) into the GAC
  2. Add <assembly> line into the web.config

If this option isn't available for you, check out caspol or the .NET configuration tools to elevate permission for your assembly.

Thoughts:

The deployment ended up to be very nice and tight:

SharePoint talks to the service via a SmartPart + jQuery.ajax

Done!

Consuming WCF WebService from jQuery AJAX (with JSON)

So the guys at work are pretty sold on jQuery now.  Everybody who've used it don't want to go back to vanilla JavaScript (just as I predicted).

One of the things always sitting at the back of my mind is to bridge the call from jQuery.ajax to WCF WebServices.

Finally we had a chance to do this, and it turns out this was pretty easy.  Special mention to Alvin Shen and Ron Maman who checked this out.

 

  1. Create an AJAX-enabled WCF WebService
    image
  2. This will update your web.config - the only difference is the WCF bindings used - here are the two interesting bits

    <service name="SSW.WCF.Services.BookService">
       <endpoint address="" behaviorConfiguration="SSW.WCF.Services.BookServiceAspNetAjaxEndPointBehavior"
        binding="webHttpBinding" contract="SSW.WCF.Services.BookService" />
    </service>

    <behaviors>
       <endpointBehaviors>
          <behavior name="SSW.WCF.Services.BookServiceAspNetAjaxEndPointBehavior">
             <enableWebScript />
          </behavior>
       </endpointBehaviors>
    </behavior>

  3. Here's the jQuery AJAX call

    $(document).ready(function() {
        $.ajax({
            type: "POST",
            url: http://localhost/<web app name>/BookingService.svc/DoWork,
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(data) {
                alert(data.d);

            }
        });
    });

 

Incredibly easy, the hardest part was working what the url was going to be

 

UPDATE technologies list:

  • jQuery
  • WCF WebService (AJAX-enabled WCF WebServices are only available in ASP.NET 3.5 - where they added the webHttpBinding, which does JSON serialization)

UPDATE:
Note that ASP.NET does date serialization a bit differently - there is no proper JSON date standard, and the JavaScript date doesn't match the .NET DateTime class with timezone, you may need to do a bit of work to serialize back to a JavaScript date. 

 

Here's a fun service that we use for testing.

// Add more operations here and mark them with [OperationContract]
[OperationContract]
public object[] TestJSON()
{
    return new object[] { DateTime.Now, 1, 1.034f, null, "test" };
}