MVC项目在IIS6上部署的几种思路
微软在vista和win2008下集成了IIS7,与IIS6相比,有重大升级,看IIS7的十大改进,http://blogs.msdn.com/cqwang/archive/2007/09/10/iis7.aspx
而在2008年发布的MVC正式版中支持IIS6/IIS7。不过对iis6支持的有点变态。
下面是邀月的一次正式部署MVC项目到IIS6的过程。为了项目接近实用,在演示项目中引用了一个Web service(主要根据地区邮编或地区名称来获取天气预报)http://www.webservicex.net/WeatherForecast.asmx?WSDL
第一步: 正式创建一MVC项目 ,本项目沿用上个示例,名称为MvcAppDemoFck。项目结构如下图:
第二步:添加web引用 ,这个与普通的web service没什么不同,输入地址 http://www.webservicex.net/WeatherForecast.asmx?WSDL
其他默认即可。如上图。
第三步:在Controller下添加新的Controller,名称为WeatherController ,添加代码如下:
public ActionResult Index()
{
return View();
}
public ActionResult GetWeather(string Id)
{
//if (string.IsNullOrEmpty(Id)) { return null; }
if (string.IsNullOrEmpty(Id)) { Id = "New York"; }
StringBuilder sb = new StringBuilder();
WeatherForecast wf = new WeatherForecast();
WeatherForecasts wfs = wf.GetWeatherByPlaceName(Id);
WeatherData[] wd = wfs.Details;
sb.AppendFormat("<B>Weather Forecast for {0}</B><br /><br />", wfs.PlaceName);
foreach (WeatherData d in wd)
{
if (!string.IsNullOrEmpty(d.WeatherImage))
{
sb.AppendFormat("<img src="/" mce_src="/""{0}/" >", d.WeatherImage);
sb.AppendFormat(" {0}", d.Day);
sb.AppendFormat(", High {0}F", d.MaxTemperatureF);
sb.AppendFormat(", Low {0}F<br />", d.MinTemperatureF);
}
}
Response.Write(sb.ToString());
return null;
}
并在 "public ActionResult Index{"处右键 Add View,新增一个View名称为GetWeather.aspx,即默认名称
第四步:修改默认的MainContent的内容部分为:
<mce:script type="text/javascript" src="<%= Url.Content(" mce_src="<%= Url.Content("~/Content/Js/jquery-1.3.2.min.js")%><!--
">
// --></mce:script>
<!--<mce:script type="text/javascript" src="<%= Url.Content(" mce_src="<%= Url.Content("~/Scripts/jquery-1.3.2.min.js")%><!--
" >
// --></mce:script>-->
<!--<mce:script type="text/javascript" src="/Scripts/jquery-1.3.2.min.js" mce_src="Scripts/jquery-1.3.2.min.js"></mce:script>-->
<!--<mce:script type="text/javascript" src="http://localhost:50002/Scripts/jquery-1.3.2.min.js" mce_src="http://localhost:50002/Scripts/jquery-1.3.2.min.js"></mce:script>-->
<!-- <mce:script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" mce_src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></mce:script>-->
<mce:script type="text/javascript"><!--
function getWeather() {
//var URl = '<%= Url.Content("/Weather/GetWeather/")%>';
var URL = "/Weather/GetWeather/" + $("#Location").val();
$.get(URL, function(data) {
$("#Result").html(data);
});
}
// --></mce:script>
<mce:script type="text/javascript"><!--
function getWeatherJSON() {
var URL = "/Weather/GetJsonWeather/";
$.getJSON(URL, { Location: $("#Location").val() }, function(data) {
var result = "";
$.each(data, function(index, d) {
if (d.WeatherImage != '') {
result += '<br /><img src="' + d.WeatherImage + '" mce_src="' + d.WeatherImage + '" > ';
result += d.Day;
result += ', High ' + d.MaxTemperatureF + 'F';
result += ', Low ' + d.MinTemperatureF + 'F';
}
});
$("#Result").html(result);
});
}
// --></mce:script>
<div>
<input type="text" id="Location" style="width: 325px" value="New York" />
<input type="button" id="btnSubmit" value="Get Weather" onclick="javascript:getWeather();" />
<input type="button" id="btnSubmitJson" value="Get Weather JSON" onclick="javascript:getWeatherJSON();" />
<br />
<br />
<div id="Result">
</div>
</div>
<div>
<ul>
<li>
<%= Html.ActionLink("WeatherJQuery", "GetWeather", "Weather")%>
</li>
<li>
<%= Html.ActionLink("WeatherJSON", "GetJsonWeather", "Weather")%>
</li>
</ul>
</div>
注意,这里一个端口号为50002,是iis的端口,而不是vs2008内置的端口,
看图:
下面开始正式的部署:如果此时在浏览器中输入http://localhost:50002/,会提示404错误。出错原因如下:
This happens because IIS 6 only invokes ASP.NET when it sees a “filename extension” in the URL that’s mapped to aspnet_isapi.dll (which is a C/C++ ISAPI filter responsible for invoking ASP.NET). Since routing is a .NET IHttpModule called UrlRoutingModule , it doesn’t get invoked unless ASP.NET itself gets invoked, which only happens when aspnet_isapi.dll gets invoked, which only happens when there’s a .aspx in the URL. So, no .aspx , no UrlRoutingModule , hence the 404.
大意是:因为IIS6只对aspx文件才调用 aspnet_isapi.dll进行处理,而在默认的MVC设置里是无路径的,所以会出现404。有人说,为什么vs2008内建的浏览器会支持呢?那正是因为调用了aspnet_isapi.dll 的缘故。所以我们在IIS6中只要通知iis,需要对该网站的地址url进行解析处理即可。
第一种尝试:Use a wildcard mapping for aspnet_isapi.dll,为aspnet_isapi.dll启用通配符映射。 这个翻译很别扭。^_^
iis-网站-属性-主目录-配置-映射-插入--(注意不是添加扩展名),可执行文件名一般为C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll。 去掉"确认文件是否存在"的勾,即不选。
OK! 再打开浏览器, http://localhost:50002/,似乎一切都很美好!!但这就等于告诉IIS,每一次的请求,都要通过aspnet_isapi.dll,而无论是否是aspx文件。这不是我们想要的。
第二种尝试:Put .aspx in all your route entries’ URL patterns。在URL格式中设置.aspx路由入口 ,即
在Global.asax.cs文件的RegisterRoutes方法中修改默认的路由规则为
routes.MapRoute("Default", "{controller}.aspx
/{action}/{id}", new { controller = "Home", action = "Index", id = "" });
这样一来,这样相当于欺骗iis6,告诉IIS6 ,我是aspx文件,你处理一下我吧。
这样处理的结果就是地址栏变成了 http://localhost:50002/Home.aspx/About或http://localhost:50002/Weather.aspx,但浏览一朷正常。就是地址太恶心了些。
第三种尝试:Use a custom filename extension in all your URL patterns,在所有的url规则中添加一个可定制的扩展名如mvc等。
与第一种非常类似。iis-网站-属性-主目录-配置-映射-添加--(注意不是插入),可执行文件名一般为C:/WINDOWS /Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll,扩展名为.mvc,动作限制为 “GET,HEAD,POST,DEBUG",同样 去掉"确认文件是否存在"的勾,即不选。因为这些文件并不是真正存在的,只不过为了欺骗可怜的IIS6。其实与第二种的效果类似,只是可以定制后缀名, 如".org"等。展示效果同第二种。
当然,第二种可以用.mvc。同时注意,第二种与第三种必须添加默认Root路径的路由规则,否则会找不到默认主页
routes.MapRoute("Root", "", new { controller = "Home", action = "Index", id = "" });
出错信息如下:
如果vs2008中启动调试也会在这句出错。
第四种尝试:利用第三方URL组件。
1、发现原来用的ISAPI_Rewrite不能在MVC环境正常使用。可能版本过低,是1.3Full。
2、老赵推荐使用IIRF( Ionics Isapi Rewrite Filter)开源,地址为:http://iirf.codeplex.com/
官方提供了MVC的匹配规则:http://cheeso.members.winisp.net/Iirf20Help/html/1ccbf1ec-0984-49d9-9ab0-63eab3ff9c63.htm
# IsapiRewrite4.ini # # ## Turn off logging #RewriteLog c:/temp/iirfLog.out #RewriteLogLevel 3 IterationLimit 1 RewriteEngine ON StatusUrl /iirfStatus RewriteRule ^/Default/.aspx /Home.mvc [I,L] RewriteRule ^/$ /Home.mvc [I,L] RewriteRule ^/([/w]+)$ /$1.mvc [I,L] RewriteRule ^/(?!Content)([/w]*)/(.*) /$1.mvc/$2 [I,L]
按照官方文档,完成配置,需要在iis中设置,而且需要IsapiRewrite4.ini和IsapiRewrite4.dll在同一个目录下,还需要重启iis,希望你看到这些不要崩溃!
安装见官方地址http://cheeso.members.winisp.net/Iirf20Help/html/c76efb95-05ba-4383-8022-7eff3e1174d0.htm
配置http://cheeso.members.winisp.net/Iirf20Help/frames.htm
性能如何,没有测试。
配置成功,截图如下:
第五种尝试:Upgrade to Windows Server 2008 and IIS 7。 据说IIS7对MVC提供了完美的支持。财力短缺,在此略去。
至此,一次mvc项目的部署告一段落。 希望有人能提供更好的方案。
结束语: MVC最好的支持应该是IIS7(vista/win2008)或者是IIS7.5(Win7/win2008r2),这是产品的生命周期使然。另外在部署过程中js的路径比较特殊,除了使用特殊的
Url.Content("~/Content/Js/jquery-1.3.2.min.js")
外,最好将js文件放置在Content/js下。而不是默认的Scripts文件。其中出过几次错,特别是在第三方URL组件时更易错。
本文参考的文章:
1、ASP.NET MVC on IIS 6 Walkthrough
(Phil Haack)
2、Deploying ASP.NET MVC to IIS 6
(Steve Sanderson)
3、JQuery AJAX with ASP.NET MVC
(
Farooq Kaiser)CodeProject
4、ASP.NET MVC Framework体验(5):路径选择(URL Routing)
(TerryLee)
5、重提URL Rewrite(2):使用已有组件进行URL Rewrite
(JeffreyZhao)
6、Asp.net MVC项目的部署(一):IIS以及Asp.net与IIS相关的部分
(xuefly)
7、Using ASP.NET MVC with Different Versions of IIS
(MVC官网)
8、ASP.NET MVC URL Routing 学习
(QLeelulu)
9、ASP.NET MVC 入门3、Routing
(QLeelulu)
助人等于自助! [email protected]