正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推荐使用HTML5 pushState的URL style的。
localhost:3002/crisis-center/
而不是Angular 1中所使用的“hash URL sytle“
localhost:3002/src/#/crisis-center/
这种URL Style带来的问题是,直接输入的URL会直接访问对应Server资源,换言之,要支持这种URL Style,Server端必须增加额外的Routing才行。本文简单介绍一下在ASP.NET Core上的三种解决思路。
MiddleWare的实现代码:
public class NotFoundMiddleware
{
private readonly RequestDelegate _next;
public NotFoundMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
string path = httpContext.Request.Path;
await _next(httpContext);
if (httpContext.Response.StatusCode == 404 &&
(path.StartsWith("/allowpath1")
|| path.StartsWith("/allowpath2"))
{
string indexPath = "wwwroot/index.html";
// Redirect is another way
//httpContext.Response.Redirect(indexPath, permanent: true);
httpContext.Response.Clear();
httpContext.Response.StatusCode = 200; // HttpStatusCode.OK;
httpContext.Response.ContentType = "text/html";
await httpContext.Response.WriteAsync(File.ReadAllText(indexPath));
}
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class NotFoundMiddlewareExtensions
{
public static IApplicationBuilder UseNotFoundMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware();
}
}
然后再Startup Class中使用该MiddleWare:
app.UseNotFoundMiddleware();
public class HomeController : Controller
{
// GET: //
public IActionResult Index()
{
return View();
}
}
创建Index.cshtml,必须放置在Views\Home或者Views\Shared文件夹中,文件内容即index.html内容。
然后再Startup 类中指定default routing:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//services.AddMvcCore()
// .AddJsonFormatters();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute("AngularDeepLinkingRoute", "{*url}",
new { controller = "Home", action = "Index" });
});
}
值得注意的是,必须在project.json中把Views文件夹加入publishOptions的include部分:
"publishOptions": {
"include": [
"wwwroot",
"Views",
"web.config",
],
"exclude": [
"node_modules",
"bower_components"
]
},
public void Configure(IApplicationBuilder app)
{
app.UseIISPlatformHandler();
var angularRoutes = new[] {
"/allowpath1",
"/allowpath2",
};
app.Use(async (context, next) =>
{
if (context.Request.Path.HasValue &&
null !=
angularRoutes.FirstOrDefault(
(ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase)))
{
context.Request.Path = new PathString("/");
}
await next();
});
app.UseDefaultFiles();
app.UseStaticFiles();
}
是为之记。
Alva Chien
2016.8.24