[转载]如何在VS2008中使自定义模板实现与项目默认模板同样效果

mikel阅读(818)

[转载]如何在VS2008中使自定义模板实现与项目默认模板同样效果 – Happy Miao – 博客园.

最近一直想做一个基于Micro Framework 的扩展模板,但是网上制作模板的方式(Export的方式google一下就可以找到),只能将自定义模板加到My Templates 下面,但这样本人认为显得是不是很不专业?要是能把自己的模板向SDK那样,增加到左边的Project Type树单独的一个分类,是不是很专业哦

要想制作VS2008的模板,我首先想到的就是VS2008SDK,于是我下载了VS2008SDK 它里面有一篇专门的关于如何增加Project Type的文章,并且含有一个写好的例子:IronPython,但是编译运行该实例后只能在SDK特有的“Microsoft Visual Studio 2008 under Experimental hive”上增加IronPython类型。但是如果用户没有安装VS2008SDK那么这种方法就会行不通。

经过对VS2008SDK的研究,并没有实现我想达到的效果,我一时陷入迷茫,该怎么办呢

既然要实现在VS2008中自定义模板,与其本身自带的项目一样的模板效果,那么一定要找到VS2008默认那些模板的位置,经过查找可以发现其存在于“C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates”

找到后我根据对该文件夹的分析,并与VS2008新建项目的层级进行对照,很自然的想到在C:”Program Files”Microsoft Visual Studio 9.0″Common7″IDE”ProjectTemplates”CSharp下创建一个文件夹暂时命名为Tuojie Framework。我想这样应该可以了吧,结果很令我失望

我在搜索了一些文件都没有发现什么线索后认为,一定是写在注册表了。但我在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\VSTemplate 下面只有UserFolderCacheFolder,这说明VS2008加载模板时一定是向Photoshop加载扩展程序时反射了指定文件夹。也就是说,我只要考到文件下,就可以了?我又一次陷入了困惑。

我继续在google 上搜索 Vs2008模板发现了VS2008中文版安装ASP.NET 3.5 Extensions模板遗失解决方法”的文章。知道了”C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe”还可以增加参数setup,我试着运行了一下,重起了VS2008,果真实现了我想要的效果,接下来我又用网上最常用的制作模板的方法制作了两个模板放到”C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Tuojie Framework\1033″下再次运行了“C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe /setup” 命令。完成了我要运行的效果,如图:

具体操作步骤:

1.在”C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\” 新建Tuojie Framework

2.根据“http://msdn.microsoft.com/zh-cn/library/xkh1wxd8.aspx”生成模板。

3.将模板拷贝到”C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Tuojie Framework\1033″

4.运行”C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe /setup” 命令

5.重启VS2008。

[转载]easyui 1.2.4 +aspnet mvc常见问题

mikel阅读(957)

[转载]easyui 1.2.4 +aspnet mvc常见问题 – philzhou – 博客园.

1. form提交回调函数无法触发,服务器端返回json被浏览器获取。

function saveUser() {
        $('#fm').form('submit', {
            url: url,
            onSubmit: function () {
                return $(this).form('validate');
            },
            success: function (result) {                
                var result = eval('(' + result + ')');
                if (result.success) {
                $('#dlg').dialog('close');      // close the dialog   
                $('#dg').datagrid('reload');    // reload the user data   
                } else {
                $.messager.show({
                title: 'Error',
                msg: result.msg
                });
                }                                
            }           
        });
      }

服务器端代码

public JsonResult AddCustomer(Customer cust)
        {
            string result = "";
            try
            {
                TestEntities data = new TestEntities();
                data.AddToCustomers(cust);
                data.SaveChanges();
                result = "成功";
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }

            return this.Json(new { success = true }, JsonRequestBehavior.AllowGet);
        }

该Action返回的Json直接被浏览器截获了,而没有触发前端ajax的回调函数。

解决办法:

return this.Json(new { success = true },"text/html", JsonRequestBehavior.AllowGet);

2.  easyui 1.2.4 bug 在一个允许多选的datagrid中删除了选中的某一行记录,并reload datagrid数据之后, 发现该已删除的记录任然存在于getSelections返回的row中,并且是第一行即如果getSelected会发现返回的时已被删除的那条记录。

解决方法:

重新加载数据前先清除 Selections

$('#test').datagrid("clearSelections");

[转载]初试jQuery EasyUI

mikel阅读(1003)

[转载]初试jQuery EasyUI – GWPBrian – 博客园.

想必关注JQuery的同学们对JQuery EasyUI已经有所耳闻了,目前已经更新到1.0.5版本,风格与EXTJS有点相似,可以很好的满足开发人员对UI的需求。

jQuery EasyUI

jQuery EasyUI是一组基于jQuery的UI插件集合,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂的JavaScript,也不需要对css样式 有深入的了解,开发者需要了解的只有一些简单的html标签。

jQuery EasyUI为我们提供了大多数UI控件的使用,如:accordion,combobox,menu,dialog,tabs,tree,window等等。

OK,下面就开始我们的初探之旅。

jQuery EasyUI—Accordion
手风琴效果,大家应该很熟悉。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Accordion</title>
<script src=”../jquery-1.4.2.min.js” type=”text/JavaScript></script>
<script src=”../jquery.easyui.min.js” type=”text/JavaScript></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript”></script>
</head>
<body>
<div style=”overflow:auto;width:600px;height:300px;padding:10px;border:1px solid #ccc;”>
<div id=”aa” class=”easyui-accordion” fit=”true” style=”width:300px;height:200px;”>
<div title=”Title1″ style=”overflow:auto;padding:10px;”>
<h3>Accordion1</h3>
</div>
<div title=”Title2″ style=”padding:10px;”>
<h3>Accordion2</h3>
</div>
<div title=”Title3″>
<h3>Accordion3</h3>
</div>
</div>
</div>
</body>
</html>

代码非常简单,只需要简单的html就可以实现。这里最重要的就是首先要引用jquery-1.4.2.min.js和jquery.easyui.min.js。

效果:

由于只是简单的html,所以我们可以通过js轻松的对Accordion进行操控,控制大小,位置等等。

jQuery EasyUI—DataGrid

