AngularJS与System.Web.Routing结合使用

4
这是一个与AngularJS应用程序路由相关的问题。该应用程序未使用MVC,但在后端使用WebAPI(这些路由有效)。
我将VS SPA模板用作基线:http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83 我遇到的问题是我的DefaultRouteHandler似乎总是在我的由angular定义的路由之前被调用。例如,我有一个路由/wageagreement/new,但.cshtml文件位于/views/wageagreement/detail中。我的angular路由在app.js中定义如下:
$stateProvider
        .state('wageagreement-new', {
            url: '/wageagreement/new',
            templateUrl: '/views/wageagreement/detail',
            controller: 'wageAgreementDetailsCtrl'
        })

如果我访问/wageagreement/new页面,我的DefaultRouteHandler(见下文)将首先被命中,文件路径为/wageagreement/new。由于该文件不存在,我会收到404错误。然后我的angular路径似乎启动并且该页面可以从/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;
    }
}

你最终决定做什么了?我即将创建我的第一个Angular项目,但我不确定是否应该使用第三方模板,采用MVC、SPA、Web API等方式。 - Bob Horn
2个回答

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

基本上重新将所有内容路由到您的Angular主页,让Angular路由来完成工作。


谢谢,这对我非常有效。我认为楼主应该接受这个答案。谢谢! - icube

0

虽然我不是Angular专家,但我可以分享一下我的经验:

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

但这仍然会使你的内容加载两次,一次是服务器端,一次是通过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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接