ASP.NET MVC中如何编写适配子目录部署的fetch()相对路径
这个问题我之前部署ASP.NET MVC应用到子目录的时候也踩过一模一样的坑,分享几个亲测好用的解决办法,保证不管你部署在根目录还是各种子目录下,fetch路径都不会错:
方法一:直接用Razor辅助方法生成正确路径(内嵌脚本场景)
如果你的fetch代码是写在Razor视图的内嵌<script>标签里,那最简单的方式就是用ASP.NET自带的@Url.Action()辅助方法,它会自动根据当前应用的部署路径生成完整的正确URL,完全不用你自己拼路径。
示例代码:
<script> // 让服务器端帮你生成正确的Action路径 const dataFetchUrl = '@Url.Action("Data", "Home")'; fetch(dataFetchUrl) .then(response => response.json()) .then(data => console.log(data)); </script>
比如你的应用部署在https://www.example.com/qa/MyApp,@Url.Action("Data", "Home")会直接生成/qa/MyApp/Home/Data,完美适配部署环境,绝对不会出现跳去根目录的情况。
方法二:全局存储应用根路径(独立JS文件场景)
如果你的fetch代码是放在单独的JS文件里(没法直接用Razor语法),那可以先在布局页或者视图里把应用的根路径存成全局变量,然后在JS文件里引用这个变量拼接路径。
第一步,在_Layout.cshtml的<head>里添加全局变量:
<script> // 把应用的根路径存在全局window对象里 window.appRoot = '@Url.Content("~")'; </script>
这里的@Url.Content("~")会返回应用的绝对根路径,比如根目录部署就是/,子目录部署就是/MyApp/或者/qa/MyApp/。
第二步,在你的独立JS文件里使用这个全局变量:
// 拼接出正确的API路径 const dataFetchUrl = `${window.appRoot}Home/Data`; fetch(dataFetchUrl) .then(response => response.json()) .then(data => console.log(data));
这种方式可以让你的独立JS文件也能轻松拿到正确的部署路径,非常灵活。
方法三:谨慎使用相对路径(简单场景可选)
如果你的页面路由结构很简单,且JS代码所在的页面始终在应用根目录对应的视图里(比如Home/Index),那可以用相对路径./Home/Data,但这种方法局限性很大——如果你的页面在更深的路由层级(比如/Admin/Users/List),相对路径就会变成/Admin/Users/Home/Data,直接出错。所以除非你的应用路由特别简单,否则不推荐用这种方法。
小补充:用路由名称生成路径(可选)
如果你在ASP.NET MVC里配置了命名路由,也可以用@Url.RouteUrl()来生成路径,原理和@Url.Action()一样,比如:
const dataFetchUrl = '@Url.RouteUrl("HomeDataRoute", new { action = "Data", controller = "Home" })';
适合依赖路由名称的场景,同样能自动适配部署路径。
总的来说,最靠谱的还是前两种方法,利用ASP.NET服务器端的辅助方法来处理路径,完全避免手动拼接的错误,不管怎么部署都能稳稳的。
内容来源于stack exchange