从名字就可以知道这是个数据的绑定和显示控件。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>DataGrid</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript”>
$(
function() {
$(
#test).datagrid({
title:
jQuery EasyUI—DataGrid,
iconCls:
icon-save,
width:
500,
height:
350,
nowrap:
false,
striped:
true,
url:
../Data/datagrid_data.json,
sortName:
ID,
sortOrder:
desc,
idField:
ID,
frozenColumns: [[
{ field:
ck, checkbox: true },
{ title:
ID, field: ID, width: 80, sortable: true }
]],
columns: [[
{ title:
基本信息, colspan: 2 },
{ field:
opt, title: 操作, width: 100, align: center, rowspan: 2,
formatter:
function(value, rec) {
return <span style=”color:red”>编辑 删除</span>;
}
}
], [
{ field:
name, title: Name, width: 120 },
{ field:
addr, title: Address, width: 120, rowspan: 2, sortable: true }
]],
pagination:
true,
rownumbers:
true,
singleSelect:
false,
toolbar: [{
text:
添加,
iconCls:
icon-add,
handler:
function() {
alert(
添加数据)
}
},
, {
text:
保存,
iconCls:
icon-save,
handler:
function() {
alert(
保存数据)
}
}]
});
});

</script>
</head>
<body>
<table id=”test”></table>
</body>
</html>

这里我们从datagrid_data.json中获取数据,代码的编写风格同EXTIS十分相似。ExtJS开发实践

效果:

jQuery EasyUI—Dialog

网页窗体效果。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Dialog</title>

<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />

<script>
$(
function(){
$(
#dd).dialog({
toolbar:[{
text:
添加,
iconCls:
icon-add,
handler:
function(){
alert(
添加数据)
}
},
,{
text:
保存,
iconCls:
icon-save,
handler:
function(){
alert(
保存数据)
}
}],
buttons:[{
text:
提交,
iconCls:
icon-ok,
handler:
function(){
alert(
提交数据);
}
},{
text:
取消,
handler:
function(){
$(
#dd).dialog(取消);
}
}]
});
});

</script>
</head>
<body>
<div id=”dd” style=”padding:5px;width:400px;height:200px;”>
<p>jQuery EasyUI—Dialog</p>
</div>
</body>
</html>

效果:

jQuery EasyUI—Tabs

无论是网站还是管理软件,我们越来越多的使用Tabs,EasyUI自然也进行了支持。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Tabs</title>

<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />
</head>
<body>
<div id=”tt” class=”easyui-tabs” style=”width:500px;height:250px;”>
<div title=”Tab1″ style=”padding:20px;display:none;”>
<h1>Tab1 Content</h1>
</div>

<div title=”Tab5″ closable=”true” style=”padding:10px;display:none;”>
<div class=”easyui-tabs” fit=”true” plain=”true” style=”height:100px;width:300px;”>
<div title=”Title1″>Content 1</div>
<div title=”Title2″>Content 2</div>
<div title=”Title3″>Content 3</div>
</div>
</div>
</div>
</body>
</html>

效果:

jQuery EasyUI—Messager

信息提示控件,可以很好的进行数据的提示,推荐。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Messager</title>
<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />
<script>
function show1() {
$.messager.show({
title:
提示信息1,
msg:
信息1,
showType:
show
});
}
function show2() {
$.messager.show({
title:
提示信息2,
msg:
信息5分钟后消失.,
timeout:
5000,
showType:
slide
});
}
function show3() {
$.messager.show({
title:
渐进显示信息3,
msg:
渐进显示信息3,
timeout:
0,
showType:
fade
});
}
</script>
</head>
<body>
<h1>信息提示</h1>
<div>
<a href=”javascript:void(0)” onclick=”show1()”>显示</a> |
<a href=”#” onclick=”show2()”>滑动</a> |
<a href=”#” onclick=”show3()”>渐进显示</a> |
</div>
</body>
</html>

效果:

页面左下角信息提示

jQuery EasyUI—ValidateBox

数据验证控件,可以很好的对表单数据进行验证。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>ValidateBox</title>

<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />
</head>
<body>
<div>
<table>
<tr>
<td>姓名:</td>
<td><input class=”easyui-validatebox” required=”true” validType=”length[1,3]”></td>
</tr>
<tr>
<td>电子邮件:</td>
<td><input class=”easyui-validatebox” required=”true” validType=”email”></td>
</tr>
<tr>
<td>URL:</td>
<td><input class=”easyui-validatebox” required=”true” validType=”url”></td>
</tr>
<tr>
<td>说明:</td>
<td><textarea class=”easyui-validatebox” required=”true” style=”height:100px;”></textarea></td>
</tr>
</table>
</div>
</body>
</html>

不需要写任何函数,只需对要验证的控件required=”true” validType=”url”就可以。

效果:

jQuery EasyUI—LayOut

页面布局,可以将整个页面划分成几个区域。类似ExtJS中的Border布局。

基本代码:

代码

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>LayOut</title>
<script src=”../jquery-1.4.2.min.js” type=”text/javascript”></script>
<script src=”../jquery.easyui.min.js” type=”text/javascript”></script>

<link href=”../themes/default/easyui.css” rel=”stylesheet” type=”text/css” />
<link href=”../themes/icon.css” rel=”stylesheet” type=”text/css” />
</head>
<body>
<div class=”easyui-layout” style=”width:600px;height:400px;”>
<div region=”north” border=”false” style=”overflow:hidden;height:60px;background:#A4BED4;”>
<h2>Border布局</h2>
</div>
<div region=”south” split=”true” style=”height:50px;background:#efefef;”>
</div>
<div region=”east” icon=”icon-reload” title=”Menu2″ split=”true” style=”width:180px;”>
</div>
<div region=”west” split=”true” title=”Menu1″ style=”width:100px;”>
</div>
<div region=”center” title=”Main Form” style=”background:#eee;”>
</div>
</div>
</body>
</html>

效果:

jQuery EasyUI—换肤

jQuery EasyUI使用了统一的CSS样式,在修改方面也很是方便:

如图所示,对于每一个控件,都有专有的CSS。相应对其修改就可以,只需简单的了解CSS即可。

