ASP.NET 5+;角度2布线(模板页面未重新加载)

ASP.NET 5+;角度2布线(模板页面未重新加载),asp.net,angular,asp.net-core,angular2-routing,Asp.net,Angular,Asp.net Core,Angular2 Routing,Angular 2 beta默认使用html5路由。 但是,当您转到某个组件,并且路由发生更改(例如)并且重新加载/刷新页面时,不会加载任何内容。 该问题也在本中提出。 大多数答案都说,如果我们打算在angular 2中采用HTML5路由,那么这个路由问题应该在服务器端解决。更多讨论 我不确定如何使用asp.net服务器环境处理此问题 是否有任何angular 2开发人员也使用asp.net并遇到此问题 另外,我正在使用ASP.NET5。我的2条路线使用MVC路线。您是否使用了: 组件中的指令:

Angular 2 beta默认使用html5路由。 但是,当您转到某个组件,并且路由发生更改(例如)并且重新加载/刷新页面时,不会加载任何内容。

该问题也在本中提出。 大多数答案都说,如果我们打算在angular 2中采用HTML5路由,那么这个路由问题应该在服务器端解决。更多讨论

我不确定如何使用asp.net服务器环境处理此问题

是否有任何angular 2开发人员也使用asp.net并遇到此问题

另外,我正在使用ASP.NET5。我的2条路线使用MVC路线。

您是否使用了:


组件中的指令:[RouterOutlet,RouterLink]

您正在寻找的功能是URL重写。有两种可能的处理方法。经典的方法是让IIS完成工作,如下所述:

如果您不想依赖IIS,可以改为在ASP.NET 5中间件中处理此问题,如我的回答所示:


您需要在ASP.NET MVC中使用此路由

app.UseMvc(routes =>
{
     routes.MapRoute("Default", "{*url}",  new { @controller = "App", @action = "Index" });
});

然后您需要使用basePath选项设置SystemJS

您看到的问题与客户端的角度路由和MVC服务器端路由之间的差异有关。您实际上收到了一个
404页面未找到
错误,因为服务器没有该路由的控制器和操作。我怀疑您没有处理错误,这就是为什么看起来好像什么都没有发生

当您重新加载
http://localhost:5000/aboutus
或者,如果您试图通过快捷方式直接链接到该URL,或者通过在地址栏中键入该URL(深度链接),它会向服务器发送请求。ASP.NET MVC将尝试解析该路由,在您的情况下,它将尝试加载
aboutusController
,并运行
Index
操作。当然,这不是您想要的,因为您的
aboutus
路线是一个角度组件

您应该做的是为ASP.NET MVC路由器创建一种将URL传递回客户端的方法


Startup.cs
文件中的
Configure()
方法中,向现有路由添加“spa回退”路由:

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

    // when the user types in a link handled by client side routing to the address bar 
    // or refreshes the page, that triggers the server routing. The server should pass 
    // that onto the client, so Angular can handle the route
    routes.MapRoute(
        name: "spa-fallback",
        template: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
});

通过创建指向最终加载Angular应用程序的控制器和视图的全面路由,这将允许将服务器未处理的URL传递到客户端以进行正确路由。

应用@ZOXEXIVO的解决方案,然后在_Layout.cshtml中添加以下内容:

<head>
    <base href="/"/>
    .....
</had>

.....

启动.cs
中,将其添加到
配置方法中。这必须在其他
app
语句之前

app.Use(async (context, next) => {
    await next();

    if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) {
        context.Request.Path = "/index.html"; // Put your Angular root page here 
        await next();
    }
});

我最喜欢的解决方案是将以下代码添加到Global.asax.cs中,它可以非常顺利、可靠地解决问题:

     private const string RootUrl = "~/Home/Index";
     // You can replace "~Home/Index" with whatever holds your app selector (<my-app></my-app>)
     // such as RootUrl="index.html" or any controller action or browsable route

     protected void Application_BeginRequest(Object sender, EventArgs e)
        {
            // Gets incoming request path
            var path = Request.Url.AbsolutePath;

            // To allow access to api via url during testing (if you're using api controllers) - you may want to remove this in production unless you wish to grant direct access to api calls from client...
            var isApi = path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase);
            // To allow access to my .net MVCController for login
            var isAccount = path.StartsWith("/account", StringComparison.InvariantCultureIgnoreCase);
            if (isApi || isAccount)
            {
                return;
            }

            // Redirects to the RootUrl you specified above if the server can't find anything else
            if (!System.IO.File.Exists(Context.Server.MapPath(path)))
                Context.RewritePath(RootUrl);
        }
