使用ASP.NET MVC 6和AngularJS在SPA中路由

时间:2016-01-10 16:48:07

标签: angularjs asp.net-mvc routing asp.net-core-mvc

我有一个示例MVC6单页应用程序,其中一个视图我想使用ngRoute加载2个Angular部分。您可以在GitHub

查看

应用中有3个网址:

  1. localhost - Index.cshtml
  2. localhost / games - 使用Angular的gamelist.html partial
  3. 的Index.cshtml
  4. localhost / games / 2 - 使用Angular的game.html partial
  5. 的Index.cshtml

    路由配置如下:

    MVC:

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}");
    
                routes.MapRoute("gamelist", "games", new { controller = "Home", action = "Index"});
                routes.MapRoute("gameWithId", "games/2", new { controller = "Home", action = "Index" });
            });
    

    角:

    myApp.config(['$routeProvider', '$locationProvider',
    function ($routeProvider, $locationProvider) {
        $routeProvider
            .when('/games', {
                templateUrl: 'partials/gameslist.html',
                controller: 'GameController',
                controllerAs: 'ctrl'
            })
            .when('/games/:gameId', {
                templateUrl: 'partials/game.html',
                controller: 'GameController',
                controllerAs: 'ctrl'
            });
    
        $locationProvider.html5Mode(true);
    }]);
    

    只要我从主页'/'启动应用程序,然后使用页面上的链接导航到部分,这一切都完美无缺。问题是,如果我通过在地址栏中输入应用程序来启动应用程序,则UR​​L#3(localhost / games / 2)不起作用。 URL#2(/ games /)确实有效。

    #3不起作用的原因是MVC从URL中删除了'/ games'部分,而Angular得到的只是'/ 2'。如果您运行示例应用程序,您将看到'$ location.path = / 2'。当然,Angular无法使用该路径进行映射,也不会渲染部分。所以我的问题是 - 如何让MVC返回到客户端的完整路径,以便Angular可以映射它?

3 个答案:

答案 0 :(得分:1)

您可以使用HTML5模式,只需确保每个请求都映射回您的Index.cshtml视图。此时AngularJS框架加载,客户端路由启动并评估请求URI并加载适当的控制器和视图。

我们使用不同的.cshtml页面在MVC中使用多个Angular应用程序来完成此操作,但我们使用带有通配符的属性路由,例如。

[Route("{*anything}")]
public ActionResult Index()
{
    return View("Index");
}

通配符运算符(*)告诉路由引擎URI的其余部分应与任何参数匹配。

我还没有机会掌握MVC6,但我认为你可以用" new"来做这样的事情。属性路由的版本?

[HttpGet("{*anything:regex(^(.*)?$)}"]
public ActionResult Index()
{
    return View("Index");
}

答案 1 :(得分:0)

要使#3链接在浏览器的地址栏中运行,我关闭了#34; html5Mode"在Angular和链接#-based。

答案 2 :(得分:0)

赞赏this blog

我认为这是一个更好的解决方案。

他的解决方案是重写不适合任何路线的请求,并且没有对角度着陆页进行任何扩展。

这是代码。

public class Startup
{
    public void Configure(IApplicationBuilder app, IApplicationEnvironment environment)
    {
        // Route all unknown requests to app root
        app.Use(async (context, next) =>
        {
            await next();

            // If there's no available file and the request doesn't contain an extension, we're probably trying to access a page.
            // Rewrite request to use app root
            if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
            {
                context.Request.Path = "/app/index.html"; // Put your Angular root page here 
                await next();
            }
        });

        // Serve wwwroot as root
        app.UseFileServer();

        // Serve /node_modules as a separate root (for packages that use other npm modules client side)
        app.UseFileServer(new FileServerOptions()
        {
            // Set root of file server
            FileProvider = new PhysicalFileProvider(Path.Combine(environment.ApplicationBasePath, "node_modules")),
            // Only react to requests that match this path
            RequestPath = "/node_modules", 
            // Don't expose file system
            EnableDirectoryBrowsing = false
        });
    }
}