[问题]服务器 'server_1' 上的 MSDTC 不可用。

mikel阅读(759)

一.A.不用事务,关用Select 语句.是否可以分布式查询?
B.LINKSERVER 在做分布式更新事务时不能对本机操作.(就是不能环回分布式事务)
C.DBCC TRACEON (3604, 7300)–用跟踪看更详细错误信息.
D.下载MS提供的DTCPing.exe 分装在两台机上,按README说明来运行它.看出错信息.
http://download.microsoft.com/download/complus/msdtc/1.7/nt45/en-us/DTCPing.exe
二.两台机的MSDTC是否都打开了.
三.MSDTC设置是否正确.
1.打开命令提示,运行”net stop msdtc”,然后运行”net start msdtc”。
2.转至”组件服务管理工具”。
3.浏览至”启动管理工具”。
4.选择”组件服务”。
a.展开”组件服务”树,然后展开”我的电脑”。
b.右键单击”我的电脑”,然后选择”属性”。
C.在 MSDTC 选项卡中,确保选中了下列选项: 网络 DTC 访问
网络管理
网络事务
XA 事务
e.另外,”DTC 登录帐户”一定要设置为”NT Authority\NetworkService”。
5.单击”确定”。这样将会提示您”MS DTC 将会停止并重新启动。
所有的依赖服务将被停止。请按'是'继续”。单击”是”继续。
6.单击”确定”关闭”我的电脑”属性窗口。
四.
MSDTC依赖于RPC,RPC使用的端口是135,测试135端口是否打开.是否有防火墙?如果有先关了防火墙.
telnet IP 135
如果是关闭的打开它.
五.
有的机由于各种原因),SQLOLEDB不能使用分布式事务,更改为”MSDASQL” 的ODBC方式联接.
使用RRAS而不是RAS.(控制面版–管理工具–远程服务管理器)
Check whether you are using Remote Access Server (RAS) to access remote servers. If so, make sure that you have implemented Routing RAS (RRAS). Linked server does not work on RAS because RAS allows only one way communication.
七.检查你的两台服务器是否在同一个域中.
如果不在同一个域中,是否建立可信任联接.
八.如果是WIN2000,升级到SP4
九.升级MDAC到2.6以上,最好是2.8.
十.要安装SQL的最新补丁: sp3a
'全部补丁的位置
http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=9032f608-160a-4537-a2b6-4cb265b80766
'应该安装的补丁sql 2000 sp3
http://download.microsoft.com/download/d/d/e/dde427eb-0296-4eac-a47c-d11a66b03816/chs_sql2ksp3.exe
我的解决方法:net stop msdtc”,然后运行”net start msdtc”开启服务后正常。

[原创]TransactionScope事务使用问题

mikel阅读(961)

最近在使用.Net中的TransactionScope事务的过程中,发现个问题,当事务提交后
直接return到另一个控制器来执行数据库操作,结果数据库连接不能使用,
后来发现原来是return语句不应该放在事务中,只有当事务提交后才真正的释放连接,否则再次打开
只不过是提交事务而已,因此需要在事务using范围外执行再次的数据库操作
错误代码:

//如果没有改变分类
if (theModuleId == moduleId)
{
return this.SavePublishInfo(identifier, infoTitle, moduleId, linkManId, infoContent, picture, keyWords,displayLinkMan);
}
else//如果修改了分类,先插入到新分类表中一条记录,然后删除源记录
{
using (System.Transactions.TransactionScope tx = new System.Transactions.TransactionScope())
{
//先插入一条记录
int userid = ((UserInfo)Session["User"]).Identifier;
Information information = new Information();
try
{
business.Save<Information>(information);
try
{
//然后再按id和moduleID删除原记录
//Information info = new Information();
information.Identifier = identifier;
information.ModuleId = theModuleId;
business.Remove<Information>(information);
tx.Complete();
return this.Index();
}
catch (Exception e)
{
//回滚事务
tx.Dispose();
return baseController.Error("Error", "错误提示", "修改记录失败!错误信息:</br>" + e.Message);
}
}
catch (Exception e)
{
tx.Dispose();
return baseController.Error("Error", "错误提示", "修改记录失败!错误信息:</br>" + e.Message);
}
}

正确代码:
注意:return this.Index();

//如果没有改变分类
if (theModuleId == moduleId)
{
return this.SavePublishInfo(identifier, infoTitle, moduleId, linkManId, infoContent, picture, keyWords,displayLinkMan);
}
else//如果修改了分类,先插入到新分类表中一条记录,然后删除源记录
{
using (System.Transactions.TransactionScope tx = new System.Transactions.TransactionScope())
{
//先插入一条记录
int userid = ((UserInfo)Session["User"]).Identifier;
Information information = new Information();
try
{
business.Save<Information>(information);
try
{
//然后再按id和moduleID删除原记录
//Information info = new Information();
information.Identifier = identifier;
information.ModuleId = theModuleId;
business.Remove<Information>(information);
tx.Complete();
}
catch (Exception e)
{
//回滚事务
tx.Dispose();
return baseController.Error("Error", "错误提示", "修改记录失败!错误信息:</br>" + e.Message);
}
}
catch (Exception e)
{
tx.Dispose();
return baseController.Error("Error", "错误提示", "修改记录失败!错误信息:</br>" + e.Message);
}
}
return this.Index();

[问题]CS1061的错误解决办法

mikel阅读(1609)

最近MVC页面中自定义了属性后,结果发现有的页面中能用this.属性名 读取有的读取不了
而且提示CS1061错误,说属性未定义,开始还以为是ViewPage的OnLoad事件的问题
后来发现原来是由于页面相似,将其他页面粘贴过来后忘了该CodeBehind=”EditInfo.aspx.cs” Inherits=”NewTang.Views.Shop.EditInfo”
的原因

[原创]JQuery的FckEditor插件使用教程

mikel阅读(1127)

需要引用的js文件:
Content/JQuery-1.2.6.js
fckeditor/fckeditor.js
JQuery.FCKEditor.js

JavaScript代码:

$(document).ready(function(){
//初始化FCKEditor
$.fck.config = {path: '../../FCKeditor/', height: 300 ,toolbar:'Basic'};
$('textarea#infoContent').fck();
});

HTML代码:

<textarea id="infoContent" name="infoContent" rows="22" ></textarea>

读取FCKEditor的值代码:

$.fck.content(&#39;infoContent&#39;, &#39;&#39;); //注意‘infoContent’即为你绑定的textArea的Id或name,这样才能取得值

[JQuery]JQuery使用手册

mikel阅读(757)

翻译整理:Young.J
官方网站
http://JQuery.com
    JQuery是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持,使我们写js变得更加方便!如果你不是个js高手又想写出优 秀的js效果,jQuery可以帮你达到目的!
   下载地址:Starterkit (
http://jQuery.bassistance.de/jQuery-starterkit.zip
                       jQuery Downloads (
http://jquery.com/src/

   下载完成后先加载到文档中,然后我们来看个简单的例子!

<script language="JavaScript" type="text/JavaScript">   
    $(document).ready(
function(){
        $(
"a").click(function() {
        alert(
"Hello world!");
   });
});
<script>

     上边的效果是点击文档中所有a标签时将弹出对话框,$("a") 是一个jQuery选择器,$本身表示一个jQuery类,所有$()是构造一个jQuery对象,click()是这个对象的方法,同 理$(document)也是一个jQuery对象,ready(fn)是$(document)的方法,表示当document全部下载完毕时执行函 数。
     在进行下面内容之前我还要说明一点$("p")和$("#p")的区别,$("p")表示取所有p标签(<p></p>)的元 素,$("#p")表示取id为"p"(<span  id="p"></span>)的元素.

我将从以下几个内容来讲解jQuery的使用:
1:核心部分
2:DOM操作
3:css操作
4:JavaScript处理
5:动态效果
6:event事件
7:ajax支持
8:插件程序

                                             一:核心部分
$(expr)
说明:该函数可以通过css选择器,Xpath或html代码来匹配目标元素,所有的jQuery操作都以此为基础
参数:expr:字符串,一个查询表达式或一段html字符串
例子:
未执行jQuery前:

<p>one</p>
<div>
     
<p>two</p>
</div>
    <
p>three</p> 
    <href="#" id="test" onClick="jq()" >jQuery</a>

jQuery代码及功能:

function jq(){  
    alert($(
"div > p").html());  
}

运行:当点击id为test的元素时,弹出对话框文字为two,即div标签下p元素的内容

function jq(){
    $(
"<div><p>Hello</p></div>").appendTo("body");
}

运行:当点击id为test的元素时,向body中添加“<div><p>Hello</p></div>”
$(elem)
说明:限制jQuery作用于一个特定的dom元素,这个函数也接受xml文档和windows对象
参数: elem:通过jQuery对象压缩的DOM元素
例子:
未执行jQuery前:

<p>one</p>
  
<div>
     
<p>two</p>
  
</div><p>three</p>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    alert($(document).find(
"div > p").html());
}

运行:当点击id为test的元素时,弹出对话框文字为two,即div标签下p元素的内容

function jq(){
   $(document.body).background(
"black");
}

运行:当点击id为test的元素时,背景色变成黑色

$(elems)
说明:限制jQuery作用于一组特定的DOM元素
参数: elem:一组通过jQuery对象压缩的DOM元素
例子:
未执行jQuery前:

<form id="form1">
     
<input type="text" name="textfield">
     
<input type="submit" name="Submit" value="提交">
</form>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){ 
   $(form1.elements ).hide(); 
}

运行:当点击id为test的元素时,隐藏form1表单中的所有元素。
$(fn)
说明:$(document).ready()的一个速记方式,当文档全部载入时执行函数。可以有多个$(fn)当文档载入时,同时执行所有函数!
参数:fn (Function):当文档载入时执行的函数!
例子:

$( function(){
    $(document.body).background(
"black");
})

运行:当文档载入时背景变成黑色,相当于onLoad。
$(obj)
说明:复制一个jQuery对象,
参数:obj (jQuery): 要复制的jQuery对象
例子:
未执行jQuery前:

<p>one</p>
<div>
   
<p>two</p>
</div>
<p>three</p>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    
var f = $("div"); 
    alert($(f).find(
"p").html()) 
}

运行:当点击id为test的元素时,弹出对话框文字为two,即div标签下p元素的内容。
each(fn)
说明:将函数作用于所有匹配的对象上
参数:fn (Function): 需要执行的函数
例子:
未执行jQuery前:

<img src="1.jpg"/>
<img src="1.jpg"/>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
   $(
"img").each(function(){ 
        
this.src = "2.jpg"; });
}

运行:当点击id为test的元素时,img标签的src都变成了2.jpg。
eq(pos)
说明:减少匹配对象到一个单独得dom元素
参数:pos (Number): 期望限制的索引,从0 开始
例子:
未执行jQuery前:

<p>This is just a test.</p>
<p>So is this</p>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    alert($(
"p").eq(1).html())
}