小结:jQuery EasyUI的体验就到这里,还有一些控件这里没有介绍,比如:combobox,splitbutton等等。

官方网站http://jquery-easyui.wikidot.com/start

下载地址:http://jquery-easyui.wikidot.com/download

本文代码:/Files/gaoweipeng/EasyUITest.rar

[转载]Visual Studio自带报表Report Viewer使用体验

mikel阅读(1040)

[转载]Visual Studio自带报表Report Viewer使用体验

概述

我的Visual Studio是2010,2005和2008也可以直接使用微软自带的报表工具开发报表。如果购买了SQL Server 2005企业版或者SQL Server 2008 R2,可以考虑使用Reporting Service,Reporting Service包括专门的报表工具,如Report Builder3.0,可以在微软网站上下载,使用Reporting Service开发需要专门的服务器存放报表文件和处理报表数据,其他应用程序仅是呈现报表而已。另外也可以考虑使用本地模式来开发和使用Report Viewer呈现报表,本地模式简单易用、方便灵活,报表寄存在应用程序中运行,本地模式可以视具体场景,使用Web和WinForm方式开发。

环境准备

Report Viewer是Visual Studio 2010自带的报表呈现控件,是微软自带的.Net Ajax控件之一,所以使用Report Viewer之前需要先添加ScriptManager和做好Web.config的相关配置,运行.Net Ajax控件需要预先安装.Net Ajax的插件,具体内容参考msdn的网站。在安装.Net Ajax插件之后,新建项目时可以选择新建Web Application,Web.config中的相关配置默认是支持.Net Ajax的。
.Net Ajax的插件下载地址请参考:
ASPAJAXExtSetup.msi:http://download.microsoft.com/download/5/4/6/5462bcbd-e738-45fa-84ca-fa02b0c4e1c2/ASPAJAXExtSetup.msi
ASPAJAXSourceCode.msi:http://download.microsoft.com/download/6/d/6/6d6c7c47-b9ff-4934-bb03-8a45b8418d35/ASPAJAXSourceCode.msi
AjaxControlToolkit:http://ajax.ASP.NET/downloads/default.aspx?tabid=47
or http://www.codeplex.com/AtlasControlToolkit/Release/ProjectReleases.aspx?ReleaseId=1425

制作第一个报表

创建好Web项目之后,选择添加新项,可以选择添加”报表”或者”报表向导”来生成报表文件,报表数据源可以选择数据源(使用DataTable)和业务对象(通过指定特定业务类特定方法获取List<>类型的数据对象列表)。
创建报表文件(.rdlc文件的创建过程)和通过Report Viewer呈现报表数据的详细过程请参考msdn:http://msdn.microsoft.com/zh-cn/library/ms251671.aspx

注意事项和工具

注意事项
1.报表文件需要存放在站点根目录中,放在文件夹中会报异常,在Reporting Service已存在类似的问题。
2.Report Viewer控件不支持URL路径中包含中文字符,如果路径存在中文字符,则会出现无法预知的JS错误。
3.VS2010传递参数时,不需要添加@字符,记得在某个版本的Reporting Service传递参数时需要添加@字符

非常有用的工具
1.打开报表文件之后,可以通过视图->报表数据菜单打开报表的相关信息窗口
2.工具栏中包含报表字样的工具栏对于格式报表非常有用。

示例代码:ReportDemo_ReportViewer.zip

作者:HorsonJin
出处:http://www.cnblogs.com/HorsonJin
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]XML to tree XML 树

mikel阅读(947)

[转载]XML to tree XML 树 – 柴哥 – 博客园.

前面发了一个 html to tree 再发一个 xml to tree

以下为代码:

