AngularJS:UI-Router解决路由hash-bang不起作用

时间:2017-05-04 19:50:04

标签: angularjs asp.net-core angular-ui-router html5mode

我目前正在使用Angular版本1.6.4。

要解决我遇到的hashbang问题,我的所有网址都采用以下格式:

http://localhost:8885/#/hotels/holiday-inn

我的app.js包括路由器(使用ui-router):

$urlRouterProvider.otherwise('/');
$locationProvider.hashPrefix('');
$locationProvider.html5Mode(true);

$stateProvider
    .state('index', {
        url: '/',
        templateUrl: 'index.html',
        controller: 'hotelController'
    })
    .state('login', {
        url: '/hotel/:name',
        templateUrl: 'views/hotel.html',
        controller: 'hotelController'
    });

我的ui-view位于Index.cshtml(我之前已将所有内容都放在_Layout.cshtml中,但将所有内容移至Index.cshtml):

<!DOCTYPE html>
<html ng-app="hotelScheduler">
<head>
    <meta charset="utf-8" />
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Application</title>
    <link href="~/css/bootstrap.min.css" rel="stylesheet" />
    <script src="~/lib/angular/angular.min.js"></script>
    <script src="~/lib/angular-ui-router/release/angular-ui-router.min.js"></script>
    <script src="~/js/app.js"></script>
    <script src="~/js/hotelController.js"></script>
</head>
<body>
    <div ui-view>
    </div>
</body>
</html>

现在我遇到了不同的问题。如果我访问http://localhost:8885/hotel/holiday-inn,我会收到404

为什么会这样?

其他问题排查:

如果我访问http://localhost:8885/#/hotel/,则会显示index.html而不是views/hotel.html,并将地址更改为http://localhost:8885/#%2Fhotel%2F。 (我知道这是路由中otherwise的工作,但是为什么它可以用于启动hashbang的URL?)

我一直在询问并在线查看,人们建议其余部分通过C#的MapRoute或服务器端代码完成。

如何通过任一选项执行此操作?如果我要执行此服务器端,如何通过ASP.Net Core和Visual Studio执行此操作?

这是我当前的MapRoute

app.UseMvc(config =>
{
    config.MapRoute(
        name: "Default",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "App", action = "Index" }
    );
});

另一个编辑:根据评论建议和https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode,我尝试将此代码添加到我的web.config中,以便重写服务器

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

但现在,绝对一切都只是重定向到根/主页:localhost:8885/

任何帮助?

2 个答案:

答案 0 :(得分:1)

HTML5模式下的$ location需要<base>标记。

通过文档:

  

如果将$ location配置为使用html5Mode(history.pushState),则需要为带有标记的应用程序指定基本URL,或者通过向requireBase:false传递定义对象,将$ locationProvider配置为不需要基本标记$ locationProvider.html5Mode():

     

https://docs.angularjs.org/error/$location/nobase

修复方法是将您的$locationProvider代码更新为:

 $locationProvider.html5Mode({
     enabled: true,
     requireBase: true
 });

然后,在<head>内,相应地设置<base>。 最常见的模式是/,但您的应用程序可能需要从其他文件夹访问资产。

<head>
  <base href="/">
  ...
</head>

或者,如果你想要聪明,就像https://plnkr.co那样可以用来引导Angular的傻瓜:

<head>
  <script>document.write('<base href="' + document.location + '" />');</script>
</head>

答案 1 :(得分:1)

我遇到类似AngulaJS SPA的问题,我可以用以下代码解决:

Startup.cs

app.Use(async (context, next) =>
            {
                await next();
                if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
                {
                    context.Request.Path = "/index.html";
                    await next();
                }
            })
            .UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List<string> { "index.html" } })
            .UseStaticFiles()
            .UseMvc();

的index.html

<base href="/" />

在引用wwwroot文件夹下的静态文件时使用正斜杠

<script src="/app.js"></script>
<script src="/app/services/auth.service.js"></script>

app.js

$stateProvider
        .state('home', {
            url: '/',
            templateUrl: '/index.html',
            controller: 'HomeController',
            controllerAs: "vm"
        });

$locationProvider.html5Mode({
        enabled: true,
        requireBase: true
    });

$urlRouterProvider.otherwise('/stores');
web.config中的重写不再适用于最新的ASP.NET核心,您可以从web.config中删除该代码。

如果您使用MVC,可以尝试使用以下代码,但我还没有

        app.UseStaticFiles()
           .UseMvc(routes =>
           {
               routes.MapRoute(
                   name: "default",
                   template: "{controller=Home}/{action=Index}");
               routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
           });