使用 Web API 路由 Angular 2 应用程序

Routing an Angular 2 app with Web API

我有一个使用 Angular CLI 创建的 Angular 2 应用程序。这必须调用 .NET 4.6 Web API。这个路线设置让我抓狂。

对于Angular,输出的默认文件夹是/dist。 Angular CLI 执行所有您梦寐以求的缩小和摇树优化,然后将其 JavaScript 文件和 index.html 输出到该文件夹​​。

因此,如果我 运行 index.html,将从同一文件夹中检索这些文件。一切正常,因为 index.html 包含一个像这样的标签:

<base href="/">

Web API 项目具有预期的结构,Angular 应用程序是其根部的寄生虫。

看起来像这样:

WebAPI_Project
|- App_Start
|    |
|    |-WebApiConfig.cs
|- Controllers
|- Models
|- src /* This is the root of the Angular app */
|    |- app
|    |    |- core           /* These three folders */
|    |    |- shared         /* are for the modules */
|    |    |- another_module /* used in the app     */
|    |    |- app.component.ts
|    |    |- app.module.ts
|    |- index.html
|- dist /* This is the Angular output folder */
     |- index.html
     |- main.bundle.js

WebApiConfig.cs 具有默认设置:

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

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

对于 运行 Angular 应用程序,我使用普通的 ng serve,它在 http://localhost:4200 上创建了一个网络服务器。此 Web 服务器对 Web API 项目一无所知,因此我还需要 运行 从 Visual Studio 中启动 IIS Express http://localhost:5200

此设置运行良好,让我可以利用 Angular CLI 的实时重新加载支持。

对我来说最大的缺点是这个配置与我们对生产的期望不同。在那里,我希望有一个网络服务器 (IIS),服务于 Web API 项目(目前在 /api/)和 Angular 应用程序(在 /,最好)。此外,在开发中,我不得不考虑 CORS,而生产设置不会。

为此,我需要更改 WebApiConfig 路由来为我的静态文件提供服务,这些文件将在 /dist/.

对于 ASP.NET Core 和 MVC 4,有很多文章展示了我应该如何在 Startup.cs 中使用 Microsoft.AspNetCore.StaticFiles(或 Microsoft.AspNet.StaticFiles)。基本上,将以下两行添加到 Configure 函数:

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{
    // Other stuff

    // Two new lines
    app.UseStaticFiles();
    app.UseDefaultFiles();

    app.UseMvc(m =>
    {
        // Other routes specified here
    });
}

问题是我既不使用 ASP.NET Core 也不使用 MVC。

尽管 Web API 显然是没有视图的 MVC,但 Web API 项目仅附带 WebApiConfig.cs 文件,没有 Startup.cs 也没有“IApplicationBuilder”。

我尝试将这一行添加到我的 Register 函数中:

config.Routes.IgnoreRoute("StaticFiles", "*.html");

这服务于 index.html(但在 localhost:5200/dist/index.html),但它找不到它的任何资产,因为 base href="/"。我可以在 index.html 中更改它,但随后 ng serve 中断。

我想我需要以下两件事之一:

  1. 一种创建路线的方法,因此对 /index.html 的引用服务于 /dist/index.html,或
  2. 一种使用前面提到的 StaticFiles 程序集的方法。

那么我该如何实现呢?

您需要首先 禁用 angular 文件的 Web api 路由,将其添加到 web.config,在 <system.webServer> </system.webServer> 内:

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
      </conditions>
      <action type="Rewrite" url="/index.html" />
    </rule>
  </rules>
</rewrite>

然后,将 <base href="/"> 添加到您的 index.html。

UPD:重写对 index.html

的访问

您可以添加另一个重写规则来覆盖对您的 /dist/ 文件夹的访问:

<rewrite>
    <rules>
        <rule name="DistAccess" stopProcessing="true">
            <match url="^(.*)/dist/(.*)" />
           <action type="Rewrite" url="{R:1}/{R:3}" />
        </rule>
    </rules>
</rewrite>

我无法让 为我工作,但他确实让我走上了正轨。

我需要两条规则:一条从根目录为 Angular 应用程序提供服务,同时维护 Web API /api/ 路由,另一条用于提供默认文档。

他们在这里:

<rewrite>
  <rules>
      <rule name="Serve Angular app from root" stopProcessing="true">
        <match url="([\w\.]+)" />
        <conditions>
          <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
        </conditions>
        <action type="Rewrite" url="/dist/{R:1}" />
      </rule>
      <rule name="Default document" stopProcessing="true">
        <match url="^$" />
        <action type="Rewrite" url="/dist/index.html" />
      </rule>
    </rules>
</rewrite>

首先,您应该像下面这样发布您的 angular 项目。

ng build --prod="true" --base-href /

然后将 Web 配置文件添加到您的 angular 项目。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
  <rules>
    <rule name="AngularJS Routes" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>
</system.webServer>
</configuration>

注意 <action type="Rewrite" url="/" /> 中的 url 是 --base-href / 中的 url .