/*
版权所有:版权所有(C) 2009
系统名称:树型控件
文件名称:xml2tree.js
作  者:DEVIN
完成日期:2009-12-22
压缩方式:jspacker
主    页:http://www.chaige.net
*/
var XML2Tree = function (ini) {
var $ = document, _this = this, $$ = 'documentElement';
this.getTitle = ini.getTitle || String;
this.click = ini.click || String;
this.box = ini.shell.big ? $.getElementById(ini.shell) : ini.shell;
this.edit = ini.edit ? true : false;
this.color = ini.color ? ini.color : '#v';
this.row = ini.row ? ini.row : '';
this.box.innerHTML = '
<p style="margin-left: 10px;"><img src="/load3.gif" alt="" /> loading...</p>
';
this.getValue = ini.getValue || String;
/* 异步下载Xml (chrome不能创建XMLDOC,使用Ajax构造) */
this.xml = !!$.all ? (new ActiveXObject('Microsoft.XMLDOM')) : (new XMLHttpRequest());
this.xml.onreadystatechange = function () {
if (_this.xml.readyState == 4) {
_this.box.innerHTML = '';
_this.addSub($.all ? _this.xml[$$] : _this.xml.responseXML[$$], _this.box)
}
}
if (!!$.all) {
this.xml.async = true; this.xml.load(ini.url)
}
else {
this.xml.open("GET", ini.url, true); this.xml.send(null)
};
}
/*
共享接口
*/
XML2Tree.prototype = {
folder: function (node) {
var UI = function (_) { return document.createElement(_) }
, caption = UI('DT'), shell = UI('DL'), body = UI('DD'), $ = XML2Tree.ini;
shell.appendChild(caption);
shell.appendChild(body);
var folderIco = this.selectIco($.folder, $.node, XML2Tree.hasChild(node));
caption.innerHTML = (this.edit ? '<label>' + this.expand(this.getValue.call(node)) + '</label>' : '')
+ this.getLineIco(node) + this.getHasIco(node)
+ folderIco + '<a href="javascript://"><span>'
+ this.getTitle.call(node) + '</span></a>';
caption.mapNode = node;
var co = this.color;
caption.onmouseover = function () {
this.style.backgroundColor = co;
}
caption.onmouseout = function () {
this.style.backgroundColor = '';
}
return { 'shell': shell, 'caption': caption };
},
addSub: function (node, shell) {
if (node == null) return;
var nodes = node.childNodes, _tree = this;
for (var i = 0; i &lt; nodes.length; i++) {
if (nodes[i].nodeType != 1) continue; /* for FF find textNode */
var _ = this.folder(nodes[i]);
shell.appendChild(_.shell);
_.caption.onclick = function (e) {
var $ = XML2Tree, childShell = $.next(this);
if (this.mapNode) {
var wrap = this.parentNode.getElementsByTagName('DD')[0];
if (XML2Tree.hasChild(this.mapNode)) {
_tree.addSub(this.mapNode, wrap);
$.toggle(this, true)
};
this.mapNode = null;
} else {
if (!childShell) return;
if (XML2Tree.hasChild(childShell)) {
var hide = childShell.style.display == 'none';
childShell.style.display = hide ? '' : 'none';
$.toggle(this, hide);
};
};
e = e || window.event;
var sE = e.srcElement || e.target;
if (sE.tagName.toUpperCase() == 'SPAN') {
var title = sE.innerHTML;
if (!XML2Tree.hasChild(childShell)) {
_tree.click.call(sE, title, false); /* 叶节点单击, this 重置为 span */
} else {
_tree.click.call(childShell, title, true); /* 文件夹节点单击, this 重置为 子节点的壳DD */
}
}
};
};
},
getLineIco: function (node) {
var icos = [], root = node.ownerDocument;
if (!root) return null;
node = node.parentNode;
while (node.parentNode != root) {
var $ = XML2Tree, img = this.selectIco($.ini.line, $.ini.empty, !!$.next(node));
icos = [img].concat(icos);
node = node.parentNode;
}
return icos.join('');
},
getHasIco: function (node) {
var last = !!XML2Tree.next(node), $ = XML2Tree.ini;
return XML2Tree.hasChild(node) ?
this.selectIco($.plus, $.plusBottom, last) :
this.selectIco($.join, $.joinBottom, last)
},
expand: function (i) {
var r = this.row, s = [];
for (var k = 0; k &lt; r.length; k++) {
var url = r[k][0].replace('{0}', i);
s.push('<a href="' + url + '">' + r[k][1] + '</a>' + (k == r.length - 1 ? '' : ' | '));
}
return s.join('');
},
selectIco: function (_1, _2, bool) {
return '<img src="' + (bool ? _1 : _2) + '" alt="" align="absimddle" />'
}
};
/*
静态接口
*/
XML2Tree.ini = {
root: 'ui/base.gif',
folder: 'ui/folder.gif',
folderOpen: 'ui/folderopen.gif',
node: 'ui/page.gif',
empty: 'ui/empty.gif',
line: 'ui/line.gif',
join: 'ui/join.gif',
joinBottom: 'ui/joinbottom.gif',
plus: 'ui/plus.gif',
plusBottom: 'ui/plusbottom.gif',
minus: 'ui/minus.gif',
minusBottom: 'ui/minusbottom.gif',
nlPlus: 'ui/nolines_plus.gif',
nlMinus: 'ui/nolines_minus.gif'
};
/* 图标预载 */
XML2Tree.prevLoad = function () {
for (var key in this.ini) {
var $ = new Image();
$.src = this.ini[key];
}
};
XML2Tree.next = function (node) {
var $ = node, _ = 'nextSibling';
for ($ = $[_]; $; $ = $[_]) {
if ($.nodeType == 1) { return $ }
};
return null;
};
XML2Tree.hasChild = function (node) {
var $ = node.childNodes;
for (var i = 0; i &lt; $.length; i++)
if ($[i].nodeType == 1) return true;
return false;
};
XML2Tree.toggle = function (node, isOpen) {
var imgs = node.getElementsByTagName('IMG')
, f = imgs.length - 1, $ = XML2Tree.ini;
imgs[f].src = isOpen ? $.folderOpen : $.folder;
if (this.next(node.parentNode)) {
imgs[f - 1].src = isOpen ? $.minus : $.plus;
} else {
imgs[f - 1].src = isOpen ? $.minusBottom : $.plusBottom;
}
};
/*
生成实例树
参数:
url: xml 地址
shell: 树容器
loading: 下载中的效果html
getTitle: 标题来源属性操作 this 重置为 xml node
chick: 节点或者叶节点的单击事件(可得到参数title,isFolder与重置后的this)
*/
XML2Tree.prevLoad();

下载地址

点我下载

~!~~~ 民工的命

原创代码,转载请联系 柴哥!!!

[转载]android之远程服务的调用

mikel阅读(960)

[转载]android之远程服务的调用 – jack.li – 博客园.

何为Android中的RPC模式?

相信有的读者还不是很理解,这里和大家做一个简单的介绍.RPC模式:Remote Procedure Call即远程进程调用.

Android操作系统中,各个组件运行在各自的进程中,它们相互之间是不能访问的.但是在程序之间不可避免的要传递一些对象、参数等,这就需要 实现进程间的相互通信.android采用了一种轻量级的实现方式—>RPC模式来完成进程之间的通信.通过定义接口语言(android interface definition language——AIDL)来完成进程之间相互访问的代码.例如:#1你需要在Activity中访问Service中的某一个方法,就可以采用这种方式来实现了.

AIDL语言是android的一种接口描述语言,编译器可以通过AIDL文件生成一段代码(注意:这段代码是自动生成的),通过预先定义的接口达到两个进程内部通信进程的目的.

详细的说下#1例子是什么个意思:如果需要在一个Activity中访问另一个Service中的某个对象,需要先将对象转化成AIDL可识别的参数(可能是多个参数),然后使用AIDL来传递这些参数,在消息的接收端,使用这些参数封装成自己需要的对象.

总的来说:android中的AIDL RPC是通过接口来实现的,类似Windows中的COM或者Corba,但它是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个Ibinder接口.

接下来我就一个具体的案例和大家讲讲RPC模式的具体实现步骤:

第一步:毫无疑问,是创建AIDL接口文件.第一个问题来了,怎样创建AIDL文件?

其实有这个疑问很正常,我上网搜了一些资料,问题解决.

在当前的Activity所在的Package右击,new一个file,取名BookInfo.aidl.该文件中的具体内容如下:

package com.ceo.remoteservice.activity;
//BookInfo的接口文件
interface BookInfo {
   void setName(String name);
   void setPrice(float price);
   void setPublish(String publish);
    
