I have a custom jQuery control that uses History.js to change browserstate
and load child panels via Ajax. In HTML 5 browsers the URl is changed completely so a page refresh works (loads the current panel).
However in IE9, and older, the state is stored as a hash value like:
http://localhost:63559/ApplicationPanel/ListView#/SectionPanel/ListView/3?&_suid=1397574319099025255064889015816
I want to extract the hash URL (e.g. /SectionPanel/ListView/3
) inside of OnActionExecuting
, so that I can redirect to the correct starting point on a page refresh (back and forward buttons operate fine).
Basically I want it to do this, but even the raw URL
does not contain the hash part.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var url = filterContext.HttpContext.Request.RawUrl;
if (url.Contains('#'))
{
url = url.Substring(url.IndexOf('#')+1);
filterContext.Result = Redirect(url);
}
base.OnActionExecuting(filterContext);
}
If I breakpoint this code the url contains only the basic URL (e.g. /ApplicationPanel/ListView
).
How can I get at the hash parameters in an MVC controller? I gather I may also need to change the way they are pushed but several variations of the following have not helped:
// If HTML4, try adding a querystring
if (typeof window.history.pushState !== "function")
{
url = "?" + url;
}
this.Historyjs.pushState({ somedata: data }, "", url);
I get a URL like:
http://localhost:63559/Level1#Level1/?/Level2/Index/3&_suid=139757562428301418756129738284
It appears this is down to the way History.js manipulates the browser url. On HTML 4 browsers it can only modify the hash tag so the server never sees the extra data.
As a test I had the plugin check for a hash URL and redirect the browser to it:
// If HTML4, extract the URL from the hash
if (typeof window.history.pushState !== "function")
{
var hash = window.location.hash;
if (hash.length)
{
var q = hash.indexOf('?');
if (q < 1)
{
q = (hash.length);
}
hash = hash.substring(1, q);
window.location = hash;
}
}
While this worked for a page refresh, unfortunately a browser page load cannot distinguish between a page reload and the back button being pressed. This code sends the back button to the same child page over and over.
Any suggestions?
I have tried various options, but nothing seems to solve all situations. In the end I resorted to stripping any hash on a page load or back button press as I can't always distinguish between those two.
End result is:
// If HTML4...
if (typeof window.history.pushState !== "function")
{
// If there is a hash, remove it and redirect (to clean up the address bar)
var hash = window.location.hash;
if (hash.length)
{
window.location = <any>window.location.pathname;
return;
}
}