首页 新闻 会员 周边

MVC3部署IIS静态资源引用路径问题。

0
悬赏园豆:10 [已解决问题] 解决于 2012-09-20 08:43

做了一个miniui+MVC的项目,在本机上调试是没有问题的,但是部署到IIS上之后发现所有的CSS,和JS引用都失效。

后来用Chrome跟踪调试发现原来是引用路径找不到了。

比如一个CSS文件引用../../Content/Style/demo.css,在本机调试路径是:

这样是没有问题的,但是部署到IIS上引用就成了
这样是访问不了的,后来调试发现正确的引用地址应该是
http://172.20.168.56:8080/QSMC.EIT/Content/Style/demo.css
 
也就是,部署上IIS后对静态资源的引用少了网站名(我们一个Server上挂的有多个网站)。
 
后来,在网上找了一些资料,发现有很多人都出现过这种问题,解决方案就是把引用文件的路径改成相对应于网站根目录的路径。就是把../../Content/Style/demo.css改成
<%= Url.Content("~/Content/scripts/miniui/themes/blue/skin.css")%>,这样就行了。
好吧,我费了九牛二虎之力吧所有的引用路径都坐了替换,这样图片,js 和css的引用路径是解决了,但是另一个问题是js文件中的Ajax请求路径也出现了这样的问题,由于我的js文件和aspx文件是分开放的,ajax中根本不识别
<%= Url.Content("“)这样的语法。
比如一个一个js请求我是这样写的正确的/Dispatch/SaveDispatchHeader,在本机调试是http://localhost:13321/Dispatch/SaveDispatchHeader,没有任何问题,
想要的结果是http://172.20.168.56:8080/qsmc.eit/Dispatch/SaveDispatchHeader。
这样的话,所有的ajax请求都会失效。。。。。。
不知道有没有人遇到类似情况,是怎么解决的。
Gamain的主页 Gamain | 菜鸟二级 | 园豆:357
提问于:2012-09-17 16:32
< >
分享
最佳答案
0

我们先说第一个问题,你使用了 ../../ 的相对路径来引用是正确的,我只能通过一个例子来给你讲解:

1,新建一个 Asp.Net Mvc 3Web 应用程序项目,名称为:MvcApplication1;

2,在项目 MvcApplication1 上点击鼠标右键,选择“发布”;

3,在“发布 Web”对话框上将“发布方法”设置为“文件系统”,在“目标位置”中输入:“D:\QSMC\MvcApplication1”;

4,点击“发布”;

5,打开IIS管理器;

6,如果“网站”节点下不包含8080端口的网站,则点击“添加网站”,端口设置为 8080,同时物理路径设置为“QSMC”;

7,在端口为8080的网站上点击鼠标右键,选择“添加应用程序”,别名输入:MvcApplication1,物理路径设置为:D:\QSMC\MvcApplication1;

 

PS:关于应用程序池的设置不在本示例中说明。

 

收获园豆:10
Launcher | 高人七级 |园豆:45045 | 2012-09-17 16:48

恩,我按照你说的方法做了,可是还是不行啊,请求地址还是少了网站名

生成的请求地址是:

Request URL:
而实际正确的地址是:
Request URL:
http://172.20.168.56:8080/QSMC.EIT/Menu/QueryMuneInfo?_=1347873300167

这一点好像和传统的sap.net网站完全不一样啊

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 17:17

@Gamain: 你说的不行这个应该是你的第二个问题吧,你可以把你的调用代码贴出来。

Launcher | 园豆:45045 (高人七级) | 2012-09-17 17:19

@Launcher:

其实第一个问题和第二个问题都是一样的

比如我有一段ajax请求的代码

$.ajax({
url: "../../Dispatch/Confirm",
data: { DisID: DisID, sidata: mini.encode(arrsi), truckerdata: mini.encode(arrtrucker) },
type: "post",
success: function (text) {
//grid.reload();
mini.alert("保存成功,现在可以打印派车单!");
//console.log(grid.getColumn(5));
grid.hideColumn(grid.getColumn(5));
grid2.hideColumn(grid2.getColumn(4));
var result = mini.decode(text);
// console.log(result.resultData);

mini.get("txtTOTALPALLETS").setValue(result.resultData["Su_PLTNO"]);
mini.get("txtTOTALCARTONS").setValue(result.resultData["Su_CTNNO"]);
mini.get("txtTOTALHPALLETS").setValue(result.resultData["Su_GTSD"]);
mini.get("txtTOTALSPALLETS").setValue(result.resultData["Su_XTSD"]);
mini.get("txtTOTALPARTPALLETS").setValue(result.resultData["Su_PSTSD"]);

IfConfirm = true;
},
error: function (jqXHR, textStatus, errorThrown) {
mini.alert(jqXHR.responseText);
return;
}
});

 

这样写在本机vs调试的时候生成的请求路径是:http://localhost:12344/Dispatch/Confirm.根据MVC的路由选择,这样是完全没有问题的。

但是当我把网站部署到iis后,这段ajax请求的地址是:

http://http://172.20.168.56:8080/Dispatch/Confirm。

很显然这个是不正确的,

正确的地址应该是http://http://172.20.168.56:8080/QSMC.EIT/Dispatch/Confirm。

即,默认生成的地址没有网站名,所以请求失败,不知道我说的你能不能明白。

其他的静态资源,比如图片,css,js等都有这样的问题。

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 17:28

@Gamain:  你可以这样截个图看看:

Launcher | 园豆:45045 (高人七级) | 2012-09-17 17:36

@Launcher: 

如图,是我部署的网站。

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 17:42

@Gamain: 你在VS调试的时候这样设置:

Launcher | 园豆:45045 (高人七级) | 2012-09-17 17:47

@Gamain: 

其他网站都是没有问题的,当然,其他网站都是不MVC程序。

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 17:48

@Gamain: 其它网站也有这样的代码:

$.ajax({
url: "../../Dispatch/Confirm",

吗?

Launcher | 园豆:45045 (高人七级) | 2012-09-17 17:49

@Launcher: 

我这样设置了,可是还是不行啊。

网上找了一下,也有人问道同样的问题,但是不是太多,也没有人给出很好的解决方案,不知道这个是不是属于个别现象啊。

有那么多人都在用mvc,对于这个问题都是如何处理的呢?

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 17:58

@Gamain: 我的意思是你这样设置后,通过调试的方式,生成的URL是否为正确的。换句话说,你可以在浏览器中查看一下原文件,也就是输出到你的客户端后的页面代码是怎样的。

Launcher | 园豆:45045 (高人七级) | 2012-09-17 17:59

@Launcher: 

恩,我就是通过chrome跟踪调试的,生成的url还是少了网站名

比如正确的应该是:

http://http://172.20.168.56:8080/QSMC.EIT/Dispatch/Confirm。

但是实际生成的却是:

http://http://172.20.168.56:8080/Dispatch/Confirm。

参考其他人的方法,定义一个httpmodel ,然后拦截,重写所有的请求,我也这样做了,写了一个httpmodel 类,能够拦截到所有的请求,但是悲剧的是自定义的httpmodel 在iis7.5下不起左右。

。。。。。。%>_<%

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 18:08

@Gamain: 

$.ajax({
url: "../../Dispatch/Confirm",

吗?

这段代码所在页面的路径是什么?

Launcher | 园豆:45045 (高人七级) | 2012-09-17 18:14

@Launcher: 

Dispatch:controller,

Confirm:action,

这个可以导航到DispatchController.cs中的Confirm方法。

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 18:18

@Launcher: 

不好意思,刚才的截图和你说的不一样

这段js实际在ConfirmDispatch.js这个文件中,被views中的ConfirmDispatch.aspx所应用。

项目结构如下

Gamain | 园豆:357 (菜鸟二级) | 2012-09-17 18:24

@Gamain: QSMC.EIT 你改成 QSMCEIT,也就是不要在路径中包含“.”。

首先,ConfirmDispatch.aspx 的url为:

http://localhost:8080/QSMCEIT/ConfirmDispatch/ConfirmDispatch.aspx

假设 ConfirmDispatch.aspx 中有段js如下:

$.ajax({url: "../../Dispatch/Confirm"})  // 此路径表达式,会先回退到顶级路径,然后再追加相对路径。

那么请求的地址为:http://localhost:8080/Dispatch/Confirm 

如果js代码如下:

$.ajax({url: "Dispatch/Confirm"})

那么请求的地址为:http://localhost:8080/QSMCEIT/Dispatch/Confirm

Launcher | 园豆:45045 (高人七级) | 2012-09-18 09:21

@Launcher:

还是不行啊,好吧,我放弃了。

我还是一点点的手动修改拼接路径吧。

悲剧!! 

Gamain | 园豆:357 (菜鸟二级) | 2012-09-18 09:55

@Gamain: 

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    主页
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <div id="Loading">
        Loading</div>
    <%using (Ajax.BeginForm("AjaxGetJSON", new AjaxOptions { LoadingElementId = "Loading", UpdateTargetId = "ajaxResult", InsertionMode = InsertionMode.InsertBefore }))
      { %>
    <p>
        <%=Html.TextBox("p.FirstName", "a", new { style = "width:250px," })%></p>
    <p>
        <%=Html.TextBox("p.LastName", "b", new { style = "width:250px," })%></p>
    <input type="submit" value="Add" style="width: 50px;" />
    <%} %>
    Action Link:
    <%=Ajax.ActionLink("GetByLink","AjaxGetString",new AjaxOptions{LoadingElementId="Loading",UpdateTargetId="ajaxResult",InsertionMode=InsertionMode.InsertBefore}) %>
    Ajax by Jquery:
    <input type="button" value="GetbyJquery" onclick="GetByJquery()" />
    <div id="ajaxResult">
    </div>
    <div id="JqueryResult">
    </div>
    <script type="text/javascript">
        function GetByJquery() {
            $.ajax({
                type: "POST",
                url: "Dispatch/Confirm",
                data: "name=Jack&location=Wang",
                success: function (msg) { $("#JqueryResult").append(msg); }
            });
        }
    </script>
    <h2>
        <%: ViewBag.Message %></h2>
    <p>
        若要了解有关 ASP.NET MVC 的更多信息,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC 网站">http://asp.net/mvc</a>。
    </p>
</asp:Content>

你可以先将 ConfirmDispatch.aspx中代码替换成上面的内容,然后测试发出的POST请求的地址是否正确。由于使用了js,所有路径的解析由客户端完成。

Launcher | 园豆:45045 (高人七级) | 2012-09-18 10:08

@Launcher: 

虽然您说的很详细,但是还没有解决我的问题。

最近又有几个同学遇到类型的问题,不知道您有没有好的解决方案呢?

Gamain | 园豆:357 (菜鸟二级) | 2013-09-10 18:12

@Gamain: 有,你把项目发给我,或者你写个简单的示例项目,然后我帮你改,再写个详细的文档给你解释为什么要这么做。

Launcher | 园豆:45045 (高人七级) | 2013-09-11 09:18

@Launcher: 

http://pan.baidu.com/share/link?shareid=1064585705&uk=218142471

这个是我写的一个非常简单的示例代码。

您可以测试一下,在VS中调试的时候没有问题,但是部署到IIS上就会有问题。

Gamain | 园豆:357 (菜鸟二级) | 2013-09-11 10:38

@Gamain: 你得告诉我点击哪里会出错。

Launcher | 园豆:45045 (高人七级) | 2013-09-11 10:45

@Launcher: 

我又重新上传了文件:

http://pan.baidu.com/share/link?shareid=1226412753&uk=218142471

如果正确的话,首页会显示如下:

如果错误(部署到IIS)的话,首页显示信息如下:

Gamain | 园豆:357 (菜鸟二级) | 2013-09-11 11:04

@Gamain: 直接部署到 IIS 的话,的确出现你提示的错误,把 jsviews\home\index.js 中修改为这样:

url: "../home/ReturnObject" ,就没有错误了。

Launcher | 园豆:45045 (高人七级) | 2013-09-11 11:25

@Gamain: 

我这样试过了,的确是不可以的。

请问您改成 url: "../home/ReturnObject" 以后.ajax 请求的URL地址是多少呢?能包含您的网站名(比如www.yoursite.com/[虚拟目录名])吗?

能把您测试的这个URL发出来看看吗?

Gamain | 园豆:357 (菜鸟二级) | 2013-09-11 12:07

@Launcher: 

比如这个页面我本地的请求地址是:

Request URL:http://localhost:1617/home/ReturnObject

部署到IIS上的请求地址是

Request URL:http://172.20.168.101:8080/home/ReturnObject

但是,很显然这个是不正确的,正确的URL请求应该如下

Request URL:http://172.20.168.101:8080/mytestsite/home/ReturnObject

少了一个虚拟目录名

Gamain | 园豆:357 (菜鸟二级) | 2013-09-11 12:11

@Gamain: 那你把 js 改成这样: url: document.URL + "/home/ReturnObject",

Launcher | 园豆:45045 (高人七级) | 2013-09-11 14:01

@Launcher: 

哦,如果是根据documen.URL来拼接的话和我说的定义全局变量基本上没有什么差别。

毕竟documen.URL取的是当前页面的完整URL,还要判断当前环境是调试环境还是IIS正式环境然后再截取出虚拟目录进行拼接。

我想到的还有一个方法就是重新httpmodule,判断当前是调试环境还是正式环境,然后重定向URL。其实这几种解决方案原理都差不多。

我不明白的是问什么MVC项目会出现这种问题,而传统的asp.net项目就没有这个问题。这点是关键。

Gamain | 园豆:357 (菜鸟二级) | 2013-09-11 16:11

@Gamain: 你不明白,我也不明白。我也不会写js,document.URL 是我从网上找的如何获取当前的页面的路径。

你能不能别把那个 js 设置一刷新就调用,能否做个按钮,让我点了按钮后,它才局部刷新出结果?这样有助于我观察问题。另外,如果你别引用 js,而是把 js 直接写入到 home\Index.cshtml 中,你看看结果如何。

Launcher | 园豆:45045 (高人七级) | 2013-09-11 16:17

@Gamain: MVC是基于路由的,如果加虚拟目录的话,路由肯定会出错。

第一种方式:你可以直接统一改路由试试.

另外一种:就是你说的全局的js变量,这个一般适合页面js中使用。如果参合到mvc的HtmlHelper方法去写的话,看着会不自然,是吧。

所以第三种方式,如果你采用类似Nginx反向代理的话,你部署应用程序时就可以不加多层的虚拟目录,直接在Nginx上去处理就可以满足你的要求。

@Launcher:哪里都看得到你,呵呵。还记得之前咱们讨论过Cache吗?呵呵.

Tim Lee | 园豆:350 (菜鸟二级) | 2015-01-30 10:10

@Tim Lee: 翻了下才记起来。

Launcher | 园豆:45045 (高人七级) | 2015-01-30 10:36
其他回答(4)
0

您好,请问您那路径问题是怎么解决的?我这边也碰到同样的问题。发布为网站没问题,但发布到虚拟目录就出问题了

zhouhappy | 园豆:202 (菜鸟二级) | 2012-12-11 16:10

如下,采用的是比较笨的方法,不知道你有没有好的解决方案。

支持(0) 反对(0) Gamain | 园豆:357 (菜鸟二级) | 2013-09-10 18:01
0

不知道博主是怎么解决这个问题。我也碰到了这个问题,我的想法是添加ajax全局事件,即,在ajax请求前对请求对象的url进行操作:在原url前添加虚拟目录名。

i柚 | 园豆:202 (菜鸟二级) | 2013-01-10 13:02

如下,采用的是比较笨的方法,不知道你有没有好的解决方案。

支持(0) 反对(0) Gamain | 园豆:357 (菜鸟二级) | 2013-09-10 18:02
0

$.ajax({
url: "/Dispatch/Confirm", 

这样写就可以了 

Gross | 园豆:206 (菜鸟二级) | 2013-04-22 10:56
0

请问您最终是怎么解决的,我的也没解决急啊?

aiaito | 园豆:202 (菜鸟二级) | 2013-09-10 14:29

没有什么好方法。

最好我采取了比较笨的方法,添加一个Global.js文件。定义一个全局的applicationPath变量。然后再其他的js文件中都引用这个变量拼接路径。

在部署到iis的时候再修改这个变量的值就可以了。

支持(0) 反对(0) Gamain | 园豆:357 (菜鸟二级) | 2013-09-10 14:44

@Gamain: 

比如ajax 的url是 "Home/Index"的话,我就这样写:

$.ajax{url:applicationPath+"Home/Index"};

在本地调试的时候设置 var  applicationPaht="";

在配置到IIS上的时候: var applicationPaht="www.yoursite.com/";

由于applicationPaht是一个全局的变量,所有只要修改一个地方就可以。

只是没有页面都要首先引用Globa.js这个文件。

支持(0) 反对(0) Gamain | 园豆:357 (菜鸟二级) | 2013-09-10 14:49

@Gamain: 我是初学者 我没那样干过 麻烦您能把global.js代码和js拼接点吗案例复我一份吗 拜托了 愁死我了

支持(0) 反对(0) aiaito | 园豆:202 (菜鸟二级) | 2013-09-10 14:57

@Gamain: 嗯 我明白你的意思!谢谢

支持(0) 反对(0) aiaito | 园豆:202 (菜鸟二级) | 2013-09-10 15:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册