   //显示book信息
   String display();
}

该接口文件中主要包括:当前的package name,接口中的方法的声明.编写完成后ctrl+s,可以发现在gen文件夹下自动生成了BookInfo.java文件.如下图所示:

需要注意的是该文件是系统自动生成的,尽量不要改动里面的代码,以免带来不必要的错误.

第二步:声明一个类public class BookInfoImpl extends BookInfo.Stub

private float price;
private String name,publish;
    
@Override
public String display() throws RemoteException {
    return "书名:" + name + "价格:" + price + "出版社:" + publish;
}
    
@Override
public void setName(String name) throws RemoteException {
    this.name = name;
}
    
@Override
public void setPrice(float price) throws RemoteException {
    this.price = price;
}
    
@Override
public void setPublish(String publish) throws RemoteException {
    this.publish = publish;
}

该文件下实现的这些方法都是在接口文件中定义的.

第三步:向客户端暴露我们的接口,定义一个远程服务的类public class RemoteService extends Service

private Stub bookifo = new BookInfoImpl();

在onBind方法里面直接return bookifo;

第四步:主要就是MainActivity的编写了

01 public class MainActivity extends Activity {
02 //声明接口
03 private BookInfo bookinfo;
04 //声明Button
05 private Button btnShow;
06 //最重要的一点就是----->实例化ServiceConnection
07 private ServiceConnection conn = new ServiceConnection(){
08
09 @Override
10 public synchronized void onServiceConnected(ComponentName name, IBinder service) {
11 //--->获得BookInfo的接口
12 bookinfo = BookInfo.Stub.asInterface(service);
13 if(bookinfo != null) {
14 try {
15 bookinfo.setName("android开发之远程服务的调用--jack.li");
16 bookinfo.setPrice(99.99f);
17 bookinfo.setPublish("苏州xxx软件有限公司");
18 String msg = bookinfo.display();
19
20 //Toast显示
21 Toast.makeText(MainActivity.this, msg, 1).show();
22 } catch (RemoteException e) {
23 e.printStackTrace();
24 }
25 }
26 }
27
28 @Override
29 public void onServiceDisconnected(ComponentName name) {
30
31 }
32
33 };
34
35 @Override
36 public void onCreate(Bundle savedInstanceState) {
37 super.onCreate(savedInstanceState);
38 setContentView(R.layout.main);
39
40 btnShow = (Button)findViewById(R.id.btnShow);
41 btnShow.setOnClickListener(new View.OnClickListener() {
42
43 @Override
44 public void onClick(View v) {
45 Intent intent = new Intent();
46 intent.setAction("com.ceo.remoteservice.activity.action.MY_REMOTE_SERVICE");
47 bindService(intent, conn, Service.BIND_AUTO_CREATE);
48 }
49 });
50 }
51 }

最后运行结果如图:


至此,所有关于Android中的RPC模式、AIDL接口语言、以及怎样在Activity中访问另一个Service中的对象就全部介绍完毕了.

有需要整个项目源代码的留下邮箱,或直接加我qq,我会发给大家.

2011.10.20.pm

jack.li

QQ:523072842
Email:523072842@qq.com

[转载]JavaScript中模拟 Dictionary键值对

mikel阅读(782)

[转载]JavaScript中模拟 Dictionary键值对 – BirchLee – 博客园.

原文发表在:http://www.birchlee.com/post/2011/10/19/27.aspx

JavaScript常常遇到一些键值对,以前用二维数组实现,今天索性模拟了一下Dictionary帮助类。

原理:创建一个对象,包含两个数组,键数组和值数组,调用JavaScript Array对象的方法。

W3C参考地址:http://www.w3school.com.cn/js/jsref_obj_array.asp

BuildDictionary()方法用于创建一个包含两个数组的Dictionary对象

AddItem方法 调用JavaScript的 Array对象的push方法,用于将key,value追加到相应的数组。

UpdateItem方法用于更改相应的value

DeleteItem方法 调用JavaScript的Array对象的Splice方法用于删除元素,第一个参数是需要删除的元素的index,第一个参数代表删除的个数。

GetKeyStr用于得到Keys数组拼接后的字符串

GetValueStr用于得到Values数组拼接后的字符串

共包含五个方法:

/*创建Dictionary*/
function BuildDictionary() {
dic = new Object();
dic.Keys = new Array(); //键数组
dic.Values = new Array(); //值数组
return dic;
}

/*添加 key,value*/
function AddItem(key, value, dic) {
var keyCount = dic.Keys.length;
if (keyCount > 0) {
var flag = true;
for (var i = 0; i < keyCount; i++) {
if (dic.Keys[i] == key) {
flag = false;
break; //如果存在则不添加
}
}
if (flag) {
dic.Keys.push(key)
dic.Values.push(value);
}
}
else {
dic.Keys.push(key)
dic.Values.push(value);
}
return dic;
}
/*更改key,value*/
function UpdateItem(key, value, dic) {
var keyCount = dic.Keys.length;
if (keyCount > 0) {
var flag = -1;
for (var i = 0; i < keyCount; i++) {
if (dic.Keys[i] == key) {
flag = i;
break; //查找相应的index
}
}
if (flag > -1) {
dic.Keys[flag] = key;
dic.Values[flag] = value;
}
return dic;
}
else {
return dic;
}
}
/*移除key value*/
function DeleteItem(key, dic) {
var keyCount = dic.Keys.length;
if (keyCount > 0) {
var flag = -1;
for (var i = 0; i < keyCount; i++) {
if (dic.Keys[i] == key) {
flag = i;
break; //查找相应的index
}
}
if (flag > -1) {
dic.Keys.splice(flag,1); //移除
dic.Values.splice(flag, 1); //移除
}
return dic;
}
else {
return dic;
}
}

/*获取Key字符串,用符号拼接*/
function GetKeyStr(separator,dic)
{
var keyCount=dic.Keys.length;
if(keyCount>0)
{
return dic.Keys.join(separator);
}
else
{
return ”;
}
}
/*获取Value字符串,用符号拼接*/
function GetValueStr(separator,dic)
{
var keyCount=dic.Keys.length;
if(keyCount>0)
{
return dic.Values.join(separator);
}
else
{
return ”;
}
}

