Angular 2的HTML5 pushState在ASP.NET Core上的解决思路

来源:互联网 发布:日语 网络聊天 编辑:程序博客网 时间:2024/06/04 16:46

Angular 2的HTML5 pushState在ASP.NET Core上的解决思路

正如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上的三种解决思路。

  • 解决思路一,使用NotFound的MiddleWare
    MSDN 有一篇Article介绍了如何实现自己的MiddleWare来实现自定义404 Page,当然,该Article主要Focus在如何智能纠错。我们这里只关注如何使用类似的方法来达到所需要的效果。

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<NotFoundMiddleware>();        }    }

然后再Startup Class中使用该MiddleWare:

app.UseNotFoundMiddleware();
  • 解决思路二,使用Routing
    使用Routing是另外一种解决问题的思路,即把所有默认的request发送给默认的Controller。这里,要求启用标准的MVC。
    实现一个HomeController类:
    public class HomeController : Controller    {        // GET: /<controller>/        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"    ]  },
  • 解决思路三,直接修改Request的Path
    这个思路更加简单暴力,也更为高效,因为之前的思路要么是访问失败(404的StatusCode)后的Redirect,要么是路由失败后的Default实现,这个思路直接在Request入口就改写了Request的Path
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

1 0
原创粉丝点击