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 simpler for me to implement and it works.