使用方法:创建一个全局的变量,操作这个全局变量就可以使用了。

在此抛砖引玉了

[转载]再谈C#的装箱和拆箱

mikel阅读(1036)

[转载]再谈C#的装箱和拆箱 – 玉开 – 博客园.

上一篇写了一下装箱拆箱的定义和IL分析,这一篇我们看下使用泛型和不使用泛型引发装箱拆箱的情况

1. 使用非泛型集合时引发的装箱和拆箱操作

看下面的一段代码:

1 var array = new ArrayList();
2 array.Add(1);
3 array.Add(2);
4
5 foreach (int value in array)
6 {
7 Console.WriteLine(“value is {0}”,value);
8 }

代码声明了一个ArrayList对象,向ArrayList中添加两个数字1,2;然后使用foreach将ArrayList中的元素打印到控制台。

在这个过程中会发生两次装箱操作和两次拆箱操作,在向ArrayList中添加int类型元素时会发生装箱,在使用foreach枚举 ArrayList中的int类型元素时会发生拆箱操作,将object类型转换成int类型,在执行到Console.WriteLine时,还会执行 两次的装箱操作;这一段代码执行了6次的装箱和拆箱操作;如果ArrayList的元素个数很多,执行装箱拆箱的操作会更多。

你可以通过使用ILSpy之类的工具查看IL代码的box,unbox指令查看装箱和拆箱的过程

2. 使用泛型集合的情况

请看如下代码:

var list = new List<int>();
list.Add(1);
list.Add(2);
foreach (int value in list)
{
Console.WriteLine("value is {0}", value);
}

代码和1中的代码的差别在于集合的类型使用了泛型的List,而非ArrayList;我们同样可以通过查看IL代码查看装箱拆箱的情况,上述代码只会在Console.WriteLine()方法时执行2次装箱操作,不需要拆箱操作。

可以看出泛型可以避免装箱拆箱带来的不必要的性能消耗;当然泛型的好处不止于此,泛型还可以增加程序的可读性,使程序更容易被复用等等。

本文使用的C#代码如下:

01 using System;
02 using System.Collections;
03 using System.Collections.Generic;
04
05 namespace boxOrUnbox
06 {
07 class Program
08 {
09 static void Main(string[] args)
10 {
11 //do nothing
12 }
13
14 static void Box()
15 {
16 object objValue = 9;
17 }
18
19 static void Unbox()
20 {
21 object objValue = 4;
22 int value = (int)objValue;
23 }
24
25 static void LookatArrayList()
26 {
27 var array = new ArrayList();
28 array.Add(1);
29 array.Add(2);
30
31 foreach (int value in array)
32 {
33 Console.WriteLine("value is {0}", value);
34 }
35 }
36
37 static void LookatGenericList()
38 {
39 var list = new List<int>();
40 list.Add(1);
41 list.Add(2);
42
43 foreach (int value in list)
44 {
45 Console.WriteLine("value is {0}", value);
46 }
47 }
48 }
49 }

C#的IL代码如下:

