1

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

Update:

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?

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • 1
    hash part is not send to server. Couldn't you use a url parameter instead? EDIT: sorry, missed some part of your question, looks like you have already tried it – A. Wolff Apr 15 '14 at 15:36

1 Answers1

0

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:

  • On HTML 4 browsers, the back button and reload will return to the top level panel (with any hash reference removed).
  • On HTML 5 it works beautifully with back, forward and refresh maintaining the current panel correctly at all levels of the hierarchy.

Code at start of jQuery plugin

// 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;
    }
}
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202