做了一个miniui+MVC的项目,在本机上调试是没有问题的,但是部署到IIS上之后发现所有的CSS,和JS引用都失效。
后来用Chrome跟踪调试发现原来是引用路径找不到了。
比如一个CSS文件引用../../Content/Style/demo.css,在本机调试路径是:
我们先说第一个问题,你使用了 ../../ 的相对路径来引用是正确的,我只能通过一个例子来给你讲解:
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:关于应用程序池的设置不在本示例中说明。
恩,我按照你说的方法做了,可是还是不行啊,请求地址还是少了网站名:
生成的请求地址是:
这一点好像和传统的sap.net网站完全不一样啊
@Gamain: 你说的不行这个应该是你的第二个问题吧,你可以把你的调用代码贴出来。
@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: 你可以这样截个图看看:
@Launcher:
如图,是我部署的网站。
@Gamain: 你在VS调试的时候这样设置:
@Gamain:
其他网站都是没有问题的,当然,其他网站都是不MVC程序。
@Gamain: 其它网站也有这样的代码:
$.ajax({
url: "../../Dispatch/Confirm",
吗?
@Launcher:
我这样设置了,可是还是不行啊。
网上找了一下,也有人问道同样的问题,但是不是太多,也没有人给出很好的解决方案,不知道这个是不是属于个别现象啊。
有那么多人都在用mvc,对于这个问题都是如何处理的呢?
@Gamain: 我的意思是你这样设置后,通过调试的方式,生成的URL是否为正确的。换句话说,你可以在浏览器中查看一下原文件,也就是输出到你的客户端后的页面代码是怎样的。
@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:
$.ajax({
url: "../../Dispatch/Confirm",
吗?
这段代码所在页面的路径是什么?
@Launcher:
Dispatch:controller,
Confirm:action,
这个可以导航到DispatchController.cs中的Confirm方法。
@Launcher:
不好意思,刚才的截图和你说的不一样
这段js实际在ConfirmDispatch.js这个文件中,被views中的ConfirmDispatch.aspx所应用。
项目结构如下
@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"})
@Launcher:
还是不行啊,好吧,我放弃了。
我还是一点点的手动修改拼接路径吧。
悲剧!!
@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:
虽然您说的很详细,但是还没有解决我的问题。
最近又有几个同学遇到类型的问题,不知道您有没有好的解决方案呢?
@Gamain: 有,你把项目发给我,或者你写个简单的示例项目,然后我帮你改,再写个详细的文档给你解释为什么要这么做。
@Launcher:
http://pan.baidu.com/share/link?shareid=1064585705&uk=218142471
这个是我写的一个非常简单的示例代码。
您可以测试一下,在VS中调试的时候没有问题,但是部署到IIS上就会有问题。
@Gamain: 你得告诉我点击哪里会出错。
@Launcher:
我又重新上传了文件:
http://pan.baidu.com/share/link?shareid=1226412753&uk=218142471
如果正确的话,首页会显示如下:
如果错误(部署到IIS)的话,首页显示信息如下:
@Gamain: 直接部署到 IIS 的话,的确出现你提示的错误,把 jsviews\home\index.js 中修改为这样:
url: "../home/ReturnObject" ,就没有错误了。
@Gamain:
我这样试过了,的确是不可以的。
请问您改成 url: "../home/ReturnObject" 以后.ajax 请求的URL地址是多少呢?能包含您的网站名(比如www.yoursite.com/[虚拟目录名])吗?
能把您测试的这个URL发出来看看吗?
@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: 那你把 js 改成这样: url: document.URL + "/home/ReturnObject",
@Launcher:
哦,如果是根据documen.URL来拼接的话和我说的定义全局变量基本上没有什么差别。
毕竟documen.URL取的是当前页面的完整URL,还要判断当前环境是调试环境还是IIS正式环境然后再截取出虚拟目录进行拼接。
我想到的还有一个方法就是重新httpmodule,判断当前是调试环境还是正式环境,然后重定向URL。其实这几种解决方案原理都差不多。
我不明白的是问什么MVC项目会出现这种问题,而传统的asp.net项目就没有这个问题。这点是关键。
@Gamain: 你不明白,我也不明白。我也不会写js,document.URL 是我从网上找的如何获取当前的页面的路径。
你能不能别把那个 js 设置一刷新就调用,能否做个按钮,让我点了按钮后,它才局部刷新出结果?这样有助于我观察问题。另外,如果你别引用 js,而是把 js 直接写入到 home\Index.cshtml 中,你看看结果如何。
@Gamain: MVC是基于路由的,如果加虚拟目录的话,路由肯定会出错。
第一种方式:你可以直接统一改路由试试.
另外一种:就是你说的全局的js变量,这个一般适合页面js中使用。如果参合到mvc的HtmlHelper方法去写的话,看着会不自然,是吧。
所以第三种方式,如果你采用类似Nginx反向代理的话,你部署应用程序时就可以不加多层的虚拟目录,直接在Nginx上去处理就可以满足你的要求。
@Launcher:哪里都看得到你,呵呵。还记得之前咱们讨论过Cache吗?呵呵.
@Tim Lee: 翻了下才记起来。
您好,请问您那路径问题是怎么解决的?我这边也碰到同样的问题。发布为网站没问题,但发布到虚拟目录就出问题了
如下,采用的是比较笨的方法,不知道你有没有好的解决方案。
不知道博主是怎么解决这个问题。我也碰到了这个问题,我的想法是添加ajax全局事件,即,在ajax请求前对请求对象的url进行操作:在原url前添加虚拟目录名。
如下,采用的是比较笨的方法,不知道你有没有好的解决方案。
$.ajax({
url: "/Dispatch/Confirm",
这样写就可以了
请问您最终是怎么解决的,我的也没解决急啊?
没有什么好方法。
最好我采取了比较笨的方法,添加一个Global.js文件。定义一个全局的applicationPath变量。然后再其他的js文件中都引用这个变量拼接路径。
在部署到iis的时候再修改这个变量的值就可以了。
@Gamain:
比如ajax 的url是 "Home/Index"的话,我就这样写:
$.ajax{url:applicationPath+"Home/Index"};
在本地调试的时候设置 var applicationPaht="";
在配置到IIS上的时候: var applicationPaht="www.yoursite.com/";
由于applicationPaht是一个全局的变量,所有只要修改一个地方就可以。
只是没有页面都要首先引用Globa.js这个文件。
@Gamain: 我是初学者 我没那样干过 麻烦您能把global.js代码和js拼接点吗案例复我一份吗 拜托了 愁死我了
@Gamain: 嗯 我明白你的意思!谢谢