001 .class private auto ansi beforefieldinit boxOrUnbox.Program
002 extends [mscorlib]System.Object
003 {
004 // Methods
005 .method private hidebysig static
006 void Main (
007 string[] args
008 ) cil managed
009 {
010 // Method begins at RVA 0x2050
011 // Code size 2 (0x2)
012 .maxstack 8
013 .entrypoint
014
015 IL_0000: nop
016 IL_0001: ret
017 } // end of method Program::Main
018
019 .method private hidebysig static
020 void Box () cil managed
021 {
022 // Method begins at RVA 0x2054
023 // Code size 10 (0xa)
024 .maxstack 1
025 .locals init (
026 [0] object objValue
027 )
028
029 IL_0000: nop
030 IL_0001: ldc.i4.s 9
031 IL_0003: box [mscorlib]System.Int32
032 IL_0008: stloc.0
033 IL_0009: ret
034 } // end of method Program::Box
035
036 .method private hidebysig static
037 void Unbox () cil managed
038 {
039 // Method begins at RVA 0x206c
040 // Code size 16 (0x10)
041 .maxstack 1
042 .locals init (
043 [0] object objValue,
044 [1] int32 'value'
045 )
046
047 IL_0000: nop
048 IL_0001: ldc.i4.4
049 IL_0002: box [mscorlib]System.Int32
050 IL_0007: stloc.0
051 IL_0008: ldloc.0
052 IL_0009: unbox.any [mscorlib]System.Int32
053 IL_000e: stloc.1
054 IL_000f: ret
055 } // end of method Program::Unbox
056
057 .method private hidebysig static
058 void LookatArrayList () cil managed
059 {
060 // Method begins at RVA 0x2088
061 // Code size 114 (0x72)
062 .maxstack 2
063 .locals init (
064 [0] class [mscorlib]System.Collections.ArrayList 'array',
065 [1] int32 'value',
066 [2] class [mscorlib]System.Collections.IEnumerator CS$5$0000,
067 [3] bool CS$4$0001,
068 [4] class [mscorlib]System.IDisposable CS$0$0002
069 )
070
071 IL_0000: nop
072 IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
073 IL_0006: stloc.0
074 IL_0007: ldloc.0
075 IL_0008: ldc.i4.1
076 IL_0009: box [mscorlib]System.Int32
077 IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
078 IL_0013: pop
079 IL_0014: ldloc.0
080 IL_0015: ldc.i4.2
081 IL_0016: box [mscorlib]System.Int32
082 IL_001b: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
083 IL_0020: pop
084 IL_0021: nop
085 IL_0022: ldloc.0
086 IL_0023: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()
087 IL_0028: stloc.2
088 .try
089 {
090 IL_0029: br.s IL_004a
091 // loop start (head: IL_004a)
092 IL_002b: ldloc.2
093 IL_002c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
094 IL_0031: unbox.any [mscorlib]System.Int32
095 IL_0036: stloc.1
096 IL_0037: nop
097 IL_0038: ldstr "value is {0}"
098 IL_003d: ldloc.1
099 IL_003e: box [mscorlib]System.Int32
100 IL_0043: call void [mscorlib]System.Console::WriteLine(string, object)
101 IL_0048: nop
102 IL_0049: nop
103
104 IL_004a: ldloc.2
105 IL_004b: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
106 IL_0050: stloc.3
107 IL_0051: ldloc.3
108 IL_0052: brtrue.s IL_002b
109 // end loop
110
111 IL_0054: leave.s IL_0070
112 } // end .try
113 finally
114 {
115 IL_0056: ldloc.2
116 IL_0057: isinst [mscorlib]System.IDisposable
117 IL_005c: stloc.s CS$0$0002
118 IL_005e: ldloc.s CS$0$0002
119 IL_0060: ldnull
120 IL_0061: ceq
121 IL_0063: stloc.3
122 IL_0064: ldloc.3
123 IL_0065: brtrue.s IL_006f
124
125 IL_0067: ldloc.s CS$0$0002
126 IL_0069: callvirt instance void [mscorlib]System.IDisposable::Dispose()
127 IL_006e: nop
128
129 IL_006f: endfinally
130 } // end handler
131
132 IL_0070: nop
133 IL_0071: ret
134 } // end of method Program::LookatArrayList
135
136 .method private hidebysig static
137 void LookatGenericList () cil managed
138 {
139 // Method begins at RVA 0x2118
140 // Code size 90 (0x5a)
141 .maxstack 2
142 .locals init (
143 [0] class [mscorlib]System.Collections.Generic.List`1<int32> list,
144 [1] int32 'value',
145 [2] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32> CS$5$0000,
146 [3] bool CS$4$0001
147 )
148
149 IL_0000: nop
150 IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
151 IL_0006: stloc.0
152 IL_0007: ldloc.0
153 IL_0008: ldc.i4.1
154 IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
155 IL_000e: nop
156 IL_000f: ldloc.0
157 IL_0010: ldc.i4.2
158 IL_0011: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
159 IL_0016: nop
160 IL_0017: nop
161 IL_0018: ldloc.0
162 IL_0019: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
163 IL_001e: stloc.2
164 .try
165 {
166 IL_001f: br.s IL_003c
167 // loop start (head: IL_003c)
168 IL_0021: ldloca.s CS$5$0000
169 IL_0023: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
170 IL_0028: stloc.1
171 IL_0029: nop
172 IL_002a: ldstr "value is {0}"
173 IL_002f: ldloc.1
174 IL_0030: box [mscorlib]System.Int32
175 IL_0035: call void [mscorlib]System.Console::WriteLine(string, object)
176 IL_003a: nop
177 IL_003b: nop
178
179 IL_003c: ldloca.s CS$5$0000
180 IL_003e: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
181 IL_0043: stloc.3
182 IL_0044: ldloc.3
183 IL_0045: brtrue.s IL_0021
184 // end loop
185
186 IL_0047: leave.s IL_0058
187 } // end .try
188 finally
189 {
190 IL_0049: ldloca.s CS$5$0000
191 IL_004b: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
192 IL_0051: callvirt instance void [mscorlib]System.IDisposable::Dispose()
193 IL_0056: nop
194 IL_0057: endfinally
195 } // end handler
196
197 IL_0058: nop
198 IL_0059: ret
199 } // end of method Program::LookatGenericList
200
201 .method public hidebysig specialname rtspecialname
202 instance void .ctor () cil managed
203 {
204 // Method begins at RVA 0x2190
205 // Code size 7 (0x7)
206 .maxstack 8
207
208 IL_0000: ldarg.0
209 IL_0001: call instance void [mscorlib]System.Object::.ctor()
210 IL_0006: ret
211 } // end of method Program::.ctor
212
213 } // end of class boxOrUnbox.Program

请尊重作者的劳动,转载请保留链接 玉开的技术博客

[转载]IIS 内部运行机制

mikel阅读(734)

[转载]IIS 内部运行机制 – ※森林小居※ – 博客园.

ASP.NET是一个非常强大的构建Web应用的平台,它提供了极大的灵活性和能力以致于可以用它来构建所有类型的Web应用。

绝大多数的人只熟悉高层的框架如: WebForms 和 WebServices –这些都在ASP.NET层次结构在最高层。

这篇文章的资料收集 整理自各种微软公开的文档,通过比较 IIS5、IIS6、IIS7 这三代 IIS 对请求的处理过程, 让我们熟悉 ASP.NET的底层机制并对请求(request)是怎么从Web服务器传送到ASP.NET运行时有所了解。通过对底层机制的了解,可以让我们对 ASP.net 有更深的理解。

IIS 5 的 ASP.net 请求处理过程

对图的解释:

IIS 5.x 一个显著的特征就是 Web Server 和真正的 ASP.NET Application 的分离。作为 Web Server 的IIS运行在一个名为 InetInfo.exe 的进程上,InetInfo.exe 是一个Native Executive,并不是一个托管的程序,而我们真正的 ASP.NET Application 则是运行在一个叫做 aspnet_wp 的 Worker Process 上面,在该进程初始化的时候会加载CLR,所以这是一个托管的环境。

ISAPI:  指能够处理各种后缀名的应用程序。 ISAPI 是下面单词的简写 :Internet Server Application Programe Interface,互联网服务器应用程序接口。

IIS 5 模式的特点:

1、首先,同一台主 机上在同一时间只能运行一个 aspnet_wp 进程,每个基于虚拟目录的 ASP.NET Application 对应一个 Application Domain ,也就是说每个 Application 都运行在同一个 Worker Process 中,Application之间的隔离是基于 Application Domain 的,而不是基于Process的。

2、其 次,ASP.NET  ISAPI 不但负责创建 aspnet_wp Worker Process,而且负责监控该进程,如果检测到 aspnet_wp 的 Performance 降低到某个设定的下限,ASP.NET  ISAPI 会负责结束掉该进程。当 aspnet_wp 结束掉之后,后续的 Request 会导致ASP.NET ISAPI 重新创建新的 aspnet_wp Worker Process。

3、最后,由于 IIS 和 Application 运行在他们各自的进程中,他们之间的通信必须采用特定的通信机制。本质上 IIS 所在的 InetInfo 进程和 Worker Process 之间的通信是同一台机器不同进程的通信(local interprocess communications),处于Performance的考虑,他们之间采用基于Named pipe的通信机制。ASP.NET ISAPI和Worker Process之间的通信通过他们之间的一组Pipe实现。同样处于Performance的原因,ASP.NET ISAPI 通过异步的方式将Request 传到Worker Process 并获得 Response,但是 Worker Process 则是通过同步的方式向 ASP.NET ISAPI 获得一些基于 Server 的变量。

IIS6 的 ASP.net 请求处理过程

对图的解释:

IIS 5.x 是通过 InetInfo.exe 监听 Request 并把Request分发到Work Process。换句话说,在IIS 5.x中对Request的监听和分发是在User Mode中进行,在IIS 6中,这种工作被移植到kernel Mode中进行,所有的这一切都是通过一个新的组件:http.sys 来负责。

注:为了避免用户应 用程序访问或者修改关键的操作系统数据,windows提供了两种处理器访问模式:用户模式(User Mode)和内核模式(Kernel Mode)。一般地,用户程序运行在User mode下,而操作系统代码运行在Kernel Mode下。Kernel Mode的代码允许访问所有系统内存和所有CPU指令。

在User Mode下,http.sys接收到一个基于 aspx 的http request,然后它会根据IIS中的 Metabase 查看该基于该 Request 的 Application 属于哪个Application Pool, 如果该Application Pool不存在,则创建之。否则直接将 request 发到对应Application Pool 的 Queue中。

每个 Application Pool 对应着一个Worker Process:w3wp.exe,毫无疑问他是运行在User Mode下的。在IIS Metabase 中维护着 Application Pool 和worker process的Mapping。WAS(Web Administrative service)根据这样一个mapping,将存在于某个Application Pool Queue的request 传递到对应的worker process(如果没有,就创建这样一个进程)。在 worker process 初始化的时候,加载ASP.NET ISAPI,ASP.NET ISAPI 进而加载CLR。最后的流程就和IIS 5.x一样了:通过AppManagerAppDomainFactory 的 Create方法为 Application 创建一个Application Domain;通过 ISAPIRuntime 的 ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime Pipeline。

IIS 7  的 ASP.net 请求处理过程

IIS7 站点启动并处理请求的步骤如下图:

步骤 1 到 6 ,是处理应用启动,启动好后,以后就不需要再走这个步骤了。

上图的8个步骤分别如下:

1、当客户端浏览器开始HTTP 请求一个WEB 服务器的资源时,HTTP.sys 拦截到这个请求。

2、HTTP.sys contacts WAS to obtain information from the configuration store.

3、WAS 向配置存储中心请求配置信息。applicationHost.config。

4、WWW 服务接受到配置信息,配置信息指类似应用程序池配置信息,站点配置信息等等。

5、WWW 服务使用配置信息去配置 HTTP.sys 处理策略。

6、WAS starts a worker process for the application pool to which the request was made.

7、The worker process processes the request and returns a response to HTTP.sys.

8、客户端接受到处理结果信息。

W3WP.exe 进程中又是如果处理得呢?? IIS 7 的应用程序池的托管管道模式分两种: 经典和集成。 这两种模式下处理策略各不相通。

IIS 6 以及 IIS7 经典模式的托管管道的架构

在IIS7之前,ASP.NET 是以 IIS ISAPI extension 的方式外加到 IIS,其实包括 ASP 以及 PHP,也都以相同的方式配置(PHP 在 IIS 采用了两种配置方式,除了 IIS ISAPI extension 的方式,也包括了 CGI 的方式,系统管理者能选择 PHP 程序的执行方式),因此客户端对 IIS 的 HTTP 请求会先经由 IIS 处理,然后 IIS 根据要求的内容类型,如果是 HTML 静态网页就由 IIS 自行处理,如果不是,就根据要求的内容类型,分派给各自的 IIS ISAPI extension;如果要求的内容类型是 ASP.NET,就分派给负责处理 ASP.NET 的 IIS ISAPI extension,也就是 aspnet_isapi.dll。下图是这个架构的示意图。

IIS  7 应用程序池的托管管道模式  经典  模式也是这样的工作原理。 这种模式是兼容IIS 6 的方式, 以减少升级的成本。

IIS6 的执行架构图,以及 IIS7  应用程序池配置成经典模式的执行架构图

IIS  7 应用程序池的 托管管道模式  集成模式

而 IIS 7 完全整合 .NET 之后,架构的处理顺序有了很大的不同(如下图),最主要的原因就是 ASP.NET 从 IIS 插件(ISAPI extension)的角色,进入了 IIS 核心,而且也能以 ASP.NET 模块负责处理 IIS 7 的诸多类型要求。这些 ASP.NET 模块不只能处理 ASP.NET 网页程序,也能处理其他如 ASP 程序、PHP 程序或静态 HTML 网页,也因为 ASP.NET 的诸多功能已经成为 IIS 7 的一部份,因此 ASP 程序、PHP 程序或静态 HTML 网页等类型的要求,也能使用像是Forms认证(Forms Authentication)或输出缓存(Output Cache)等 ASP.NET 2.0 的功能(但须修改 IIS 7 的设定值)。也因为 IIS 7 允许自行以 ASP.NET API 开发并加入模块,因此 ASP.NET 网页开发人员将更容易扩充 IIS 7 和网站应用程序的功能,甚至能自行以 .NET 编写管理 IIS 7 的程序(例如以程控 IIS 7 以建置网站或虚拟目录)。

IIS 7 的执行架构图(集成托管信道模式下的架构)

小结

IIS5 到 IIS6 的改进,主要是 HTTP.sys 的改进。

IIS6 到 IIS7 的改进,主要是 ISAPI 的改进。

参考资料:

ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI

http://www.cnblogs.com/artech/archive/2007/09/09/887528.html

ASP.NET Internals – IIS and the Process Model

http://dotnetslackers.com/articles/iis/ASPNETInternalsIISAndTheProcessModel.aspx

模组化的IIS 7 与.NET 能力整合

http://www.microsoft.com/taiwan/technet/columns/profwin/33-iis7-componentization-integration.mspx

Introduction to IIS 7.0 Architecture

http://learn.iis.net/page.aspx/101/introduction-to-iis7-architecture/