进入特定Angular 2.0 SPA状态的外部链接无法正常工作

时间:2016-11-08 15:19:16

标签: html5 angular iis url-rewriting angular2-routing

我使用的是AngularJS 2.4.6,Typescript 2.1.2,IIS 8.0,Chrome,Visual Studio 2015

我正在使用Angular Heroes教程并注意到当我刷新浏览器时我得到了404响应(由于PathLocationStrategy -aka HTML5路径 - 默认使用)...所以这是有道理的,因为IIS看不到/仪表板回来。

有很多解决方案使用URL重写,我做了,确实正确地路由到index.html。

我的问题是,当我刷新浏览器时,我希望它处于相同的状态。这与使用哈希策略的角度1.5一样好用。

我是否需要做一些特定的事情来创建这种行为?原样(Angular 2.0),刷新最终导致基本状态显示而不是我所在的状态。

我注意到Rewrite操作将301发送回浏览器,因此index.html再次不知道预期的状态。

重要的是,外部链接(例如,来自电子邮件)如何进入Angular 2 app特定状态?

例如,如果我发送一封包含我的应用程序链接的电子邮件,例如:
  https://myserver/some/path/to/aState

这个简单的场景似乎无法与我尝试的所有内容一起使用IIS。

该项目不涉及MVC。客户端代码向webapi middletier web发出ajax请求,但出于我要求的目的,你可以假设根本没有http调用。

2 个答案:

答案 0 :(得分:0)

我假设您使用 Visual Studio 2015 上的ASP.NET MVC和解决方案根目录下的index.html开发解决方案,其文件/文件夹结构最少,如下所示:

- /Controllers
- index.html
- /src/app/ (Angular source)
- web.config

第1步:web.config配置

将以下rewrite rules添加到您的web.config的system.webServer部分:

<system.webServer>
  <rewrite>
    <rules>
      <rule name="clientRewrite rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" ignoreCase="true" negate="true" />      
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/assets/" ignoreCase="true" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

此配置会将所有请求(/ api和/ assets除外)重定向到index.html。您可以自定义此行为。

此外,请不要忘记在webpages中启用appSettings

<add key="webpages:Enabled" value="false" />

修改

buildProviders`汇编`部分中为html扩展名添加system.web

<buildProviders>
  <add extension=".html" type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor" />
</buildProviders>

第2步:index.html

请务必在index.html上的base href个标记之间添加<head> ... </head>

<base href="/">

第3步:Global.asax配置

您需要注册html分机。只需将以下方法添加到Global.asax.cs:

public static void RegisterHtmlExtension()
{
    RazorCodeLanguage.Languages.Add("html", new CSharpRazorCodeLanguage());
    WebPageHttpHandler.RegisterExtension("html");
}

并在RegisterHtmlExtension();方法中调用Application_Start()

您无需为angular views(模板)注册路线。以下(最小)服务器路由配置就足够了:

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

    //register custom routes (extensions, etc)
    var routePublisher = EngineContext.Current.Resolve<IRoutePublisher>();
    routePublisher.RegisterRoutes(routes);
}

如果您有WebAPI控制器,则可能需要为它们配置适当的路由。此配置应该有效:

public static class WebApiRouteProvider
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            "DefaultApi",
            "api/{controller}/{id}",
            new { area = "api", id = RouteParameter.Optional }
        );
    }
}

并且,您必须通过GlobalConfiguration.Configure(WebApiRouteProvider.Register);方法调用Application_Start()来注册这些路线。

<强>结论

这样,您就可以将所有请求重定向到index.html(除了在重写规则中明确定义的路径)。

并且,Angular将能够拦截具有给定路径的所有请求(例如:http://yoursite.com/about/ushttp://yoursite.com/account/login等),这将导致具有给定路径的渲染组件。

答案 1 :(得分:0)

您是否尝试过使用哈希策略?

RouterModule.forRoot(appRoutes, { useHash: true })