jqueryajaxasp.net-mvcurlonactionexecuting

How to get hash part of a History.js URL from in MVC Controller's OnActionExecuting


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?


Solution

  • 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:

    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;
        }
    }