运行:当点击id为test的元素时,alert对话框显示:So is this,即第二个<p>标签的内容

get() get(num)
说明:获取匹配元素,get(num)返回匹配元素中的某一个元素
参数:get (Number): 期望限制的索引,从0 开始
例子:
未执行jQuery前:

<p>This is just a test.</p>
<p>So is this</p>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    alert($(
"p").get(1).innerHTML);
}

运行:当点击id为test的元素时,alert对话框显示:So is this,即第二个<p>标签的内容
注意get和eq的区别,eq返回的是jQuery对象,get返回的是所匹配的dom对象,所有取$("p").eq(1)对象的内容用jQuery方法html(),而取$("p").get(1)的内容用innerHTML

index(obj)
说明:返回对象索引
参数:obj (Object): 要查找的对象
例子:
未执行jQuery前:

<div id="test1"></div>
<div id="test2"></div>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    alert($(
"div").index(document.getElementById('test1')));
    alert($(
"div").index(document.getElementById('test2')));
}

运行:当点击id为test的元素时,两次弹出alert对话框分别显示0,1

size()   Length
说明:当前匹配对象的数量,两者等价
例子:
未执行jQuery前:

<img src="test1.jpg"/>
<img src="test2.jpg"/>
<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
    alert($(
"img").length);
}

运行:当点击id为test的元素时,弹出alert对话框显示2,表示找到两个匹配对象 

                                                   二:DOM操作
属性
我 们以<img id="a" scr="5.jpg"/>为例,在原始的javascript里面可以用var o=document.getElementById('a')取的id为a的节点对象,在用o.src来取得或修改该节点的scr属性,在jQuery 里$("#a")将得到jQuery对象[ <img id="a" scr="5.jpg"/> ],然后可以用jQuery提供的很多方法来进行操作,如$("#a").scr()将得到5.jpg,$("#a").scr("1.jpg")将该对 象src属性改为1,jpg。下面我们来讲jQuery提供的众多jQuery方法,方便大家快速对DOM对象进行操作
herf()   herf(val)
说明:对jQuery对象属性herf的操作。
例子:
未执行jQuery前

<href="1.htm" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
   alert($(
"#test").href());
   $(
"#test").href("2.html");
}

运行:先弹出对话框显示id为test的连接url,在将其url改为2.html,当弹出对话框后会看到转向到2.html
同理,jQuery还提供类似的其他方法,大家可以分别试验一下:
herf()  herf(val)   html()  html(val)   id()  id (val)  name()  name (val)   rel()  rel (val)
src()    src (val)   title()  title (val)   val()  val(val)

操作
after(html)  在匹配元素后插入一段html

<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){  
       $(
"#test").after("<b>Hello</b>");  
}

执行后相当于:

<href="#" id="test" onClick="jq()">jQuery</a><b>Hello</b>

after(elem)  after(elems)  将指定对象elem或对象组elems插入到在匹配元素后

<id="test">after</p><href="#" onClick="jq()">jQuery</a>

jQuery代码及功能

function jq(){  
     $(
"a").after($("#test"));  
}

执行后相当于

<href="#" onClick="jq()">jQuery</a><id="test">after</p>


append(html)在匹配元素内部,且末尾插入指定html

<href="#" id="test" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){ 
     $("#test").append("
<b>Hello</b>");  
}

执行后相当于

<href="#" onClick="jq()">jQuery<b>Hello</b></a>

同理还有append(elem)  append(elems) before(html) before(elem) before(elems)请执行参照append和after的方来测试、理解!
appendTo(expr)  与append(elem)相反

<id="test">after</p><href="#" onClick="jq()">jQuery</a>

jQuery代码及功能

function jq(){  
      $(
"a"). appendTo ($("#test"));  
}

执行后相当于

<id="test">after<href="#" onClick="jq()">jQuery</a> </p>


clone() 复制一个jQuery对象

<id="test">after</p><href="#" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){  
     $(
"#test").clone().appendTo($("a"));  
}

复制$("#test")然后插入到<a>后,执行后相当于

<id="test">after</p><href="#" onClick="jq()">jQuery</a><id="test">after</p>


empty() 删除匹配对象的所有子节点

<div id="test">
  
<span>span</span>
  
<p>after</p>
</div>
<href="#" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){  
    $(
"#test").empty();  
}

执行后相当于

<div id="test"></div><href="#" onClick="jq()">jQuery</a>

insertAfter(expr)   insertBefore(expr)
     按照官方的解释和我的几个简单测试insertAfter(expr)相当于before(elem),insertBefore(expr)相当于after (elem)
prepend (html)  prepend (elem)  prepend (elems)   在匹配元素的内部且开始出插入
通过下面例子区分append(elem)  appendTo(expr)  prepend (elem)

<id="a">p</p>
<div>div</div>

执行$("#a").append($("div")) 后相当于

<id="a">
  P
  
<div>div</div>
</p>

执行$("#a").appendTo($("div")) 后 相当于

<div>
   div
   
<id="a">p</p>
</div>

执行$("#a").prepend ($("div")) 后 相当于

<id="a">
   
<div>div</div>
   P
</p>

remove()  删除匹配对象
注意区分empty(),empty()移出匹配对象的子节点,remove(),移出匹配对象
wrap(htm) 将匹配对象包含在给出的html代码内

<p>Test Paragraph.</p> <href="#" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){  
      $(
"p").wrap("<div class='wrap'></div>"); 
}

执行后相当于

<div class='wrap'><p>Test Paragraph.</p></div>


wrap(elem) 将匹配对象包含在给出的对象内

<p>Test Paragraph.</p><div id="content"></div>
<href="#" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){  
      $(
"p"
).wrap( document.getElementById('content') );
}

执行后相当于

<div id="content"><p>Test Paragraph.</p></div>

遍历、组合
add(expr)  在原对象的基础上在附加符合指定表达式的jquery对象

<p>Hello</p><p><span>Hello Again</span></p>
<href="#" onClick="jq()">jQuery</a>

jQuery代码及功能:

function jq(){
     
var f=$("p").add("span");    
     
for(var i=0;i < $(f).size();i++){
     alert($(f).eq(i).html());}
}

执行$("p")得到匹配<p>的对象,有两个,add("span")是在("p")的基础上加上匹配<span >的对象,所有一共有3个,从上面的函数运行结果可以看到$("p").add("span")是3个对象的集合,分别是 [<p>Hello</p>],[<p><span>Hello Again</span></p>],[<span>Hello Again</span>]。
add(el)  在匹配对象的基础上在附加指定的dom元素。
        $("p").add(document.getElementById("a"));
add(els)  在匹配对象的基础上在附加指定的一组对象,els是一个数组

<p>Hello</p><p><span>Hello Again</span></p>

jQuery代码及功能:

function jq(){
     
var f=$("p").add([document.getElementById("a"), document.getElementById("b")])
     
for(var i=0;i < $(f).size();i++){
             alert($(f).eq(i).html());}
}

注意els是一个数组,这里的[ ]不能漏掉。
ancestors ()  一依次以匹配结点的父节点的内容为对象,根节点除外(有点不好理解,看看下面例子就明白了)

<div>
    
<p>one</p>
    
<span>
    
<u>two</u>
    
</span>
</div>

jQuery代码及功能:

function jq(){
     
var f= $("u").ancestors();
     
for(var i=0;i < $(f).size();i++){
      alert($(f).eq(i).html());}
}

第一个对象是以<u>的父节点的内容为对象,[ <u>two</u> ]
第一个对象是以<u>的父节点的父节点(div)的内容为对象,[<p>one</p><span><u>two</u></span> ]
一般一个文档还有<body>和<html>,依次类推下去。
ancestors (expr)  在ancestors()的基础上之取符合表达式的对象
如上各例子讲var f改为var f= $("u").ancestors(“div”),则只返回一个对象:
[ <p>one</p><span><u>two</u></span>  ]
children()  返回匹配对象的子介点

<p>one</p>
<div id="ch">   
     
<span>two</span>
</div>

jQuery代码及功能:

function jq(){
    alert($(
"#ch").children().html());
}

$("#ch").children()得到对象[ <span>two</span> ].所以.html()的结果是”two”
children(expr)  返回匹配对象的子介点中符合表达式的节点

<div id="ch">   
      
<span>two</span>
      
<span id="sp">three</span>
</div>

jQuery代码及功能