private const string RootUrl=“~/Home/Index”;
//您可以将“~Home/Index”替换为保存应用程序选择器的任何内容()
//例如RootUrl=“index.html”或任何控制器操作或可浏览的路由
受保护的无效应用程序\u BeginRequest(对象发送方,事件参数e)
{
//获取传入请求路径
var path=Request.Url.AbsolutePath;
//要允许在测试期间通过url访问api(如果您使用的是api控制器),您可能希望在生产中删除此项,除非您希望授予从客户端直接访问api调用的权限。。。
var isApi=path.StartsWith(“/api”,StringComparison.InvariantCultureIgnoreCase);
//允许访问my.net MVCController进行登录
var isAccount=path.StartsWith(“/account”,StringComparison.InvariantCultureIgnoreCase);
如果(isApi | | isAccount)
{
返回;
}
//如果服务器找不到任何其他内容,则重定向到上面指定的RootUrl
如果(!System.IO.File.Exists(Context.Server.MapPath(path)))
重写路径(RootUrl);
}

您可以同时使用这两种路由 从角度路由呼叫总部/索引时

Home/Index.cshtml
<my-app></my-app>

app.routing.ts
    const routes: Routes = [
        { path: '', redirectTo: '/Home/Index', pathMatch: 'full' },
        { path: 'Home/Index', component: DashboardComponent }
    ]
Home/Index.cshtml
app.routing.ts
常数路由:路由=[
{路径:'',重定向到:'/Home/Index',路径匹配:'full'},
{路径:“主/索引”,组件:仪表板组件}
]
所以,URL何时将成为主/索引
将加载活动url的组件,以便加载仪表板组件。

这里还有两个解决此问题的选项。您可以将哈希定位策略添加到应用程序模块中

import { LocationStrategy, HashLocationStrategy } from '@angular/common';

@NgModule({
imports: [.... ],
declarations: [...],
bootstrap: [AppComponent],
providers: [
{
  provide: LocationStrategy,
  useClass: HashLocationStrategy
}
]
})
export class AppModule { }
此选项仅适用于您的Angular2应用程序中位于家庭ASP控制器上的部分

第二个选项是向ASP控制器添加与Angular 2应用程序路由匹配的路由,并返回“索引”视图


我一点运气都没有

 routes.MapRoute("Default", "{*url}",  
                  new { @controller = "App", @action = "RedirectIndex" });
工作。我仍然有一个404和任何客户端的路线

更新:
找出了“全部捕获”路由不起作用的原因:我定义了一个属性路由(
[route(“api/RedirectIndex”)]
),虽然普通路由可以通过回退路由直接访问,但它没有启动。删除属性路由使其工作

另一个似乎与“捕获所有”路由处理程序一样简单的解决方案是创建一个自定义处理程序,该处理程序在
Configure()
中的中间件管道末端触发:

如果没有其他处理程序接收请求,那么这基本上就是一个“一网打尽”的路由,它只是通过现有的URL请求发送index.html

即使与(在这种情况下)组合使用,也能很好地发挥作用,因为上面提到的内容永远不会被解雇

就这个话题写了一篇博文:


以上选择的解决方案对我不起作用。在跟踪T的所有评论后,我也得到了404。我正在MVC中使用angular5应用程序
 routes.MapRoute("Default", "{*url}",  
                  new { @controller = "App", @action = "RedirectIndex" });
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

});

//handle client side routes
app.Run( async (context) =>
{
        context.Response.ContentType = "text/html";
        await context.Response.SendFileAsync(Path.Combine(env.WebRootPath,"index.html"));

});
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Catch All",
                "dist/{*url}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }


            );