55

我一直在使用 Web API 在 ASP.NET MVC 内部开发一个AngularJS项目。除非您尝试直接转到有角度的路由 URL 或刷新页面,否则它工作得很好。我认为这将是我可以使用MVC 的路由引擎处理的事情,而不是胡乱使用服务器配置。

当前的 WebAPIConfig:

public static class WebApiConfig
{
    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 },
            constraints: new { id = @"^[0-9]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiWithActionAndName",
            routeTemplate: "api/{controller}/{action}/{name}",
            defaults: null,
            constraints: new { name = @"^[a-z]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiWithAction",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { action = "Get" }
        );
    }
}

当前路由配置:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute(""); //Allow index.html to load
        routes.IgnoreRoute("partials/*"); 
        routes.IgnoreRoute("assets/*");
    }
}

当前 Global.asax.cs:

public class WebApiApplication : HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        var formatters = GlobalConfiguration.Configuration.Formatters;
        formatters.Remove(formatters.XmlFormatter);
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
            PreserveReferencesHandling = PreserveReferencesHandling.None,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        };
    }
}

目标:

/api/* 继续转到 WebAPI,/partials/和 /assets/都转到文件系统,绝对其他任何东西都被路由到 /index.html,这是我的 Angular 单页应用程序。

- 编辑 -

我似乎已经让它工作了。将此添加到RouteConfig.cs的底部:

 routes.MapPageRoute("Default", "{*anything}", "~/index.html");

对根 web.config 的更改:

<system.web>
...
  <compilation debug="true" targetFramework="4.5.1">
    <buildProviders>
      ...
      <add extension=".html" type="System.Web.Compilation.PageBuildProvider" /> <!-- Allows for routing everything to ~/index.html -->
      ...
    </buildProviders>
  </compilation>
...
</system.web>

但是,它闻起来像黑客。有没有更好的方法来做到这一点?

4

6 回答 6

27

使用通配符段:

routes.MapRoute(
    name: "Default",
    url: "{*anything}",
    defaults: new { controller = "Home", action = "Index" }
);
于 2013-10-28T19:10:58.330 回答
12

建议更多本地方法

<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404" subStatusCode="-1"/>
        <error statusCode="404" prefixLanguageFilePath="" path="/index.cshtml" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>
于 2014-06-17T09:48:05.760 回答
5

就我而言,这些方法都不起作用。我被困在 2 个错误消息地狱中。要么没有提供这种类型的页面,要么是某种 404。

url重写工作:

<system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS" stopProcessing="true">
          <match url="[a-zA-Z]*" />

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

注意我在 [a-zA-Z] 上匹配,因为我不想重写任何 .js .map 等 url。

这在 VS 中开箱即用,但在 IIS 中,您可能需要安装 url-rewrite 模块https://www.iis.net/downloads/microsoft/url-rewrite

于 2016-10-04T20:15:15.787 回答
4

我有一个与前几个答案类似的方法,但缺点是如果有人错误地进行 API 调用,他们最终会得到那个索引页面而不是更有用的东西。

所以我更新了我的,这样它将为任何不以 /api 开头的请求返回我的索引页面:

        //Web Api
        GlobalConfiguration.Configure(config =>
        {
            config.MapHttpAttributeRoutes();
        });

        //MVC
        RouteTable.Routes.Ignore("api/{*anything}");
        RouteTable.Routes.MapPageRoute("AnythingNonApi", "{*url}", "~/wwwroot/index.html");
于 2017-02-02T18:39:00.093 回答
1

几天前我一直在使用 OWIN Self-Host 和 React Router,并且遇到了可能类似的问题。这是我的解决方案。

我的解决方法很简单;检查它是否是系统中的文件;否则返回index.html。因为如果请求了其他一些静态文件,您并不总是希望返回 index.html。

在您的 Web API 配置文件中:

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

config.Routes.MapHttpRoute(
    name: "Default",
    routeTemplate: "{*anything}",
    defaults: new { controller = "Home", action = "Index" }
);

然后创建一个HomeController如下...

public class HomeController: ApiController
{
    [HttpGet]
    [ActionName("Index")]
    public HttpResponseMessage Index()
    {
        var requestPath = Request.RequestUri.AbsolutePath;
        var filepath = "/path/to/your/directory" + requestPath;

        // if the requested file exists in the system
        if (File.Exists(filepath))
        {
            var mime = MimeMapping.GetMimeMapping(filepath);
            var response = new HttpResponseMessage();
            response.Content = new ByteArrayContent(File.ReadAllBytes(filepath));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(mime);
            return response;
        }
        else
        {
            var path = "/path/to/your/directory/index.html";
            var response = new HttpResponseMessage();
            response.Content = new StringContent(File.ReadAllText(path));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
            return response;
        }
    }
}
于 2020-06-21T18:11:01.420 回答
0

好吧,我刚刚删除了RouteConfig.RegisterRoutes(RouteTable.Routes);调用Global.asax.cs,现在无论我输入什么 url,如果资源存在,它将被提供。甚至 API 帮助页面仍然有效。

于 2016-02-18T13:47:45.303 回答