我最近遇到了一个问题,我们被告知要从我们的Backbone应用程序中删除哈希符号。这提出了两个问题:(a)ASP.NET路由需要处理任何远程链接的URL(目前这对哈希符号没有问题),这样我们就不会遇到404错误而且(b)正确的路由需要保存并传递给客户端(Backbone)应用程序。我们目前正在为后端使用ASP.NET MVC5和Web API 2。
设置
对于一个示例(和测试项目),我使用Backbone创建了一个测试项目 - 一个简单的C#ASP.NET MVC5 Web应用程序。它非常简单(这里是index.cshtml文件的副本,请忽略注释掉的内容,因为它们将在下面解释):
<script type="text/javascript">
$(document).ready(function(event) {
Backbone.history.start({
//pushState: true,
//root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
});
</script>
<div class="jumbotron">
<h3>Backbone PushState Test</h3>
</div>
<div class="row"></div>
现在,在没有启用pushState的情况下,我没有问题远程链接到此路由,即http://localhost/Home/Index#test/sometext
结果是div
类.row
现在是"Hello, sometext"
。
问题
启用pushState将允许我们使用 / 替换网址中的那个讨厌的#,即:http://localhost/Home/Index/test/sometext
。我们可以使用router.navigate("url", true);
的Backbone方法(以及其他方法)来手动调整URL。 然而,这并不能解决远程链接的问题。因此,在尝试访问http://localhost/Home/Index/test/sample
时,您最终会遇到IIS提供的典型404.0错误。所以,我认为它是在 RouteConfig.cs 文件中处理的 - 在里面,我添加了一个“ CatchAll ”路线:
routes.MapRoute(
name: "CatchAll",
url: "{*clientRoute}",
defaults: new { controller = "Home", action = "Index" }
);
我还取消注释Backbone.history.start()中的pushState和root属性;方法:
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
这使我至少可以在链接到这些路线时超过404.0页面 - 这很好。但是,当我去找他们时,没有一条路线真正“触发”。尝试在Chrome,Firefox和IE11中调试它们后,我注意到没有任何事件触发。但是,如果我使用appRouter.navigate("/help", { trigger: true });
手动导航到它们,则会捕获路由并触发事件。
我现在不知道接下来应该从哪里开始进行故障排除。我已将我的Javascript放在$(document).ready()事件以及window.onload事件中(以及不在事件内部);这些都没有纠正这个问题。任何人都可以提供关于下一步的建议吗?
答案 0 :(得分:1)
您只需在“新路线”行之后移动Backbone.history.start。
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
请务必转到“... /主页/索引/帮助”。如果它不起作用,请尝试暂时删除root并转到“... / help”以查看根是否是问题。
如果仍有问题,请在“返回”行的Backbone.History.loadUrl中设置js断点。它从History.start的最后一行调用,以在页面加载时执行当前浏览器URL。 “this.matchRoot()”必须通过,“fragment”与“this.handlers”中的每个“route”或regexp字符串匹配。您可以看到浏览器URL与路由正则表达式匹配的原因或原因。
要设置为js断点,请在浏览器中按F12打开开发控制台,按Ctrl-O或Ctrl-P打开js文件,然后键入骨干js文件的名称。然后搜索“loadUrl:”。您还可以搜索“Router =”以查找路由器类定义的开头(与“View =”和“Model =”相同,以查找主干视图/模型实现代码)。当我遇到这样的问题时,我发现查看骨干代码非常有用。它具有令人惊讶的可读性以及获得答案的更好的地方?
如果你的js文件碰巧被缩小/压缩,最好关闭它。或者,您可以尝试使用浏览器unminify选项。在Chrome中,这是“{}”按钮或“漂亮的打印”。然后js代码不是全部在1行,你可以设置断点。但函数和变量名称可能仍会受到损坏。
答案 1 :(得分:0)
我通过以下方式使用感觉“hackish”解决了我自己的问题。如果有人能提交更好的回复,我们将不胜感激!
我的解决方案: 我全局覆盖默认的Backbone.Router.intilaize方法(它为空),其中包含以下内容:
$(document).ready(function (event) {
var _root = "/Home/Index/";
_.extend(Backbone.Router.prototype, {
initialize: function () {
/* check for route & navigate to it */
var pathName = window.location.pathname;
var route = pathName.split(_root)[1];
if (route != undefined && route != "") {
route = "/" + route;
this.navigate("", { trigger: false });
this.navigate(route, { trigger: true });
}
}
});
});