Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Durandal JS: typing url without hash give HTTP Error 404.0 - Not Found

I am building a SPA application using Durandaljs. When I enter a URL WITHOUT hash, it shows the error: HTTP error 404.0 - NOT FOUND. However, it is working fine WITH hash.

Example:

www.domain.com/page =>  HTTP error 404.0 - NOT FOUND
www.domain.com/#page = > working fine.

How can I map the www.domain.com/page to www.domain.com/#page?

like image 803
Jason Avatar asked Mar 20 '14 06:03

Jason


2 Answers

In order for pushState to work correctly in your app (including deep linking), you must configure the router for pushState and tell the server to ignore all but certain paths/routes.

The server should ignore paths that contain resources or services used by your SPA, and should always send the Durandal.cshtml (or whatever you name it) for these ignored routes.

These routes should be ignored even if there's additional route info in the request. This will allow for deep linking using pushState-style URLs.

Here's the MVC routing from a Durandal-based app I recently completed:

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.Ignore("{resourcedir}/{*resource}", 
        new {resourcedir = @"(api|breeze|app|scripts|content|assets|signalr)"});
    routes.MapRoute(
        name: "Default",
        url: "{*sparoute}",
        defaults: new { controller = "Durandal", action = "Index"});
}

Basically, we're telling the server to ignore any requests that start with:

  • api/
  • breeze/
  • app/
  • scripts/
  • content/
  • assets/
  • signalr/

We're ignoring api, breeze and singlar because WEBApi and SignalR will handle those requests. Also, app, scripts, content, and assets are ignored because the underlying ASP.NET engine will serve those requests.

The final statement (routes.MapRoute) causes all non-ignored requests to send back the default page (the only real page in the SPA).

For example, www.domain.com/page will send the same response from the server as if you'd asked for www.domain.com/. Once the SPA loads and Durandal's router/history has initialized, the suffix is converted to hash if needed (like you're using IE) and is then dispatched through the router.

Note that if your application is not rooted at /, you need to specify the root path. You should also include hashChange: true so that your application works in IE, like this:

router.activate({ pushState: true, hashChange: true, root: '/approot' })
like image 178
MickeyPickle Avatar answered Nov 19 '22 06:11

MickeyPickle


You can, I'm using it in my latest Durandal site which is based on the DurandalAuth template.

When you are initializing your router, set pushState: true, like this:

return router.map([
    { route: 'somroute', moduleId: 'somroute', title: 'Home', nav: true, hash: "#somroute" }
  ])
  .buildNavigationModel()
  .mapUnknownRoutes("notfound", "notfound")
  .activate({ pushState: true });

You can see a working example on my site: noadou

like image 30
Jamie Hammond Avatar answered Nov 19 '22 04:11

Jamie Hammond