Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS with System.Web.Routing

This is a question about routing for an AngularJS app. It is not using MVC, it does use WebAPI for the backend (these routes work fine).

I'm using the VS SPA template as a baseline: http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83

The problem I'm having is that my DefaultRouteHandler seems to always get hit before my angular defined routes. So for example I have a route that is /wageagreement/new, but the .cshtml file lives in /views/wageagreement/detail. My angular route is defined as follows in app.js:

$stateProvider
        .state('wageagreement-new', {
            url: '/wageagreement/new',
            templateUrl: '/views/wageagreement/detail',
            controller: 'wageAgreementDetailsCtrl'
        })

If I go to the page /wageagreement/new, my DefaultRouteHandler (see below) is first hit and the filepath is /wageagreement/new. Because this file doesn't exist I get a 404 error returned. THEN my angular path seems to kick in and the page loads fine from /view/wageagreement/detail. So for every page I get the error 404 flash up then I get the right page. Is there any way to make this work? I'm starting to think maybe my .cshtml files must match my routes to make it work.

public class DefaultRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        // Use cases:
        //     ~/            -> ~/views/index.cshtml
        //     ~/about       -> ~/views/about.cshtml or ~/views/about/index.cshtml
        //     ~/views/about -> ~/views/about.cshtml
        //     ~/xxx         -> ~/views/404.cshtml
        var filePath = requestContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath;

        if (filePath == "~/")
        {
            filePath = "~/views/touranalysis/index.cshtml";
        }
        else
        {
            if (!filePath.StartsWith("~/views/", StringComparison.OrdinalIgnoreCase))
            {
                filePath = filePath.Insert(2, "views/");
            }

            if (!filePath.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase))
            {
                filePath = filePath += ".cshtml";
            }
        }

        var handler = WebPageHttpHandler.CreateFromVirtualPath(filePath); // returns NULL if .cshtml file wasn't found

        if (handler == null)
        {
            requestContext.RouteData.DataTokens.Add("templateUrl", "/views/404");
            handler = WebPageHttpHandler.CreateFromVirtualPath("~/views/404.cshtml");
        }
        else
        {
            requestContext.RouteData.DataTokens.Add("templateUrl", filePath.Substring(1, filePath.Length - 8));
        }

        return handler;
    }
}
like image 385
Ryan Langton Avatar asked Feb 13 '23 20:02

Ryan Langton


1 Answers

The VS SPA template (http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83) is doing double routing. It's not insufficient. It's just wrong. Non of the direct links work except the root one.

If you want to use Angular routing all you have to do is to make DefaultRouteHandler class look like this

public class DefaultRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return WebPageHttpHandler.CreateFromVirtualPath("~/views/index.cshtml");
    }
}

Basicaly re-route everithing to your Angular main page and let the Angular routing do the job.

like image 105
rglek Avatar answered Feb 26 '23 21:02

rglek