SharePoint: Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)

I had a really strange error yesterday – when altering some pre-existing sharepoint code to ensure that spcontext.current.web.parentweb objects were disposed of correctly, I encountered the above error. Previously the code reinstantiated SPWeb objects from SPContext.Current.Web.ParentWeb.Url, rather than just using SPContext,Current.Web.ParentWeb directly and disposing. Note that I have never had any problem with this before, but in the above case, further objects were being obtained from SPContext.

This is the closest article relating to this issue: http://blog.richfinn.net/, however, in the code I am working on,  all spweb and spsite objects were disposed as expected.

My current suspicion, from looking at the SharePoint logs, is that somewhere in the stack, before or after the code I altered, an object is not disposed of correctly – I have not yet located this. The error in the logs is:

10/28/2008 15:58:34.11 w3wp.exe (0x10D8) 0x0E30 Windows SharePoint Services General 0 Medium Potentially excessive number of SPRequest objects (12) currently unreleased on thread 6. Ensure that this object or its parent (such as an SPWeb or SPSite) is being properly disposed. Allocation Id for this object: {6BEFDD45-D359-48FD-AA0A-624B4C2CB21F} Stack trace of current allocation: at Microsoft.SharePoint.SPRequestManager.Add(SPRequest request, Boolean shareable) at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous) at Microsoft.SharePoint.SPWeb.InitializeSPRequest() at Microsoft.SharePoint.SPWeb.EnsureSPRequest() at Microsoft.SharePoint.SPWeb.get_Request() at Microsoft.SharePoint.SPWeb.InitWebPub…

If anyone has any suggestions, I would be grateful! I will update this article when I resolve properly and definitively.

SharePoint: Debugging Assemblies in the GAC (part 2)

I wrote an article on debugging assemblies in the GAC some time ago, see Quicknote-Easy-way-to-debug-assemblies-in-the-GAC . There seems to be a lot of conflicting view about what is required out there on the web, and how the debugger works is not something that appears to be widely understood.

The other day, a colleague of mine was saying that visual studio always allowed him to debug gac’d assemblies. He had no problem with symbol files loading. It turned out that he was dropping assemblies to the gac either manually through the UI or through gacutil /i. In the past, I had always packaged assemblies into a wsp and then subsequently deployed the wsps through stsadm – which did not permit me to debug gac’d assemblies.

I came across a really interesting blog post the other day however, at http://www.elumenotion.com/Blog/Lists/Posts/Post.aspx?ID=23. It basically turns out that the visual studio debugger works by matching loaded assemblies to the user that created them (see visual studio tools->options->debugging->enable just my code). This meant that my colleague was always able to debug the gac, as he had manually copied the code in, as opposed to deploying the code through stsadm (which must therefor install it as the service account?). If you turn off this flag, you can debug assemblies deployed to the gac through stsadm without copying pdb files around, just by attaching to the relevant w3wp.

Edit: also use the module window in visual studio (ctrl+alt+u) to see what symbols are loaded. You can also right click to manually load symbols for and assembly

SharePoint: Using SPListItem in SPGridView Custom Template Columns

In the past, where I have had to create custom columns for use in an SPGridView, I have created a class that implements ITemplate and have then got data from the datasource in the appropriate databinding event handler using

string itemId = DataBinder.GetPropertyValue(currentGridViewRow.DataItem, “ID”).ToString();

I recently came accross another way of doing it that allows you to access an SPListItem directly (although this only works if you are binding your SPGridView to an SPDataSource). The code below illustrates:

public class LabelTemplate : ITemplate
{
    void ITemplate.InstantiateIn(Control container)
    {
        Label label = new Label();
        container.Controls.Add(label);
        label.DataBinding += new EventHandler(this.Label_DataBinding);
    }

    private void Label_DataBinding(object sender, EventArgs e)
    {
        Label test = (Label)sender;
        // Get SPListItem
        SPGridViewRow currentRow = (SPGridViewRow)test.NamingContainer;
        SPDataSourceViewResultItem currentItem = (SPDataSourceViewResultItem)currentRow.DataItem;
        SPListItem item = (SPListItem)currentItem.ResultItem;
        test.Text = item.Title;
    }
}

SharePoint: SPWebConfigModification Note

I’ve just been working on automating some changes to web.config using SPWebConfigModification. I have done this a while ago, but forgot the difference between two parameters (it is important that these are set correctly – if name is not set correctly, adding web.config nodes may work, but remove wont work):

  • XPath – the path to the parent node where your web.config node will be added to.
  • Name – the xpath used to identify your web.config node, from the parent web.config node specified path the above Xpath.

Example code:

using (SPSite site = new SPSite(url))
{
    // Get webapp and ensure that previous mods are cleared
    SPWebApplication webApp = site.WebApplication;
    webApp.WebConfigModifications.Clear();

    string xPath = “configuration/system.web/securityPolicy”;
    string name = “trustLevel[@name=\”Custom_TrustLevel\”]”;

    // Note – you should create multiple mods before ApplyWebConfigModifications, as
    // opposed to calling for each change
    SPWebConfigModification mod = new SPWebConfigModification(name, xPath);
    mod.Value = “<trustLevel name=\”Custom_TrustLevel\” policyFile=\”C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\Custom_TrustLevel.config\” />”;
    mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
    webApp.WebConfigModifications.Add(mod);

    // Apply the modifications
    webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
    webApp.Farm.Update();
    webApp.Update();
}

SharePoint: Publishing Pages Programmatically

A quick snippet of code on how to publish pages (as this is something I have been asked a few times):

string pageUrl = “http://path/to/my/webpage.aspx”;

using (SPSite site = new SPSite(pageUrl))
{
    using (SPWeb web = site.OpenWeb())
    {
        // n.b Publishing web does not implement iDisposable
        PublishingWeb publishWeb = PublishingWeb.GetPublishingWeb(web);
        PublishingPageCollection webPages = publishWeb.GetPublishingPages();
        PublishingPage currentPage = webPages[pageUrl];

        SPListItem pageListItem = currentPage.ListItem;
        pageListItem.Update();

        if (pageListItem.File.CheckOutStatus != SPFile.SPCheckOutStatus.None)
        {
            pageListItem.File.CheckIn(“Message describing what was checked in”);
        }

        pageListItem.File.Publish(“Message on what was published”);
    }
}