Chris Pietschmann

husband, father, hacker, entrepreneur, futurist, innovator, autodidact

NAVIGATION - SEARCH

ASP.NET: Fix for WebParts + UrlRewriting/UrlMapping Issue

The problem with using WebParts with UrlRewriting (or UrlMapping) is the WebPart PersonalizationProvider uses the path of the page being rendered to save/load the personalization state, not the path that was rewritten that the user sees. So, to fix this you just need to create a custom PersonalizationProvider and override all the methods that reference path, and call the base methods but pass in the path that was requested instead of the path being rendered.

Here's a SqlPersonalizationProvider I wrote that does this:

public class SqlPersonalizationProvider : System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider
{
    protected override void LoadPersonalizationBlobs(WebPartManager webPartManager, string path, string userName, ref byte[] sharedDataBlob, ref byte[] userDataBlob)
    {
        base.LoadPersonalizationBlobs(webPartManager, this.GetActualPath(), userName, ref sharedDataBlob, ref userDataBlob);
    }

    protected override void ResetPersonalizationBlob(WebPartManager webPartManager, string path, string userName)
    {
        base.ResetPersonalizationBlob(webPartManager, this.GetActualPath(), userName);
    }

    public override int ResetState(PersonalizationScope scope, string[] paths, string[] usernames)
    {
        return base.ResetState(scope, paths, usernames);
    }

    public override int ResetUserState(string path, DateTime userInactiveSinceDate)
    {
        return base.ResetUserState(this.GetActualPath(), userInactiveSinceDate);
    }

    protected override void SavePersonalizationBlob(WebPartManager webPartManager, string path, string userName, byte[] dataBlob)
    {
        base.SavePersonalizationBlob(webPartManager, this.GetActualPath(), userName, dataBlob);
    }

    protected string GetActualPath()
    {
        HttpApplication app = HttpContext.Current.ApplicationInstance;
        string p = app.Request.RawUrl;

        // Convert Absolute to Relative
        if (p.ToLowerInvariant().StartsWith(VirtualPathUtility.ToAbsolute("~/").ToLowerInvariant()))
        {
            p = "~/" + p.Substring(VirtualPathUtility.ToAbsolute("~/").Length);
        }

        // Remove QueryString Parameters
        if (p.Contains("?"))
            p = p.Substring(0, p.IndexOf("?"));

        return p;
    }   
}

Another implementation (possibly a better one) would be to create a custom WebPartManager and change the path that is sent to the PersonalizationProvider, but the way shown above was simplier for me to implement and it works.

blog comments powered by Disqus