function jq(){
    alert($(
"#ch").children(“#sp”).html());
}

$("#ch").children()得到对象[<span>two</span><span id="sp">three</span> ].
$("#ch").children(“#sp”)过滤得到[<span id="sp">three</span> ]
parent ()  parent (expr)取匹配对象父节点的。参照children帮助理解
contains(str)  返回匹配对象中包含字符串str的对象

<p>This is just a test.</p><p>So is this</p>

jQuery代码及功能:

function jq(){
    alert($(
"p").contains("test").html());
}

$("p")得到两个对象,而包含字符串”test”只有一个。所有$("p").contains("test")返回 [ <p>This is just a test.</p> ]
end() 结束操作,返回到匹配元素清单上操作前的状态.

filter(expr)   filter(exprs)   过滤现实匹配符合表达式的对象 exprs为数组,注意添加“[ ]”

<p>Hello</p><p>Hello Again</p><class="selected">And Again</p>

jQuery代码及功能:

function jq(){
    alert($(
"p").filter(".selected").html())
}

$("p")得到三个对象,$("p").contains("test")只返回class为selected的对象。
find(expr)  在匹配的对象中继续查找符合表达式的对象

<p>Hello</p><id="a">Hello Again</p><class="selected">And Again</p>

Query代码及功能:

function jq(){
    alert($(
"p").find("#a").html())
}

在$("p")对象中查找id为a的对象。
is(expr)  判断对象是否符合表达式,返回boolen值

<p>Hello</p><id="a">Hello Again</p><class="selected">And Again</p>

Query代码及功能:

function jq(){
    alert($(
"#a").is("p"));
}

在$("#a ")是否符合jquery表达式。
大家可以用$("#a").is("div");  ("#a").is("#a")多来测试一下
next()  next(expr)  返回匹配对象剩余的兄弟节点

<p>Hello</p><id="a">Hello Again</p><class="selected">And Again</p>

jQuery代码及功能

function jq(){
        alert($(
"p").next().html());
        alert($(
"p").next(".selected").html());
}

$("p").next()返回 [ <p id="a">Hello Again</p> , <p class="selected">And Again</p> ]两个对象
$("p").next(".selected)只返回 [<p class="selected">And Again</p> ]一个对象
prev ()  prev (expr)  参照next理解

not(el)  not(expr)  从jQuery对象中移出匹配的对象,el为dom元素,expr为jQuery表达式。

<p>one</p><id="a">two</p>
<href="#" onclick="js()">jQuery</a>

jQuery代码及功能:

function js(){
     alert($(
"p").not(document.getElementById("a")).html());
     alert($(
"p").not(“#a”).html());
}

$("p")由两个对象,排除后的对象为[<p>one</p> ]
siblings ()  siblings (expr)  jquery匹配对象中其它兄弟级别的对象

<p>one</p>
<div>
  
<id="a">two</p>
</div>
<href="#" onclick="js()">jQuery</a>

jQuery代码及功能:

function js(){
       alert($(
"div").siblings().eq(1).html());
}

$("div").siblings()的结果实返回两个对象[<p>one</p>,<a href="#" onclick="js()">jQuery</a> ]
alert($("div").siblings(“a”)返回一个对象[<a href="#" onclick="js()">jQuery</a> ]
其他
addClass(class)   为匹配对象添加一个class样式
removeClass (class)   将第一个匹配对象的某个class样式移出

attr (name)   获取第一个匹配对象的属性

<img src="test.jpg"/><href="#" onclick="js()">jQuery</a> 

jQuery代码及功能:

function js(){
     alert($(
"img").attr("src"));
}

返回test.jpg
attr (prop)   为第一个匹配对象的设置属性,prop为hash对象,用于为某对象批量添加众多属性

<img/><href="#" onclick="js()">jQuery</a>

jQuery代码及功能:

function js(){
     $(
"img").attr({ src: "test.jpg", alt: "Test Image" }); 
}

运行结果相当于<img src="test.jpg" alt="Test Image"/>
attr (key,value)   为第一个匹配对象的设置属性,key为属性名,value为属性值

<img/><a href="#" onclick="js()">jQuery</a>

jQuery代码及功能

function js(){
     $(
"img").attr(“src”,”test.jpg”); 
}

运行结果相当于<img src="test.jpg"/>
removeAttr (name)   将第一个匹配对象的某个属性移出

<img alt="test"/><href="#" onclick="js()">jQuery</a>

jQuery代码及功能:

function js(){
     $(
"img"). removeAttr("alt"); 
}

运行结果相当于<img />
toggleClass (class)   将当前对象添加一个样式,不是当前对象则移出此样式,返回的是处理后的对象

<p>Hello</p><class="selected">Hello Again</p><href="#" onclick="js()">jQuery</a>

$("p")的结果是返回对象 [<p>Hello</p>,<p class="selected">Hello Again</p> ]
$("p").toggleClass("selected")的结果是实返回对象 [ <p class="selected">Hello</p>, <p>Hello Again</p> ] 
         :CSS操作

      传统javascript对css的操作相当繁琐,比如<div id="a" style="background:blue">css</div>取它的background语法是 document.getElementById("a").style.background,而jQuery对css更方便的操 作,$("#a").background(),$("#a").background(“red”)
$("#a")得到jQuery对象[ <div id="a" … /div> ]
$("#a").background()将取出该对象的background样式。
$("#a").background(“red”)将该对象的background样式设为red
jQuery提供了以下方法,来操作css
background ()   background (val)     color()    color(val)     css(name)    css(prop)   
css(key, value)      float()   float(val)   height()   height(val)  width()  width(val) 
left()   left(val)       overflow()   overflow(val)   position()   position(val)  top()   top(val)


这里需要讲解一下css(name)  css(prop)  css(key, value),其他的看名字都知道什么作用了!

<div id="a" style="background:blue; color:red">css</div><id="b">test</P>

css(name)  获取样式名为name的样式
$("#a").css("color") 将得到样式中color值red,("#a").css("background ")将得到blue
css(prop)  prop是一个hash对象,用于设置大量的css样式
$("#b").css({ color: "red", background: "blue" });
最 终效果是<p id="b" style="background:blue; color:red">test</p>,{ color: "red", background: "blue" },hash对象,color为key,"red"为value,
css(key, value)  用于设置一个单独得css样式
$("#b").css("color","red");最终效果是<p id="b" style="color:red">test</p>
                                              :JavaScript处理

$.browser()  判断浏览器类型,返回boolen值

$(function(){
    
if($.browser.msie) {
        alert(
"这是一个IE浏览器");}
    
else if($.browser.opera) {
        alert(
"这是一个opera浏览器");}
})

当页面载入式判断浏览器类型,可判断的类型有msie、mozilla、opera、safari
$.each(obj, fn)  obj为对象或数组,fn为在obj上依次执行的函数,注意区分$().each()

$.each( [0,1,2], function(i){ alert( "Item #" + i + "" + this ); });

    分别将0,1,2为参数,传入到function(i)中

$.each({ name: "John", lang: "JS" },  function(i){ alert( "Name: " + i + ", Value: " + this );

    { name: "John", lang: "JS" }为一个hash对象,依次将hash中每组对象传入到函数中
$.extend(obj, prop)  用第二个对象扩展第一个对象

var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
$.extend(settings, options);

执行后settings对象为{ validate: true, limit: 5, name: "bar" }
可以用下面函数来测试

$(function(){
       
var settings = { validate: false, limit: 5, name: "foo" };
        
var options = { validate: true, name: "bar" };
        $.extend(settings, options);
        $.each(settings,  
function(i){ alert( i + "=" + this ); });
})

$.grep(array,fn)  通过函数fn来过滤array,将array中的元素依次传给fn,fn必须返回一个boolen,如fn返回true,将被过滤

$(function(){
        
var arr= $.grep( [0,1,2,3,4], function(i){ return i > 2; });
        $.each(arr, 
function(i){ alert(i); });
})

我们可以看待执行$.grep后数组[0,1,2,3,4]变成[0,1]
$.merge(first, second)  两个参数都是数组,排出第二个数组中与第一个相同的,再将两个数组合并

$(function(){ 
        
var arr = $.merge( [0,1,2], [2,3,4] )
        $.each(arr,  
function(i){ alert(i); });
})

可以看出arr的结果为[0,1,2,3,4]
$.trim(str)  移出字符串两端的空格
    $.trim("   hello, how are you?   ")的结果是"hello, how are you?"
                                   :动态效果

       在将这部分之前我们先看个例子,相信做网页的朋友都遇到n级菜单的情景,但点击某菜单按钮时,如果它的子菜单是显示的,则隐藏子菜单,如果子菜单隐藏,则 显示出来,传统的javascript做法是先用getElementById取出子菜单所在容器的id,在判断该容器的style.display是否 等于none,如果等于则设为block,如果不等于这设为none,如果在将效果设置复杂一点,当点击按钮时,不是忽然隐藏和显示子菜单,而是高度平滑 的转变,这时就要通过setTimeout来设置子菜单的height了,再复杂一点透明度也平滑的消失和显现,这时显现下来需要编写很多代码,如果js 基础不好的朋友可能只能从别人写好的代码拿过来修改了!jQuery实现上面效果只需要1句话就行,$("#a").toggle("slow"),,学完jQuery后还需要抄袭修改别人的代码吗?下面我们逐个介绍jQuery用于效果处理的方法。
hide()  隐藏匹配对象

<id="a">Hello Again</p><href="#" onClick=’ ("#a").hide()’>jQuery</a>

当点击连接时,id为a的对象的display变为none。
show() 显示匹配对象
hide(speed)  以一定的速度隐藏匹配对象,其大小(长宽)和透明度都逐渐变化到0,speed有3级("slow", "normal",  "fast"),也可以是自定义的速度。
show(speed)  以一定的速度显示匹配对象,其大小(长宽)和透明度都由0逐渐变化到正常
hide(speed, callback)  show(speed, callback) 当显示和隐藏变化结束后执行函数callback
toggle()    toggle(speed) 如果当前匹配对象隐藏,则显示他们,如果当前是显示的,就隐藏,toggle(speed),其大小(长宽)和透明度都随之逐渐变化。

<img src="1.jpg" style="width:150px"/>
<href="#" onClick='$("img").toggle("slow")'>jQuery</a>

fadeIn(speeds)   fadeOut(speeds)  根据速度调整透明度来显示或隐藏匹配对象,注意有别于hide(speed)和show(speed),fadeIn和fadeOut都只调整透明度,不调整大小

<img src="1.jpg" style="display:none"/><href="#" onClick='$("img ").fadeIn("slow")'> jQuery </a>

点击连接后可以看到图片逐渐显示。
fadeIn(speed, callback)  fadeOut(speed, callback)   callback为函数,先通过调整透明度来显示或隐藏匹配对象,当调整结束后执行callback函数

<img src="1.jpg"/>
<href="#" onClick='$("img ").fadeIn("slow",function(){ alert("Animation Done."); })'> jQuery </a>

点击连接后可以看到图片逐渐显示,显示完全后弹出对话框
fadeTo(speed, opacity, callback)  将匹配对象以speed速度调整倒透明度opacity,然后执行函数callback。Opacity为最终显示的透明度(0-1).

<img src="1.jpg"/><br>
<href="#" onClick='$("img ").fadeTo("slow",0.55,function(){ alert("Animation Done."); })'> jQuery </a>

大家可以看一下自己看看效果,如果不用jQuery,编写原始javascript脚本可能很多代码!
slideDown(speeds)  将匹配对象的高度由0以指定速率平滑的变化到正常!

<img src="1.jpg" style="display:none"/>
<href="#" onClick='$("img ").slideDown("slow")'>jQuery</a>

slideDown(speeds,callback)  将匹配对象的高度由0变化到正常!变化结束后执行函数callback

slideUp("slow")  slideUp(speed, callback) 匹配对象的高度由正常变化到0

slideToggle("slow") 如果匹配对象的高度正常则逐渐变化到0,若为0,则逐渐变化到正常 
 :事件处理

 hover(Function, Function)    当鼠标move over时触发第一个function,当鼠标move out时触发第二个function
样式:<style>.red{color:#FF0000}</style>
Html代码: <div id="a">sdf</div>
jQuery代码及效果

$(function(){
  $(
"#a").hover(function(){$(this).addClass("red");},
                           
function(){ $(this).removeClass("red"); 
                          });
})

最终效果是当鼠标移到id为a的层上时图层增加一个red样式,离开层时移出red样式
toggle(Function, Function)    当匹配元素第一次被点击时触发第一个函数,当第二次被点击时触发第二个函数
样式:<style>.red{color:#FF0000}</style>
Html代码: <div id="a">sdf</div>
jQuery代码及效果

$(function(){
  $(
"#a"). toggle (function(){$(this).addClass("red");},
                             
function(){ $(this).removeClass("red"); 
                            });
})

最终效果是当鼠标点击id为a的层上时图层增加一个red样式,离开层时移出red样式
bind(type, fn)   用户将一个事件和触发事件的方式绑定到匹配对象上。
trigger(type)   用户触发type形式的事件。$("p").trigger("click")
还有:unbind()   unbind(type)    unbind(type, fn)

Dynamic event(Function)    绑定和取消绑定提供函数的简捷方式
例:

$("#a").bind("click",function() { 
                                       $(
this).addClass("red");
})

也可以这样写:

$("#a").click(function() { 
                        $(
this).addClass("red");
});

最终效果是当鼠标点击id为a的层上时图层增加一个red样式,
jQuery提供的函数
用于browers事件
error(fn)    load(fn)     unload(fn)    resize(fn)    scroll(fn)

用于form事件
change(fn)    select(fn)    submit(fn)
用于keyboard事件
keydown(fn)    keypress(fn)    keyup(fn)

用于mouse事件
click(fn)    dblclick(fn)    mousedown(fn)   mousemove(fn)
mouSEOut(fn)  mouSEOver(fn)     mouseup(fn)

用于UI事件
blur(fn)    focus(fn)

以上事件的扩展再扩展为5类
举例,click(fn) 扩展 click()  unclick()  oneclick(fn)  unclick(fn)
click(fn):增加一个点击时触发某函数的事件
click():可以在其他事件中执行匹配对象的click事件。
unclick ():不执行匹配对象的click事件。
oneclick(fn):只增加可以执行一次的click事件。
unclick (fn):增加一个点击时不触发某函数的事件。
上面列举的用于browers、form、keyboard、mouse、UI的事件都可以按以上方法扩展。

                                       :Ajax支持

 通用方式:
$.ajax(prop)    通过一个ajax请求,回去远程数据,prop是一个hash表,它可以传递的key/value有以下几种
         (String)type:数据传递方式(get或post)。
         ((String)url:数据请求页面的url
         ((String)data:传递数据的参数字符串,只适合post方式
         ((String)dataType:期待数据返回的数据格式(例如 "xml", "html", "script",或 "json")
         ((Boolean)ifModified: 当最后一次请求的相应有变化是才成功返回,默认值是false
         ((Number)timeout:设置时间延迟请求的时间。可以参考$.ajaxTimeout
         ((Boolean)global:是否为当前请求触发ajax全局事件,默认为true
         ((Function)error:当请求失败时触发的函数。
         ((Function)success:当请求成功时触发函数
         ((Function)complete:当请求完成后出发函数
jQuery代码及说明

$.ajax({url: "ajax.htm",
          success:
function(msg){ 
                         $(div
"#a").html(msg);
                } 
    });

将ajax.htm返回的内容作为id为a的div内容

$.ajax({ url: "ajax.aspx",
              type:
"get",           
             dataType:
"html",
             data: 
"name=John&location=Boston",
             success:
function(msg){ 
                                 $(
"#a").html(msg);
                              } 
         });

用get方式向ajax.aspx页面传参数,并将返回内容负给id为a的对象。
$.ajaxTimeout(time) 设置请求结束时间
   $.ajaxTimeout( 5000 )
其它简化方式:

$.get(url, params, callback)  用get方式向远程页面传递参数,请求完成后处理函数,除了url外,其它参数任意选择

$.get( "ajax.htm" , function(data){ $("#a").html(data)  })
$.get(   "ajax.asp"
            { name: 
"young", age: "25" },
            function(data){ alert("Data Loaded: " + data); }
        ) 

$.getIfModified(url, params, callback)  用get方式向远程页面传递参数,从最后一次请求后如果数据有变化才作出响应,执行函数callback
$.getJSON(url, params, callback)  用get方式向远程json对象传递参数,请求完成后处理函数callback。
$.getScript(url, callback)  用get方式载入并运行一个远程javascript文件。请求完成后处理函数callback。
$.post(url, params, callback)  用post方式向远程页面传递参数,请求完成后处理函数callback
load(url, params, callback)  载入一个远程文件并载入页面DOM中,并执行函数callback

$("#a").load("ajax.htm"function() { alert("load is done"); } );

仰天一笑 徐羽 向ajax.htm页面发出请求,将返回结果装入id为a的内容中,然后再执行函数callback。
loadIfModified(url, params, callback)  用get方式向远程页面传递参数,从最后一次请求后如果数据有变化才作出响应,将返回结果载入页面DOM中,并执行函数callback
ajaxStart(callback) 当ajax请求发生错误是时执行函数callback
ajaxComplete(callback)  当ajax请求完成时执行函数callback
ajaxError(callback)  当ajax请求发生错误时执行函数callback
ajaxStop(callback)  当ajax请求停止时执行函数callback
ajaxSuccess(callback)  当ajax请求成功时执行函数callback
   
                                       :jQuery插件

     随着jQuery的广泛使用,已经出现了大量jQuery插件,如thickbox,iFX,jQuery-googleMap等,简单的引用这些源文件 就可以方便的使用这些插件。这里我简单的介绍一些网址供大家参考,这些网站头提供了大量的demo,并且使用及其简单,及时E文不好,也能快速掌握!
    http://jquery.com/plugins     官方推荐
    http://interface.eyecon.ro/demos    效果超级棒,使用更简单,一定有你喜欢的!
    http://www.dyve.net/jquery/
    http://bassistance.de/jquery-plugins
   还有其它很多插件,大家可以google以下,如果大家发现好的了,可以留言共享以下!
   
    ——————————————————————————————————————————————
    至此jQuery已经介绍完毕,并合并整理提供给大家 下载 ,更多详细的使用请大家参考官方网站,下面我再推荐一些jQuery的学习网站方便大家更好的掌握这项工具!
    http://keel.sike.googlepages.com/jQuery_getting_started.html     中文入门介绍,Keel翻译
    http://jquery.com/api      jquery提供全部基本方法的介绍及demo,方便大家查询!

[正则表达式]C#常用正则表达式

mikel阅读(758)

“^\d+$” //非负整数(正整数 + 0)
“^[0-9]*[1-9][0-9]*$” //正整数
“^((-\d+)|(0+))$” //非正整数(负整数 + 0)
“^-[0-9]*[1-9][0-9]*$” //负整数
“^-?\d+$” //整数
“^\d+(\.\d+)?$” //非负浮点数(正浮点数 + 0)
“^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$” //正浮点数
“^((-\d+(\.\d+)?)|(0+(\.0+)?))$” //非正浮点数(负浮点数 + 0)
“^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$” //负浮点数
“^(-?\d+)(\.\d+)?$” //浮点数
“^[A-Za-z]+$” //由26个英文字母组成的字符串
“^[A-Z]+$” //由26个英文字母的大写组成的字符串
“^[a-z]+$” //由26个英文字母的小写组成的字符串
“^[A-Za-z0-9]+$” //由数字和26个英文字母组成的字符串
“^\w+$” //由数字、26个英文字母或者下划线组成的字符串
“^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$” //email地址
“^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$” //url
/^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日
/^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
“^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$” //Emil
“(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?” //电话号码
“^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$” //IP地址
YYYY-MM-DD基本上把闰年和2月等的情况都考虑进去了
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$
C#正则表达式
图片 src[^>]*[^/].(?:jpg|bmp|gif)(?:\”|\')
中文 ^([\u4e00-\u9fa5]+|[a-zA-Z0-9]+)$
网址 “\foundAnchor>[^'””>]+?)[^>]*?\>”
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
匹配空行的正则表达式:\n[\s| ]*\r
匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/
匹配首尾空格的正则表达式:(^\s*)|(\s*$)(像vbscript那样的trim函数)
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
—————————————————————————
以下是例子:
利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:onkeyup=”value=value.replace(/[^\u4E00-\u9FA5]/g,'')” onbeforepaste=”clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))”
1.用正则表达式限制只能输入全角字符: onkeyup=”value=value.replace(/[^\uFF00-\uFFFF]/g,'')” onbeforepaste=”clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))”
2.用正则表达式限制只能输入数字:onkeyup=”value=value.replace(/[^\d]/g,'') “onbeforepaste=”clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))”
3.用正则表达式限制只能输入数字和英文:onkeyup=”value=value.replace(/[\W]/g,'') “onbeforepaste=”clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))”
4.计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^\x00-\xff]/g,”aa”).length;}
5.JavaScript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
String.prototype.trim = function()
{
return this.replace(/(^\s*)|(\s*$)/g, “”);
}
利用正则表达式分解和转换IP地址:
6.下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的JavaScript程序:
function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error(“不是一个正确的IP地址!”)
}
}
不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var ip=”10.100.20.168″
ip=ip.split(“.”)
alert(“IP值是:”+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
(?<=>)[^>]*(?=<)

[MVC]构建不带Web窗体的应用

mikel阅读(865)

构建不带 Web 窗体的 Web 应用程序
Chris Tavares
本文基于 ASP.NET MVC Framework 的预发布版本撰写而成。文中的详细信息均可能会有所变更。
本文讨论:

  • 模型视图控制器模式
  • 创建控制器和视图
  • 构建窗体和回发
  • 控制器工厂和其他扩展点
本文使用了以下技术:
ASP.NET

代码下载位置: MVCFramework2008_03.exe (189 KB)
Browse the Code Online

我 从事专业开发迄今为止已有 15 年,在此之前,我利用业余时间从事开发至少也有 10 年了。与我这一代的大多数人一样,我是从 8 位计算机起步,然后转用 PC 平台的。随着计算机的复杂性日益增加,我编写的应用程序涵盖了从小型游戏到个人数据管理再到控制外部硬件的各项功能。
不过,在我职业生涯的前半段,我编写的所有软件都有一个共同点:即,都是运行在用户桌面上的本地应用程序。我最早是在 90 年代初期听说万维网这件新生事物。那时我发现,通过构建 Web 应用程序,可以让我输入我的考勤卡信息而不必再费时费力从工作场所赶回办公室。
一言以蔽之,我感觉很是困惑。我当时满脑子是面向桌面的理念,很难接纳这种无状态的 Web。要添加很多让人头疼的调试、我没有 UNIX 服务器的超级用户访问权限,再加上这个奇怪的角括号,这些因素使年轻时的我止步不前,又重返桌面开发渡过了几年时光。
我远离了 Web 开发领域,虽然这领域显然很重要,但我并没有真正理解其编程模型。然后,Microsoft® .NET Framework 和 ASP.NET 发行了。尽管它与桌面应用程序编程有许多相似之处,但终于有了可以让我从事 Web 应用程序编程的框架。我可以构建窗口(页面),将控件与事件挂钩,而设计器使我不必处理那些讨厌的角括号。最妙的是,ASP.NET 会通过查看状态自动为我处理 Web 的无状态性质!我又重新找回了程序员的快乐 … 至少在一段时间内是如此。
随着经验的增加,我的设计内容也随之丰富。我早已掌握了几种最佳实践,并将其应用到桌面应用程序编程。其中的两种就是:
  • 分离关注点:不要将 UI 逻辑与基础行为混合在一起。
  • 自动单元测试:编写自动测试以验证您的代码是否按预期执行。
这 些是适用于任何技术的基本原则。分离关注点是一项可帮助您处理复杂问题的基本原则。在同一个对象内混合多种责任(如计算剩余的工时、设置数据格式并绘图) 会给维护带来很大的负担。而自动测试对于获得生产质量的代码同时仍保持条理性至关重要,尤其是当您更新现有项目时更是如此。
ASP.NET Web 窗体使入门变得非常简单,但另一方面,要将我的设计理念应用到 Web 应用程序却并非易事。Web 窗体坚持以 UI 为侧重点;其基本单位为页面。首先设计 UI 并拖曳控件。只需将应用程序逻辑融入页面的事件处理程序(与为 Windows® 应用程序启用的 Visual Basic® 非常相似)就万事大吉,这一点非常吸引人。
但 进一步的页面单元测试常常有很大困难。您必须先启动所有 ASP.NET,然后才能在“页面”对象的生命周期内运行该对象。尽管可以通过发送 HTTP请求到服务器或自动化浏览器来测试 Web 应用程序,但这类测试非常脆弱(更换一个控制 ID 测试就会中断)、难以设置(您必须以完全相同的方式在每位开发人员的计算机上设置该服务器)并且运行缓慢。
当 我开始构建更复杂的 Web 应用程序时,Web 窗体提供的抽象概念(如控件、视图状态和页面生命周期)就开始添乱而不是帮忙了。我需要花越来越多的时间来配置数据绑定(并编写大量的事件处理程序对其进 行正确配置)。我不得不想办法缩减视图状态的大小以便更快加载我的页面。Web 窗体要求每个 URL 均存在物理文件,这对于动态站点(例如 wiki)非常困难。而成功编写一个自定义的 WebControl 是一个非常复杂的过程,需要全面了解页面生命周期和 Visual Studio® 设计器。
自从在 Microsoft 工作开始,我就一直与其他人分享关于各种 .NET 难题的体验并希望可以解决一些难题。最近,作为开发人员参加有关模式与实践的 Web 客户端软件工厂项目 (codeplex.com/websf) 时,我遇到了一个这样的机会。特别是,模式与实践交付的内容之一就是自动单元测试。在 Web 客户端软件工厂中,我们建议使用 Model View Presenter (MVP) 模式构建可测试的 Web 窗体。
简 而言之,MVP 并非将您的逻辑放入页面中,而是让您构建自己的页面,页面 (View) 只需调用单独的对象,即 Presenter。Presenter 对象随即执行响应视图上活动必需的任何逻辑,通常通过使用其它对象 (Model) 访问数据库、执行业务逻辑等。一旦这些步骤完成后,Presenter 会更新视图。这种方法提供了可测试性,因为表示器从 ASP.NET 管道中隔离出来;它与视图通过界面进行通信并可脱离页面独立进行测试。
MVP 的这种功能实现有点笨;您需要单独的视图界面,并且您必须在源代码文件中编写许多事件转发函数。但如果您想要在 Web 窗体应用程序中得到可测试的 UI,这差不多是最佳途径。任何改进均需要在基础平台中做出更改。
模型视图控制器模式
幸运的是,ASP.NET 团队听取了象我这样的开发人员的意见,并且已经着手开发一种新的 Web 应用程序框架,该框架与您所熟知并喜爱的 Web 窗体处于同一层级,但采用一组完全不同的设计目标:
  • 使用 HTTP 和 HTML—不隐藏。
  • 可测试性贯穿整个框架之内。
  • 几乎在每个点均可扩展。
  • 对输出进行总体控制。
由 于此新框架基于模型视图控制器 (MVC) 模式,因此其名称为 ASP.NET MVC。MVC 模式最初在 70 年代发明,是 Smalltalk 技术的一部分。正如我将在本文中所展示的,它实际上非常适合 Web 的性质。MVC 将您的 UI 分为三种不同的对象:用于接收和处理输入的控制器;包含您域逻辑的模型;以及用于生成输出的视图。在 Web 环境中,输入为 HTTP 请求,而请求流程与图 1 类似。

Figure 1 MVC 模式请求流程 (单击该图像获得较大视图)
这实际上与 Web 窗体中的过程完全不同。在 Web 窗体模型中,输入进入页面(视图),然后视图负责处理输入并生成输出。而 MVC 中这些责任是分开的。
因 此,您可能立即会产生以下一种想法:“嘿,这太好了。我应该如何使用它?”或“为什么我要编写这些对象,以前只需要编写一个对象?”这两个问题都问得很 好,最好通过示例来进行解释。因此,我将使用 MVC Framework 编写一个小型 Web 应用程序以说明其优点。
创建控制器
要 继续进行,您将需要安装 Visual Studio 2008 并获得 MVC Framework 的副本。在撰写本文时,ASP.NET 扩展的 2007 年 12 月社区技术预览 (CTP) 中已提供了这些内容 (asp.net/downloads/3.5-extensions)。您可能想要获取扩展 CTP 和 MVC 工具包,其中包括一些非常有用的帮助程序对象。一旦下载并安装 CTP 后,您将在“新建项目”对话框中获得名为“ASP.NET MVC Web 应用程序”的新项目类型。
选择“MVC Web 应用程序”项目后,会为您提供一个与常用网站或应用程序稍有不同的解决方案。该解决方案模板会创建一个带有一些新目录的 Web 应用程序(如图 2 中所示)。特别是 Controllers 目录包含各种控制器类,而 Views 目录(及其所有子目录)包含了各种视图。

Figure 2 MVC 项目结构 
我 将会编写一个非常简单的控制器,返回 URL 中传递的名称。右键单击 Controllers 文件夹并选择“添加项目”以显示常用的“添加项目”对话框以及一些新增加的内容,包括 MVC 控制器类和几个 MVC 视图组件。在此例中,我将添加一个非常富有想象力、名为 HelloController 的类:
using System;
using System.Web;
using System.Web.Mvc;
namespace HelloFromMVC.Controllers
{
public class HelloController : Controller
{
[ControllerAction]
public void Index()
{
...
}
}
}
控制器 类比页面简单得多。实际上,唯一真正必需做的就是从 System.Web.Mvc.Controller 中衍生并将 [ControllerAction] 属性置于您的操作方法中。操作是调用以响应特定 URL 请求的一种方法。操作负责执行所需的一切处理,然后呈现一个视图。我将通过编写一个将名称传递到视图的简单操作着手,如下所示:
[ControllerAction]
public void HiThere(string id)
{
ViewData["Name"] = id;
RenderView("HiThere");
}
操作方法会通过 ID 参数从 URL 接收该名称(稍后会介绍方法),将其存储在 ViewData 集合中,然后呈现名为 HiThere 的视图。
在 讨论如何调用此方法,或该视图的显示内容之前,我希望说一说可测试性。还记得我之前关于测试 Web 窗体页面类有多难的评论吗?控制器的测试简单得多。实际上,控制器可以直接实例化,而调用操作方法无需任何附加的基础结构。您不需要 HTTP 上下文,也不需要服务器,只要测试工具即可。作为示例,我在图 3 中为此类包括了 Visual Studio Team System (VSTS) 测试单元。
下 面将进行几项操作。实际的测试相当简单:实例化该控制器,使用预期的数据调用该方法,然后检查呈现的视图是否正确。我通过创建测试专用的子类覆盖 RenderView 方法进行检查。这可以缩短实际创建 HTML 的时间。我只关心是否将正确的数据发送到视图以及是否呈现了正确的视图。我不关心此测试视图本身的底层详细信息。
创建视图
当 然,最终我必须生成一些 HTML,因此,让我们创建该 HiThere 视图。要进行此操作,首先,我将在解决方案中的 Views 文件夹下创建名为 Hello 的新文件夹。默认情况下,控制器将在 Views\<控制器前缀> 文件夹(控制器前缀为控制器类的名称去掉 "Controller" 字样)中查找视图。因此,对于 HelloController 呈现的视图,它会在 Views\Hello 中查找。解决方案的查找结果如图 4 所示。

Figure 4 将视图添加到项目中 (单击该图像获得较大视图)
视图的 HTML 如下所示:
<html  >
<head runat="server">
<title>Hi There!</title>
</head>
<body>
<div>
<h1>Hello, <%= ViewData["Name"] %></h1>
</div>
</body>
</html>
应注意以下几件事。没有 runat="server" 标记。没有 form 标记。没有控件声明。实际上,这看起来更象传统的 ASP 而不是 ASP.NET。请注意,MVC 视图仅负责生成输出,因此其不需要任何 Web 窗体页面所需的事件处理或复杂控件。
MVC Framework 借用了 .aspx 文件格式作为一种有用的文本模板语言。如果需要,甚至可以使用源代码,但默认情况下,源代码文件如下所示:
using System;
using System.Web;
using System.Web.Mvc;
namespace HelloFromMVC.Views.Hello
{
public partial class HiThere : ViewPage
{
}
}
没有页 面初始化或加载方法,没有事件处理程序,除了基类声明以外没有任何内容,基类声明为 ViewPage 而不是 Page。这就是 MVC 视图所需的一切。运行该应用程序,导航至 http://localhost:<端口>/Hello/HiThere/Chris,您将看到如图 5 所示的内容。

Figure 5 成功的 MVC 视图 (单击该图像获得较大视图)
如果您看到的并非如图 5 所示,而是难以理解的意外情况,请不要惊慌。如果您将 HiThere.aspx 文件设置为 Visual Studio 中的活动文档,则当按 F5 后,Visual Studio 将尝试直接访问 .aspx 文件。由于 MVC 视图要求控制器在显示前运行,因此尝试直接导航至该页面将不起作用。只需将该 URL 编辑为与图 5 中所示的内容相匹配,即可正常工作。
MVC Framework 如何知道调用我的操作方法?该 URL 甚至没有文件扩展名。答案是 URL 路由。如果您仔细查看 global.asax.cs 文件,则会看到如图 6 所示的代码段。全局 RouteTable 会存储 Route 对象的集合。每个 Route 说明一个 URL 窗体以及对其进行何种操作。默认情况下,会向该表中添加两个路由。第一个是该方法的内容。它说明每个 URL 在服务器名后均由三部分组成,第一部分应为控制器名,第二部分为操作名称,而第三部分为 ID 参数。
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
// Change Url= to Url="[controller].mvc/[action]/[id]"
// to enable automatic support on IIS6
RouteTable.Routes.Add(new Route
{
Url = "[controller]/[action]/[id]",
Defaults = new { action = "Index", id = (string)null },
RouteHandler = typeof(MvcRouteHandler)
});
RouteTable.Routes.Add(new Route
{
Url = "Default.aspx",
Defaults = new {
controller = "Home",
action = "Index",
id = (string)null },
RouteHandler = typeof(MvcRouteHandler)
});
}
}
Url = "[controller]/[action]/[id]"
此默认 路由是能让我的 HiThere 方法得以调用的路由。请记住此 URL:http://localhost/Hello/HiThere/Chris?此路由将 Hello 与控制器、HiThere 与操作以及 Chris 与 ID 一一对应。MVC Framework 随即创建 HelloController 实例,调用 HiThere 方法,然后将 Chris 作为 ID 参数的值传递。
此默认路由为您提供了许多功能,但您也可以添加自己的路由。例如,我想要一个真正友好的站点,好友们只需输入他们的姓名即可获得个性化的问候。如果我在路由表的顶部添加以下路由
  RouteTable.Routes.Add(new Route
{
Url = "[id]",
Defaults = new {
controller = "Hello",
action = "HiThere" },
RouteHandler = typeof(MvcRouteHandler)
});
随后,我只需访问 ,我的操作仍处于调用状态,而我将会看到熟悉的友好问候。
系 统如何知道调用哪个控制器和操作?答案是 Defaults 参数。它利用新的 C# 3.0 匿名类型语法来创建一个伪词典。Route 上的 Defaults 对象可包含任意附加的信息,对于 MVC,它还可以包含一些众所周知的条目:即控制器和操作。如果 URL 中没有指定控制器或操作,则其将使用 Defaults 中的名称。这就是为什么即使我在 URL 中忽略它们,但仍可以将我的请求映射到正确的控制器和操作。
还 有一件事需要注意:还记得我说过“添加到表格的顶部”吗?如果您将其置于底部,将会出现错误。路由根据先到先得的原则进行工作。当处理 URL 时,路由系统会自上至下浏览表格,并且使用第一个匹配的路由。在本例中,默认路由 "[controller]/[action]/[id]" 匹配,因为它们是操作和 ID 的默认值。这样,它会继续查找 ChrisController,但我没有控制器,因此会出现错误。
稍大的示例
现 在,我已经说明了 MVC Framework 的基础知识,将为您展示一个更大的示例,实现比仅显示字符串更多的功能。wiki 是一种可以在浏览器中进行编辑的网站。可以轻松地添加或编辑页面。我使用 MVC Framework 编写了一个小型的示例 wiki。“编辑此页面”屏幕如图 7 所示。

Figure 7 编辑主页 (单击该图像获得较大视图)
您可以检查本文的代码下载以查看如何实现底层 wiki 逻辑。现在我想重点说明 MVC Framework 如何使 Web 上的 wiki 获取变得简单。让我们先设计 URL 结构。我想要以下各项:
  • /[pagename] 显示该名称的页面。
  • /[pagename]?version=n 显示页面的请求版本,其中 0 = 当前版本,1 = 以前的版本,以此类推。
  • /Edit/[pagename] 打开该页的编辑屏幕。
  • /CreateNewVersion/[pagename] 是为提交编辑而传入的 URL。
让我们从 wiki 页面的基本显示开始。我为它创建了一个名为 WikiPageController 的新类。接下来,我会添加一个名为 ShowPage 的操作。启动的 WikiPageController 如图 8 所示。ShowPage 方法相当简单。WikiSpace 和 WikiPage 类分别表示一组 wiki 页面和特定的页面(及其修订)。此操作只需加载模型并调用 RenderView。但此处的 "new WikiPageViewData" 行是什么意思?
我前面的示例说明了一种将数据从控制器传递到视图的方法:即 ViewData 词典。词典非常方便,但也很危险。它们几乎包含一切内容,您不能获取内容的任何 IntelliSense®,并且由于 ViewData 词典属于 Dictionary<string, object> 类型,它将消耗内容,您必须计算所有一切。
当您了解在视图中将需要什么数据后,就可以传递强类型化的 ViewData 对象。在我的示例中,我创建了一个简单的对象 (WikiPageViewData),如图 9 中所示。此对象将 wiki 页面信息带到视图,同时还携带了一些实用工具方法,执行获取 wiki 标记的 HTML 版本这类任务。
现在,我已经定义了视图数据,那么,我如何使用它呢?在 ShowPage.aspx.cs 中,您将看到以下内容:
namespace MiniWiki.Views.WikiPage {
public partial class ShowPage : ViewPage<WikiPageViewData>
{
}
}
请注意,我将基类类型定义为 ViewPage<WikiPageViewData>。这意味着页面的 ViewData 属性为 WikiPageViewData 类型,而不是象以前示例中的“Dictionary”。
.aspx 文件中的实际标记非常简单:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
AutoEventWireup="true" CodeBehind="ShowPage.aspx.cs"
Inherits="MiniWiki.Views.WikiPage.ShowPage" %>
<asp:Content
ID="Content1"
ContentPlaceHolderID="MainContentPlaceHolder"
runat="server">
<h1><%= ViewData.Name %></h1>
<div id="content" class="wikiContent">
<%= ViewData.HtmlBody %>
</div>
</asp:Content>
请注意,当引用 ViewData 时,我没有使用索引操作符 []。由于我现在有强类型化的 ViewData,我可以直接访问该属性。不需要进行任何计算,而 Visual Studio 会提供 IntelliSense。
目光敏锐的读者将会注意到此文件中的 <asp:Content> 标记。没错,“母版页”确实可以与 MVC 视图配合使用。并且“母版页”还可以成为视图。让我们看看“母版页”的源代码:
namespace MiniWiki.Views.Layouts
{
public partial class Site :
System.Web.Mvc.ViewMasterPage<WikiPageViewData>
{
}
}
相关标记如图 10 中所示。现在,“母版页”将获得与视图完全相同的 ViewData 对象。我已经将“母版页”的基类声明为 ViewMasterPage<WikiPageViewData>,因此,我拥有了正确类型的 ViewData。我会在那里设置各种 DIV 标记以对页面进行布局,填写版本列表,然后以常用内容占位符收尾。
另 一件需要注意的事是对 Html.ActionLink 的调用。以下是呈现帮助程序的一个示例。各种视图类均具有两种属性,Html 和 Url。每种均有输出 HTML 代码块的有用方法。在本例中,Html.ActionLink 获取一个对象(此处为匿名类型)并通过路由系统将其返回。这将会生成一个 URL,该 URL 将路由至我指定的控制器和操作。这样一来,无论我如何更改路由,“编辑此页面”链接将始终指向正确的位置。
您可能还注意到,我还不得不依靠手动构建链接(到先前页面版本的链接)。遗憾的是,当前的路由系统在涉及查询字符串时生成 URL 的功能不是十分完善。这应会在框架的后续版本中得到修复。
创建表单和回发
现在,让我们看看控制器上的 EditPage 操作:
[ControllerAction]
public void EditPage(string pageName)
{
WikiSpace space = new WikiSpace(Repository);
WikiPage page = space.GetPage(pageName);
RenderView("editpage",
new WikiPageViewData {
Name = pageName,
Page = page });
}
同样,该操作所做的不多—它只是呈现指定页面的视图。视图中的内容变得更加有趣,如图 11 中所示。此文件构建了一个 HTML 表单,但没有出现 Runat="server"。Url.Action helper 用于生成表单回发的 URL。其中还使用了几种不同的 HTML 帮助程序(如 TextBox、TextArea 和 SubmitButton)。它们会出色完成您的预期目标:为各种输入字段生成 HTML。
处 理 Web 编程最头疼的事情之一就是表单中的错误。更确切地说,您想要显示错误信息,但同时想要保留原来输入的数据。我们都有过那种经历,在填写一张有 35 个字段的表单时出现一个错误,程序却只是提供一堆错误信息和一张新的空白表单。MVC Framework 使用 TempData 存储以前输入信息,以便可以重新填入表单。这是 ViewState 实际上在 Web 窗体中变得非常简单的原因,因为保存控件的内容几乎是自动的。
我想在 MVC 中如法炮制,因此引入了 TempData。TempData 是一种词典,与非类型化的 ViewData 很相似。不过,TempData 的内容仅针对单一请求存在,随后就会被删除。要了解如何使用此方法,请参阅图 12,NewVersion 操作。
首 先,它创建一个 NewVersionPostData 对象。这是另一个帮助程序对象,具有存储记入的内容和进行某些验证的属性和方法。为加载 postData 对象,我将使用 MVC 工具包的帮助程序。UpdateFrom 实际上是工具包提供的扩展方法,它使用反射将表单字段的名称与我的对象中属性的名称相对映。最终结果是,所有字段值均载入到我的 postData 对象中。不过,UpdateFrom 使用起来确实有缺点,由于它直接从 HttpRequest 获取表单数据,使单元测试变得更为困难。
NewVersion 检查的第一项是 SubmitAction。如果用户单击“确定”按钮并确实想要发布编辑的页面,则此项检查将通过。如果此处有任何其它值,操作会重定向回 ShowPage,只是重新显示原来的页面。
如果用户确实单击了“确定”,则检查 postData.Errors 属性。这将在记入内容上运行一些简单的验证。如果没有任何错误,我会将新版本的页面重新写入 wiki。不过,如果出现错误,情况会变得饶有趣味。
如果出现错误,我会设置 TempData 词典的各个字段,以便其包含 PostData 的内容。然后,我会重定向回“编辑”页面。现在,由于已设置 TempData,页面将重新显示以用户上次记入的值初始化的表单。
处 理记入、验证和 TempData 的这个过程现在变得有些烦琐,并且需要多做一些手动工作。将来发行的版本应包括至少会将一些 TempData 检查自动化的帮助程序方法。关于 TempData 的最后一个注意事项是:TempData 的内容存储在用户的服务器端会话中。如果您关闭会话,TempData 将无法正常工作。
创建控制器
现 在,wiki 的基础已在发挥功效,但继续进行之前,我想要明确实现中的以下几个要点。例如,Repository 属性用于分离 wiki 的逻辑与物理存储。您可以提供在文件系统(正如我所做的那样)、数据库或您想要的任何位置中存储内容的存储库。遗憾的是,我需要解决两个问题。
首先,我的控制器类与具体的 FileBasedSpaceRepository 类紧密地连在一起。我需要一个默认值,以便在属性没有设置时,也能合理使用。更糟的是,磁盘上文件的路径在这里也是硬编码的。最起码,它应取自配置。
其次,我的对象必须依赖存储库,否则无法运行。对于良好的设计,存储库实际应为构造函数参数,而不是属性。但我无法将其添加到构造函数中,因为 MVC Framework 要求控制器上的构造函数不能有参数。
幸 运的是,我可以通过一个扩展性挂接摆脱此限制:即控制器工厂。控制器工厂的功能正如其名称所指:它创建 Controller 实例。您只需要创建一个类实现 IControllerFactory 接口并向 MVC 系统注册即可。您可以为所有控制器或仅为指定的类型注册控制器工厂。图 13 所示为 WikiPageController 的控制器工厂,其现在将存储库作为构造函数参数传递。 在这种情况下,实现非常烦琐,但它可以创建能使用更强大工具(特别是依赖关系注入容器)的控制器。 无论如何,现在我拥有了将控制器依赖关系分离到对象中(易于管理和维护)的所有详细信息。
此工作的最后一步是向框架注册工厂。通过 ControllerBuilder 类可进行此操作,方法是将以下行添加到 Application_Start 方法中的 Global.asax.cs(路由前后均可):
ControllerBuilder.Current.SetControllerFactory(
typeof(WikiPageController), typeof(WiliPageControllerFactory));
这将注 册 WikiPageController 的工厂。如果此项目中有其他控制器,它们不会使用此工厂,因为此工厂仅针对 WikiPageController 类型进行了注册。如果您想要将工厂设置为供所有控制器使用,还可以调用 SetDefaultControllerFactory。
其他扩展点
控 制器工厂只是框架扩展性的起点。本文中无法详述所有的细节,因此我将仅仅说明要点。首先,如果您想要输出的内容不是 HTML,或想要使用其他模板引擎而不是 Web 窗体,可将控制器的 ViewFactory 设为其他项。您可以实现 IviewFactory 界面,然后即可完全控制如何生成输出。这对于生成 RSS、XML 或图形非常有用。
正 如您所见到的,路由系统非常灵活。但路由系统中没有任何内容是 MVC 专用的。每个路由均有一个 RouteHandler 属性;目前为止,我始终将其设为 MvcRouteHandler。但可以实现 IRouteHandler 界面并将路由系统与其他 Web 技术挂接。将来推出的框架将附带 WebFormsRouteHandler,并且其他技术也会在将来利用通用路由系统的优势。
控 制器并非必须从 System.Web.Mvc.Controller 衍生。控制器需要做的仅仅是实现 IController 界面,该界面只有称为 Execute 的一种方法。您可以从中进行任何操作。另一方面,如果您想将 Controller 基类的几种行为组合在一起,您可以覆盖 Controller 的许多虚拟函数:
  • OnPreAction、OnPostAction 和 OnError 可让您将每个已执行操作上的预处理和后处理连接起来。OnError 为您提供在控制器内处理错误的机制。
  • 当 URL 路由到控制器但控制器没有实现路由中请求的操作时,会调用 HandleUnknownAction。默认情况下,此方法会抛出一个异常,但您可以用所需的操作覆盖默认值。
  • InvokeAction 是一种方法,它负责解决调用何种操作方法并进行调用。如果您想要自定义过程(例如,除去 [ControllerAction] 属性的要求),应使用该方法。
还有其他几种针对 Controller 的虚拟方法,但这些方法主要是测试挂接而不是作为扩展点。例如,RedirectToAction 是虚拟的,因此您可以创建实际并不进行重定向的衍生类。这样,您不需要完全运行 Web 服务器就能测试重定向操作。
要告别 Web 窗体吗?
现 在您可能在想:“Web 窗体会面临怎样的命运?MVC 会取代它吗?”答案是否定的!Web 窗体是一种普及技术,Microsoft 将继续支持并改进它。它在许多应用程序中发挥着重要的作用;例如,可使用 Web 窗体创建典型的 Intranet 数据库报表应用程序,所花的时间比使用 MVC 编写短得多。此外,Web 窗体支持大量的控件,许多控件均具备非常先进的功能,可以大大提高效率。
那 么,什么时候应该选择 MVC 呢?这主要取决于您的要求和喜好。您是否正在为获得想要的 URL 格式而烦恼?您是否想要对 UI 进行单元测试?以上情况均需要依靠 MVC。反之,如果您要显示许多数据,提供可编辑的网格和优良的树形视图控件?那么,您暂时最好还是使用 Web 窗体。
今后,MVC Framework 很可能在 UI 控制部分有所改进,但在便利性上,它可能始终不及 Web 窗体,因为后者具备大量拖曳功能。同时,ASP.NET MVC Framework 为 Web 开发人员提供了一种在 Microsoft .NET Framework 中构建 Web 应用程序的新方法。Framework 针对可测试性设计、推倡使用 HTTP 并且几乎在每个点均可扩展。对于那些想要完全控制其 Web 应用程序的开发人员来说,这是一个对 Web 窗体的诱人补充。
Chris Tavares 是 Microsoft 模式和实施方案小组的一名开发人员,他致力于帮助开发社区了解在 Microsoft 平台上构建系统的最佳实践。他还是 ASP.NET MVC 小组的虚拟成员,帮助您设计新的框架。可以通过 cct@tavaresstudios.com 与 Chris 取得联系。

[正则表达式]用正则表达式剔除文本中的HTML标记

mikel阅读(642)

函数虽然简单,但是对处理HTML文档还是很有效的
<%
Function RemoveHTML(strHTML)
Dim objRegExp, Match, Matches
Set objRegExp = New Regexp
objRegExp.IgnoreCase = True
objRegExp.Global = True
'取闭合的<>
objRegExp.Pattern = "<.+?>"
'进行匹配
Set Matches = objRegExp.Execute(strHTML)
' 遍历匹配集合,并替换掉匹配的项目
For Each Match in Matches
strHtml=Replace(strHTML,Match.Value,"")
Next
RemoveHTML=strHTML
Set objRegExp = Nothing
End Function
%>

[MVC].net中“检测到有潜在危险的Request.Form 值”错误解决方法

mikel阅读(651)

由于在.net中,Request时出现有HTML或JavaScript等字符串时,系统会认为是危险性值。立马报错上面的错误。6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
解决办法:6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
解决方案一: 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
在.aspx文件头中加入这句: 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
<%@ Page validateRequest="false"  %> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
解决方案二: 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
修改web.config文件: 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
<configuration> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
  <system.web> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
    <pages validateRequest="false" /> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
  </system.web> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
</configuration> 6jZÁªÉÞ¯‚www.orpai.com&decäs¢?$
因为validateRequest默认值为true。只要设为false即可