IIS站点中window.location.href带斜杠跳转404,相对路径正常问题排查
这个问题我碰到过好多次了,本质就是开发环境和生产部署环境的网站根路径(虚拟目录)不一致导致的,我给你掰扯清楚来龙去脉:
1. 开发环境(VS2017 + IIS Express)为啥能正常工作?
当你在VS里用IIS Express跑MVC项目时,它会自动把你的项目名MbsaExercise设为站点的虚拟目录。举个例子,你的页面URL可能是http://localhost:5000/MbsaExercise/Home/Index,这时候网站的根路径是http://localhost:5000/MbsaExercise/。
你写的window.location.href = '/MbsaExercise/MobileExerciseDescriptionMaint?mode=Init',浏览器会把它解析成http://localhost:5000/MbsaExercise/MobileExerciseDescriptionMaint?mode=Init——刚好和项目的路由匹配,自然能正常跳转。
2. 部署到IIS默认网站后为啥会404?
等你把项目部署到IIS默认网站时,情况就变了:
- 如果是把项目直接部署到默认网站的根目录(没有虚拟目录),那网站的根路径就是
http://你的服务器IP/,这时候原来的/MbsaExercise/xxx会被浏览器解析成http://你的服务器IP/MbsaExercise/xxx——但你的项目里根本没有这个路径(因为控制器路由是/MobileExerciseDescriptionMaint),所以直接404。 - 如果是把项目部署成默认网站下的子应用程序(虚拟目录别名是
MbsaExercise),那当前页面的URL可能是http://你的服务器IP/MbsaExercise/Home/Index,这时候你用/MbsaExercise/xxx,浏览器还是会从域名根目录(http://你的服务器IP/)出发找路径,看似没问题,但如果你的路由配置里没加这个前缀,或者IIS的应用程序映射有问题,也可能出现404。
而换成不带斜杠的MbsaExercise/xxx或带点的./MbsaExercise/xxx时,浏览器会以当前页面的URL路径为起点拼接:
- 比如当前页面是
http://你的服务器IP/Home/Index,./MobileExerciseDescriptionMaint?mode=Init会拼成http://你的服务器IP/MobileExerciseDescriptionMaint?mode=Init,刚好匹配路由; - 如果当前页面是
http://你的服务器IP/MbsaExercise/Home/Index,就会拼成http://你的服务器IP/MbsaExercise/MobileExerciseDescriptionMaint?mode=Init,也能正常访问。
3. 最佳解决方案:别硬写路径,用MVC的UrlHelper自动生成
为了避免这种环境差异的坑,最好不要手动写死路径,而是用MVC自带的Url.Action或Url.Content来生成适配所有环境的路径。
示例代码(在视图里写):
<script> // 用Url.Action生成路由路径,自动适配虚拟目录 var targetUrl = '@Url.Action("MobileExerciseDescriptionMaint", "你的控制器名", new { mode = "Init" })'; window.location.href = targetUrl; </script>
或者用Url.Content处理静态/直接路径:
<script> var targetUrl = '@Url.Content("~/MobileExerciseDescriptionMaint?mode=Init")'; window.location.href = targetUrl; </script>
这里的~/是MVC的根路径标记,它会自动识别当前网站的虚拟目录:开发环境会转换成/MbsaExercise/...,部署到根目录会转换成/...,部署到子应用会转换成/子应用名/...,完美解决环境差异问题。
一句话总结
/xxx是域名根绝对路径,只认域名最开头的目录,和当前页面位置无关;xxx/./xxx是相对路径,跟着当前页面的路径走;- 硬写绝对路径会因为开发和部署的虚拟目录不同失效,用MVC的UrlHelper生成路径才是正道。
内容的提问来源于stack exchange,提问作者iqworks

