【问题标题】:MVC 6 Routing, SPA fallback + 404 Error PageMVC 6 路由,SPA 回退 + 404 错误页面
【发布时间】:2016-02-10 21:03:25
【问题描述】:

使用 ASP.NET Core 1.0 的 MVC 6RC1,您可以在调用 app.UseMvc 时从 Startup.Configure 函数中映射路由。我已经映射了一个“spa-fallback”路由,以确保 HomeControllerIndex 视图是默认值,如下所示:

public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env, 
                      ILoggerFactory loggerFactory)
{
    // ... omitted for brevity
    app.UseExceptionHandler("/Home/Error");
    app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");

    app.UseMvc(routes =>
    {
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
        routes.MapRoute("spa-fallback", "{*anything}", new { controller = "Home", action = "Index" });
        routes.MapWebApiRoute("defaultApi", "api/{controller}/{id?}");
    });
}

我希望回退,以便我的 Angular2 应用的路由不会产生 404, Not Found 的 HTTP 状态代码。但是,当用户无意中尝试导航到不存在的页面视图时,我还需要正确处理。你可能会注意到我也调用了app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");

使用状态代码和“spa-fallback”路由重定向到我的错误页面的调用似乎相互排斥——这意味着我似乎只能拥有一个或另一个(但遗憾的是不能同时拥有)。有谁知道我怎样才能做到两全其美?

【问题讨论】:

  • 目前新包可以在“Microsoft.AspNetCore.SpaServices”中找到:“1.0.0-beta-000005”。
  • @SamanAhmadi,我看到了...谢谢
  • @DavidPine 您会考虑更改接受的答案吗?试图建立我的街头信誉;-)

标签: c# asp.net-mvc-routing asp.net-core-mvc angular2-routing


【解决方案1】:

我想出了两种可能的解决方法/解决方案。

ASP.NET Core 1.0,RC1

特别是使用 Angular2,我们可以简单地换掉 LocationStrategy。例如在我的wwwroot/app/boot.ts 我有以下内容:

import {provide} from "angular2/core";
import {bootstrap} from "angular2/platform/browser";
import {LocationStrategy, HashLocationStrategy, ROUTER_PROVIDERS} from "angular2/router";
import {HTTP_PROVIDERS} from "angular2/http";

import {AppComponent} from "./app.component"

bootstrap(AppComponent,
    [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        provide(LocationStrategy, { useClass: HashLocationStrategy })
    ]);

请注意,我正在使用provide 函数来用HashLocationStrategy 覆盖标准LocationStrategy。这会在 URL 中添加 # 并防止 MVC 错误地抛出 404's,而且当用户手动输入 URL 不存在。

ASP.NET Core 1.0,RC2

只需使用Microsoft.AspNet.NodeServices。在这个库中有AngularServicesReactServices,它们允许通过MapSpaFallbackRoute 函数专门映射SPA 路由。我声明我们需要等待 RC2,但要了解当前的实现并未完全按预期运行。

【讨论】:

  • 感谢您让我知道这件事,我要去看看。在角度方面,我不想使用哈希定位策略,因为 html5 浏览器不需要它。
【解决方案2】:

我花了一些时间才弄清楚如何在不使用 MVC 为我的索引提供服务的情况下执行此操作,并且仍然收到丢失文件的 404。这是我的 http 管道:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseDefaultFiles();
        app.UseStaticFiles();

        app.UseMvc(                
            routes => {
                routes.MapRoute(
                    name: "api",
                    template: "api/{controller}/{action}/{id?}");

                // ## commented out since I don't want to use MVC to serve my index.    
                // routes.MapRoute(
                //     name:"spa-fallback", 
                //     template: "{*anything}", 
                //     defaults: new { controller = "Home", action = "Index" });
        });

        // ## this serves my index.html from the wwwroot folder when 
        // ## a route not containing a file extension is not handled by MVC.  
        // ## If the route contains a ".", a 404 will be returned instead.
        app.MapWhen(context => context.Response.StatusCode == 404 &&
                               !Path.HasExtension(context.Request.Path.Value),
                    branch => {
                           branch.Use((context, next) => {
                               context.Request.Path = new PathString("/index.html");
                               Console.WriteLine("Path changed to:" + context.Request.Path.Value);
                               return next();});

                    branch.UseStaticFiles();
        });            
    }

【讨论】:

  • 感谢您对此进行调查,我应该更新我的问题或早点删除它——因为事后我已经弄清楚了。
  • 这个解决方案很好,因为它不需要 MVC。我目前使用 ASP.NET 作为静态文件服务器(无 MVC),但我确实希望能够将非资产路径重新路由到 index.html
  • 不错的答案 我建议对 When 谓词使用更好的代码:context => context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)
  • 谢谢!我将更新答案以包含此改进。
  • 就我而言,我没有使用任何 MVC 路由——除了静态文件,所有逻辑路径都应该路由到 index.html。所以,我首先删除了 UseMvc 语句。然后,我不得不删除 context.Response.StatusCode == 404 && 部分,否则我将获得 200 的所有请求。
【解决方案3】:

试试这个:

public void Configure(IApplicationBuilder app,
    IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{
    app.UseExceptionHandler("/Home/Error");
    app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");

    app.UseMvc(routes =>
    {
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
        routes.MapWebApiRoute("defaultApi", "api/{controller}/{id?}");
    });

    app.Run(async context =>
    {
        context.Response.Redirect("/Home/Index");
        await Task.CompletedTask;
    });
}

app.Run() 将捕获与之前定义的任何路由都不匹配的所有请求。这样,您可以获得自定义 spa 后备并同时使用 app.UseStatusCodePagesWithRedirects()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 2013-08-31
    • 2016-07-30
    • 2016-10-20
    • 1970-01-01
    相关资源
    最近更新 更多