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

时间:2017-01-26 14:10:15

标签: angular asp.net-web-api url-routing angular-cli asp.net-web-api-routing

我有一个使用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中运行它,它在http://localhost:5200启动IIS Express。

此设置运行良好,并允许我利用Angular CLI的实时重新加载支持。

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

为此,我需要更改WebApiConfig路由以提供我的静态文件,该文件将位于/dist/下。

对于ASP.NET Core和MVC 4,有很多文章展示了如何在Microsoft.AspNetCore.StaticFiles中使用Microsoft.AspNet.StaticFiles(或Startup.cs)。基本上,将以下两行添加到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程序集的方法。
  3. 那我该如何实现呢?

3 个答案:

答案 0 :(得分:4)

您需要第一次禁用角度文件的网络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>

答案 1 :(得分:2)

我无法让Dmitriy's answer为我工作,但他确实让我走上正轨。

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

他们是:

<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>

答案 2 :(得分:0)

首先,您应该像下面这样发布您的 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="/" /> 中的网址是 --base-href / 中的网址。