AngularJS与System.Web.Routing

时间:2014-02-07 16:43:34

标签: angularjs routes

这是一个关于AngularJS应用程序路由的问题。它没有使用MVC,它确实使用WebAPI作为后端(这些路由工作正常)。

我正在使用VS SPA模板作为基线:http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83

我遇到的问题是我的DefaultRouteHandler似乎总是在我的角度定义路线之前被击中。例如,我有一个/ wageagreement / new的路由,但.cshtml文件位于/ views / wageagreement / detail中。我的角度路线在app.js中定义如下:

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

如果我转到页面/ wageagreement / new,我的DefaultRouteHandler(见下文)首先被点击,文件路径是/ wageagreement / new。由于此文件不存在,我收到404错误。然后我的角度路径似乎开始,页面从/ view / wageagreement / detail加载得很好。因此,对于每个页面,我得到错误404闪烁然后我得到正确的页面。有没有办法让这项工作?我开始认为我的.cshtml文件可能必须与我的路线相匹配才能使其正常工作。

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

2 个答案:

答案 0 :(得分:8)

VS SPA模板(http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83)正在进行双重路由。这还不够。这是错的。除了根链接之外,非直接链接不起作用。

如果你想使用Angular路由,你所要做的就是让DefaultRouteHandler类看起来像这样

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

Basicaly重新路由到你的Angular主页,让Angular路由完成工作。

答案 1 :(得分:0)

我不是Angular专家,但会分享我的经验:

您的网址不必与视图的实际位置相匹配,但它确实需要与该位置足够的关联,以便您可以从A构建B.在我们的应用程序中,Angular路由器urltemplateUrl实际匹配,服务器端处理程序正在构建类似于"~/Views/{url}.cshtml"的URL,您的服务器似乎已经这样做了。

这仍然会加载您的内容两次,一次是服务器端,一次是通过Angular的路由。为避免这种情况,您可以在Angular启动时使用Angular $templateCache机制(我们在模块的run()方法中执行此操作),如下所示:

    var view = angular.element('#ui-view');
    $templateCache.put(view.data('tmpl-url'), view.html());

这将读取服务器呈现HTML的内容并对其进行缓存,以便当您的应用程序需要在客户端(紧接其后)调用它时,它将在缓存中找到该视图而不会触发另一个调用。我不知道是否正在重新渲染视图,您可能想要检查它。我们目前没有看到任何闪烁,但这可能是因为我们目前只在相对强大的开发机器上使用它。

当然,这需要您的视图上的data-tmpl-url属性,填充data-tmpl-url="@Request.RequestContext.RouteData.DataTokens["TemplateUrl"]",但我相信这会与您的模板一起内置。如果不是 - 添加它。我在你的代码中看到游览服务器已经填充了这个数据令牌。

请注意,我们使用AngularUI,因此#ui-view。如果您使用内置的AngularJS路由器,请将其替换为#ng-view