如何在不干扰AngularJS路由的情况下制作ASP MVC本地化路由

时间:2014-09-05 15:44:31

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

我正在使用ASP MVC和AngularJS开始一个项目,我想让ASP MVC从URL中处理本地化,如下所示:http://localhost:4416/en/#/contact或此http://localhost:4416/en-US/#/home等等本地化是在哈希标记之前设置的,我希望ASP MVC Route能够处理它,因为我还将Razor用于View页面。在之前的ASP MVC项目中,我有这种类型的路由来处理语言和文化:

routes.MapRoute(
      name: "Default",
      url: "{language}/{controller}/{action}/{id}",
      defaults: new
      {
        controller = "Home",
        action = "Index",
        id = UrlParameter.Optional,
        language = "en",
        culture = "CA"
      }
  );

在AngularJS中,我的第一个测试路线是:

app.config(['$routeProvider', function ($routeProvider) {
    //Setup routes to load partial templates from server. 
    //TemplateUrl is the location for the server view (Razor .cshtml view)
    $routeProvider
        .when('/home', { templateUrl: '/home/main', controller: 'MainController' })
        .when('/contact', { templateUrl: '/home/contact', controller: 'ContactController' })
        .when('/about', { templateUrl: '/home/about', controller: 'AboutController' })
        .when('/demo', { templateUrl: '/home/demo', controller: 'DemoController' })
        .when('/angular', { templateUrl: '/home/angular' })
        .otherwise({ redirectTo: '/home' });
}]);

作为旁注,从{language}删除routes.MapRoute并传递http://localhost:4416/#/contact的常规网址确实有效,但没有任何本地化处理。所以我通常使用的是URL中的语言路由(它总是在那里,并且在哈希标记之前找到)。
哦,仅作为参考,我基于AngularStart项目,我将所有软件包更新为ASP.MVC5,EF6,AngularJS 1.2.23

编辑
我知道我的Global.asax.cs文件会触发两次,第一次从我的网址获取语言,因为我默认在我的项目属性中的地址,但随后发生的是AngularJS触发器启动然后重新路由到默认/home,因为否则。我假设我可能不得不在Angular代码中加入一些东西来处理语言,但是我需要提出的内容对我来说并不清楚......

1 个答案:

答案 0 :(得分:0)

经过一段时间后,我设法让它的大部分工作(除了html5mode)。因此,如果我们坚持使用哈希标签,那么一切正常......让我们看看代码

Angular app声明:

var app = angular.module('main', ['ngCookies', 'ngRoute', 'ngGrid', 'ngResource', 'ui.bootstrap']);     //Define the main module

app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
      //Setup routes to load partial templates from server. TemplateUrl is the location for the server view (Razor .cshtml view)
      $routeProvider
          .when('/home', { templateUrl: '/home/main', controller: 'MainController' })
          .when('/contact', { templateUrl: '/home/contact', controller: 'ContactController' })
          .when('/about', { templateUrl: '/home/about', controller: 'AboutController' })
          .when('/demo', { templateUrl: '/home/demo', controller: 'DemoController' })
          .when('/angular', { templateUrl: '/home/angular' })
          .otherwise({ redirectTo: '/home' });
    }]);

Shared\_Layout.cshtml代码

<head>
    <base id="basePath" href="/@((ViewContext.RouteData.Values["language"] != null) ? ViewContext.RouteData.Values["language"] : "en")/" />  
</head>

<body>
    <!-- the rest of your bootstrap navbar code here... -->
    <li class="dropdown">
        <a href='' class="dropdown-toggle" data-toggle="dropdown">Pages<b class="caret"></b></a>
        <ul class="dropdown-menu">
          <li><a href='#/home'>Home</a></li>
          <li><a href="#/demo">Demo</a></li>
          <li><a href='#/angular'>Learn Angular</a></li>
          <li><a href='#/about'>About</a></li>
          <li><a href='#/contact'>Contact</a></li>
        </ul>
      </li>
</body>

App_Start\RouteConfig.cs代码

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(
          name: "Default",
          url: "{language}/{controller}/{action}/{id}",
          defaults: new
          {
            language = "en",
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional,            
            culture = "CA"
          },
          constraints: new { language = @"^[a-zA-Z]{2}$" }
      );

      routes.MapRoute(
          name: "DefaultWithoutLang",
          url: "{controller}/{action}/{id}",
          defaults: new
          {
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional
          }
      );
    }
}

然后终于在Global.asax文件中,我添加了这个新函数

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
  string connectedUsername = "";
  if (HttpContext.Current.User.Identity.IsAuthenticated)
  {
    connectedUsername = HttpContext.Current.User.Identity.Name;
  }

  var handler = Context.Handler as MvcHandler;
  var routeData = handler != null ? handler.RequestContext.RouteData : null;

  var routeCulture = (routeData != null && routeData.Values.ContainsKey("language")) ? routeData.Values["language"].ToString() : null;
  var phpsessionid = HttpContext.Current.Request.Cookies["PHPSESSID"];
  var languageCookie = HttpContext.Current.Request.Cookies["language"];
  var userLanguages = HttpContext.Current.Request.UserLanguages;

  // Set the Culture based on a route, a cookie or the browser settings,
  // or default value if something went wrong
  var cultureInfo = new CultureInfo(
      routeCulture ?? (
          languageCookie != null
             ? languageCookie.Value
             : userLanguages != null
                 ? userLanguages[0]
                 : "en")
  );

  // save language in a cookie (fr, en, es, ...)
  var langCookie = new HttpCookie("language", cultureInfo.TwoLetterISOLanguageName);
  HttpContext.Current.Response.AppendCookie(langCookie);

  Thread.CurrentThread.CurrentUICulture = cultureInfo;
  Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
}

所以它除了前面指定的html5mode之外都工作。如果有人可以帮我解决这个问题,我会很高兴...我在某个地方读到我可能需要一个中间件来捕获404并以某种方式对其进行转换,但我不太明白这一部分。

如果发现任何错误,请随意更正我的代码(在ASP和Angular中仍然是新的)。