我打算用asp.net MVC4构建一个SPA,但由于路由,我不太确定如何设置我的项目。例如,大多数SPA使用像这样mypage/#/News/today
的hashrouting。
如果我没有指定名为mypage/News/today
Controller
且行动News
的{{1}},则直接浏览today
会怎样?
应用程序应该处理两种类型的路由,我该如何实现?
我是否必须以经典的方式构建我的应用程序,例如使用适当的操作和视图添加多个控制器,还使用knockout,jquery等构建客户端MVC结构?
答案 0 :(得分:0)
您必须让所有通往“页面”的路由都掉落,以让您的SPA处理它们(如果不是到达您的SPA中的真实页面,则包括假冒的404),但同时,需要确保您将获得正确的API调用和/或文件请求响应。
下面是我的设置(我正在使用Vue作为js框架,但这无关紧要,对于服务器端而言根本不重要)。
首先,除了默认的路由设置外,还将其添加到您的Startup.cs中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.Use(async (context, next) =>
{
await next();
var path = context.Request.Path.Value;
// If there's no available file and the request doesn't contain an extension, we're probably trying to access a page
if (context.Response.StatusCode == (int)HttpStatusCode.NotFound && !Path.HasExtension(path) && !path.StartsWith("/api"))
{
context.Request.Path = "/Home/SpaRedirect"; // attempts to redirect to the URL within the SPA
context.Response.StatusCode = (int)HttpStatusCode.OK; // Make sure we update the status code, otherwise it returns 404
await next();
}
});
...
}
因此,新添加到HomeController的SpaRedirect如下所示,只是将请求的URL存储在ViewData中...
public IActionResult SpaRedirect()
{
ViewData["RequestUrl"] = HttpContext.Request.Path;
return View("Index");
}
然后在Index.cshtml中,只需在会话存储中捕获请求的url,这样我们就可以在客户端使用它:
<script src="~/dist/main.js" asp-append-version="true">
sessionStorage.setItem("redirectAttempt", @ViewData["RequestUrl"]);
</script>
然后在启动脚本文件(SPA的入口点)中,添加以下内容:
let redirectAttemptUrl = sessionStorage.getItem("redirectAttempt");
if (redirectAttemptUrl) {
router.push(redirectAttemptUrl);
sessionStorage.removeItem("redirectAttempt");
}
这只是检查是否存在所请求的URL,然后SPA的路由器尝试导航到该URL(在上面的示例中是一个vue-router),然后将其从存储中删除。
因此,如果用户尝试通过在URL栏中输入URL(或通过书签)直接导航到URL,则该应用将加载并放置到正确的位置(如果存在)。 。。。把我们带到最后一块...
最后,您必须在SPA中处理“ 404”,这是通过在您的route defs中添加一个包罗万象的路由来完成的,该路由将用户带到您设置的404组件页面,对于Vue来说,它如下所示:
// adding an explicit 404 path as well for programmatically handling when something is not found within the app, i.e. return this.$router.push('/404')
{ path: '/404', component: NotFound, name: '404', alias: '*' }, // remove alias to not show the actual url that resulted in our little 404 here
{ path: '*', redirect: '/404' }, // this is the catch-all path to take us to our 404 page
注意:我不是专家,所以可能会遗漏一些东西,希望对如何改进它有更多意见。这不能处理的一件事是,如果用户已经在SPA中并且由于某种原因直接编辑URL以导航到其他地方,它仍然会触发服务器调用和完全重载,理想情况下不会这样,但这是我要讲的一个很简单的问题。