[转载][jQuery]使用jQuery.Validate进行客户端验证(高级篇-下)

mikel阅读(989)

[转载][jQuery]使用jQuery.Validate进行客户端验证(高级篇-下)——不使用微软验证控件的理由 – kyo-yo – 博客园.

继续上一篇文章使用jQuery.Validate 进行客户端验证(高级篇-上),本文将继续介绍JQuery.Validate的高级应用——JQuery.Validate的AJAX验证及简 单扩展。

今天主要介绍的内容有:

1、如何使用JQuery.Validate进行AJAX验证?

2、默认jQuery.Validate在进行AJAX验证时返回必须是bool类型,如何返回一个对象包括错误消息及验证结果?

3、在反复使用jQuery.Validate进行AJAX验证时,总是需要编写相关AJAX参数,可否进行进一步封装?

第一点:如何使用jQuery.Validate进行AJAX验证?(具体见High-2.aspx

jQuery.Validate为我们提供了一个方便的AJAX验证方式(封装了jQuery的AJAX,同时将jQuery的AJAX和 jQuery.Validate的验证很好的结合在一起),在此我仅仅介绍jQuery.Validate在ASP.NET下如何进行AJAX验 证,PHP、JSP等请查看官方例子。

我是采用jQuery.Validate+WebService进行AJAX验证,客户端编写jQuery.Validate的remote验证属 性,服务器端采用WebSerice进行接收参数进行验证。

首先来看下jQuery.Validate的remote属性如何编写AJAX验证规则:

01 function InitRules() {
02 opts = {
03 rules:
04 {
05 <%=txtUid.UniqueID %>:
06 {
07 required: true,
08 remote:{
09 type: "POST",
10 async: false,
11 url: "WebService.asmx/CheckUid",
12 dataType: "xml",
13 data: {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}}
14 }
15 }
16 }
17 }
18 }

如果使用过jQuery.ajax的朋友肯定会很熟悉这段代码,jQuery.Validate的remote采用和jQuery.ajax相同的 参数设置(原因就上面所说的封装了jQuery.ajax的原因)。

这边来详细讲解下jQuery.Validate的 remote的一些知识:

1、jQuery.Validate的remote默认可以直接填写远程验证的地址,格式为:remote:”validate.aspx”,但是 很多情况下这个远程验证需要提交参数、返回类型等限制,所以就可以采用在“{}”中编写具体属性的方式来包装提交参数。

2、jQuery.Validate的remote官方代码中,远程的输出只能是true或者false,不允许有其他输出,这个我觉得不太好,具 体的扩展在后面我会讲到

3、jQuery.Validate的remote在使用时如果想提交参数需要以JSON的方式提交格式如下:

1 data: {
2 uid:function(){
3 return jQuery("#<%=txtUid.ClientID %>").val();
4 }
5 }

此处肯定会有人不明白,为什么参数需要以function的形式提交,而不是直接写

jQuery(“#<%=txtUid.ClientID %>”).val();

这里我要说明的是:jQuery.Validate 的验证规则是在页面加载的时候就已经被加载了的,如果还是像以往一样直接写”jQuery(“#<%=txtUid.ClientID %>”).val();”,那么验证的时候提交给服务器端的数据永远是页面加载时txtUid控件的值。

而使用function的好处就是在页面加载的时候 仅仅告诉jQuery.Validate,在控件需要进行remote验证的时候需要调用function这个函数,这样就保证了在执行remote验证 的时候可以获取到最新的值

我还修改了jQuery.Validate的remote方法,先来看下我修改的代码(具体见scripts/jquery.validate1.js 896行):

01 if (previous.old !== value) {
02 previous.old = value;
03 var validator = this;
04 this.startRequest(element);
05 var data = {};
06 data[element.name] = value;
07 $.ajax($.extend(true, {
08 //url:url,//此URL无法获取
09 url: param.url,//获取param验证规则中所写路径
10 mode: "abort",
11 port: "validate" + element.name,
12 type: param.type,
13 dataType: "json",
14 //data:data,
15 data: param.data || data,//获取param.data或data中所提交的参数
16 success: function(response) {
17 以下省略...
18 }

这边我修改了url和data的获取方式,主要是因为在真正执行的时候,变量url是空的,所以需要从param中获取。

而data为什么要改成param.data || data,主要原因就是下面这句代码:

data[element.name] = value;

这句代码的意思就是:为哪个控件设置远程验证就获取哪个控件的值,但是在实际的开发中,当遇到进行AJAX验证的时候会出现需要同时提交多个数据的 情况,此时这句代码就是错误的了,所以需要改成

param.data || data,这样就能保证在提交多个数据的时候以多个数据为准。

下面来看下webservice的代码:

1 [WebMethod]
2 public bool CheckUid(string uid)
3 {
4 return uid == "testuid" ? true : false;
5 }

相当的简单,就是判断下用户名是不是指定的用户名。

注意:webservice.cs中必须将 [System.Web.Script.Services.ScriptService]这个特性取消注释,否则AJAX验证将无效!

第二点:默认jQuery.Validate在进行AJAX验证时返回必须是bool类型,如何返回一个对象包括错误消息及验证结 果?(具体见 App_Code/WebService.cs/CheckUid

在第一点中介绍jQuery.Validate知识的时候就提到了,jQuery.Validate默认直接收true或false,但是在具体的 开发中,我们会分层开发,三层或者多层,webservice在接收到验证请求后不做具体的处理直接调用逻辑层的验证方法,交由逻辑层进行验证操作(当 然你也可以把验证全部写在webservice中,但是这样就体现不出分层的好处了),此时的验证会产生多种情况,以最常见的用户名验 证为例:

1)用户名已存在,此时的消息应该是“用户名已存在,请重新输入!”

2)用户名不符合规则,此时的消息应该是“用户名不符合规则,请重新输入!”

3)验证时出现程序异常,此时的消息应该是“程序出现异常,请联系管理员!”

可以看出,仅仅一个用户名验证就会出现这3种信息,如果不返回一个明确的消息,仅仅告诉用户“用户名有误”,客户端的使用者将会相当的痛苦,因为使 用者并不知道他的用户名输入到底错在哪了。

所以为了更好的客户体验,以及项目的合理性,我们在服务器端封装一个实体类(具体见AppCode/AjaxClass),代码如下:

1 [Serializable]
2 public class AjaxClass
3 {
4 public string Msg { get; set; }
5 public int Result { get; set; }
6 }

就是一个最简单的实体类,有2个属性,Msg和Result,Msg用于存放验证失败的信息,Result用于存放结果。

看下WebSerivce的代码如何修改:

01 [WebMethod]
02 public AjaxClass CheckUid(string uid)
03 {
04 //return uid == "testuid" ? true : false;
05 AjaxClass ajaxClass = new AjaxClass();
06 try
07 {
08 if (uid == "testuid")
09 {
10 ajaxClass.Msg = "用户名已存在,请重新输入!";
11 ajaxClass.Result = 0;
12 }
13 if (uid.IndexOf("test") == -1)
14 {
15 ajaxClass.Msg = "用户名格式不正确,用户名必须包含test,请重新输入!";
16 ajaxClass.Result = 0;
17 }
18 else
19 {
20 ajaxClass.Msg = "格式正确!";
21 ajaxClass.Result = 1;
22 }
23 }
24 catch
25 {
26 ajaxClass.Msg = "程序出现异常,请联系管理员!";
27 ajaxClass.Result = 0;
28 }
29 return ajaxClass;
30 }

上面的WebService就完整的实现了我先前说的3种错误情况(由于这边仅仅是例子所以就只有表示层,实际开发中需要分层开 发,此代码应该放入业务逻辑层

注意:在webservice返回值前,如果检查成 功必须要为ajaxClass.Result = 1,否则客户端验证会无法通过。

虽然完成了服务器端的代码修改,但是直接运行页面还是会出错,这是因为我上面所说过的,jQuery.Validate的remote远程的输出只 能是true或者false,我们来看下具体的代码,其中注释掉的就是原来官方的代码:

01 success: function(response) {
02 if (response.Result) {//if(response){
03 var submitted = validator.formSubmitted;
04 validator.prepareElement(element);
05 validator.formSubmitted = submitted;
06 validator.successList.push(element);
07 validator.showErrors();
08 } else {
09 var errors = {};
10 //errors[element.name] = response.Result || validator.defaultMessage(element, "remote");
11 errors[element.name] = response.Msg;
12 validator.showErrors(errors);
13 }
14 previous.message = response.Msg; //previous.valid = response;
15 previous.valid = response.Result;
16 validator.stopRequest(element, response.Result);
17 }

可以看到一共修改了3处地方:

1、判断返回值,原来是直接判断response,现在则是判断response.Result,因为现在的response已经 是一个包含消息及结果的对象了。

2、错误消息,原来的错误消息是直接获取默认配置好的消息,我这边是获取response.Msg。

3、设置previous对象,将previous对象的消息和结果设置为AJAX返回的消息和结果,以供 jQuery.Validate下面代码的返回。

这样jQuery.Validate的remote的方法就修改了,但是并没有结束,原因是先前在AJAX提交参数的时候由于 jQuery.Validate的验证规则的缘故,提交的参数并不是以JSON的格式提交的而是以{uid:function()}这样的方式,结果就导 致了无法设置jQuery.AJAX的contentType:”application/json; charset=utf-8″,如果设置了会出现以下错误:

pic24这样从webservice返回的AjaxClass对象就无法像以往的JSON方式直接操作 了,所以我们只能换一种格式——XML,因为webservice默认返回的数据是XML格式:

1 <?xml version="1.0" encoding="utf-8" ?>
3 <Msg>用户名格式不正确,用户名必 须包含test,请重新输入!</Msg>
4 <Result>0</Result>
5 </AjaxClass>

接下来看下具体的remote方法应该如何编写,设 置dataType:”xml”,然后将XML数据转换成一个对象以供上面我修改的jQuery.Validate的remote方法中 ajaxsuccess的使用,具体看一下代码:

01 remote:{
02 type: "POST",
03 dataType:"json",
04 async: false,
05 url: "WebService.asmx/CheckUid",
06 data: {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}},
07 dataFilter: function(dataXML) {
08 var result = new Object();
09 result.Result = jQuery(dataXML).find("Result").text();
10 result.Msg = jQuery(dataXML).find("Msg").text();
11 if (result.Result == "-1") {
12 result.Result = false;
13 return result;
14 }
15 else {
16 result.Result = result.Result == "1" ? true : false;
17 return result;
18 }
19 }
20 }

就是jQuery.Ajax方法dataFilter,可以在AJAX请求成功后将数据进行过滤处理,这里我就使用了jQuery方法把结果和消息 从XML中获取出来直接赋给一个对象,再将这个对象返回,交由ajaxsuccess使用。

这样就算是完成了修改jQuery.Validate的remote方法,使得可以返回验证结果及验证消息,看下效果图:

pic25

第三点:在反复使用jQuery.Validate进行AJAX验证时,总是需要编写相关AJAX参数,可否进行进一步封装?(具 体见High-3.aspx和jquery.validate.extension.js)

在开发一个系统的时候经常会用到AJAX的验证,而如果每次都要编写上面那么多的代码还是很不方便,所以我现在就来进行一下简单的封装,代码如下:

01 //远程验证抽象方法
02 function GetRemoteInfo(postUrl, data) {
03 var remote = {
04 type: "POST",
05 async: false,
06 url: postUrl,
07 dataType: "xml",
08 data: data,
09 dataFilter: function(dataXML) {
10 var result = new Object();
11 result.Result = jQuery(dataXML).find("Result").text();
12 result.Msg = jQuery(dataXML).find("Msg").text();
13 if (result.Result == "-1") {
14 result.Result = false;
15 return result;
16 }
17 else {
18 result.Result = result.Result == "1" ? true : false;
19 return result;
20 }
21 }
22 };
23 return remote;
24 }

这个函数主要接收2个参数,一个是远程验证的路径和需要提交的参数,返回包装好的remote对象。

页面调用也很简单,代码如下:

01 <script src="scripts/jquery.validate.extension.js" type="text/JavaScript"></script>
02 <script type="text/JavaScript">
03 function InitRules() {
04 var dataInfo = {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}};
05 var remoteInfo = GetRemoteInfo('WebService.asmx/CheckUid', dataInfo);
06
07 opts = {
08 rules:
09 {
10 <%=txtUid.UniqueID %>:
11 {
12 required: true,
13 remote:remoteInfo
14 }
15 }
16 }
17 }
18 </script>

怎么样?相比上面的代码一下子干净了很多吧?

页面上只要做3步操作:

1、包装好需要提交的data对象。

2、将远程验证地址和包装好的data对象传递给封装好的方法获取remote对象。

3、将函数返回的remote对象放入规则中。

至此使用jQuery.Validate进行客户端验证——不使用微软验证控件的理由这一系列就算全部写完了,大体上将 jQuery.Validate在ASP.NET上的一些常见应用讲了一下,同时也提出了许多我自己修改扩展的东西,希望对正在苦恼客户端验证的朋友有所 帮助,谢谢大家的支持了!

PS:1、其实这一系列并没有把 jQuery.Validate的所有功能介绍完,比如onfocusin,onfocusout,onkeyup等,这些就需要大家在使用的过程中自己 查看源代码实验了。

2、本文有点长,而且内容比较多,如果文中有什么错 误或者有指导意见欢迎大家提出来,谢谢了!

源代码下载:点我下载

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

[转载]ASP.NET MVC实现(查询+分页)

mikel阅读(1096)

[转载]ASP.NET MVC实现(查询+分页) – NSun快速开发 – 博客园.

ASP.NET中我们知道有viewstate这样的页面级容器为我们保存表单数据,这样我们每次提交时数据 都不会丢失,很容易的完成查询+分页的实现找 过相关MVC分 页的例子,都是扩展HtmlHelper方法来实现。我想大家在ASP.NET开发中都用过 wuqiAspNetPager分页 控件以及daceyNSunPage用来开发Winform项目的分页控 件非常方便的满足了大家的分页需求。那么我们来看下在MVC中的查询+分页是怎么实现的。(这里我用到了wuqi的mvcpager)

下面例子是asp.net中的分页查询:

前台代码:

<html>
<body>
<form id=”form1″ runat=”server”>
部门编号:
<asp:TextBox ID=”deptcode” Width=”80px” runat=”server”></asp:TextBox>
部门名称:
<asp:TextBox ID=”deptname” Width=”80px” runat=”server” ></asp:TextBox>
<asp:Button ID=”btnquery” runat=”server” Text=”查询” onclick=” btnquery_Click”/>
<table class=”TableBlock” width=”100%” style=”margin-top: 10px;”>
<tr>
<th>编号</th>
<th>名称</th>
</tr>
<asp:Repeater ID=”TableBlockList” runat=”server”>
<ItemTemplate>
<tr>
<td><%#Eval(code) %></td>
<td><%#Eval(name) %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</form>
</body>
</html>

后台代码:

protected virtual SelectSQLSection GetSelectSearch()
{
SelectSQLSection select
= db.GetSelectSqlSection ();
if (!string.IsNullOrEmpty (deptname.Text))  {
select.Where (View_DeptQueryInfo.__name.Like(deptname.Text
+ %));
}
if(!string.IsNullOrEmpty(deptcode.Text)){
select.Where (View_DeptQueryInfo.__code.Like(deptcode.Text
+ %));
}
return select;
}
protected void BindTable(Repeater rpt, AspNetPager anp)
{
int countPage = 0;
DataTable dt
=db.SelectPageToDataTable(GetSelectSearch (), anp.PageSize, anp.CurrentPageIndex,
out countPage);
anp.RecordCount
= countPage;
rpt.DataSource
= dt;
rpt.DataBind();
}

以上就完成了查询分页的功能,没什么特别的和我们做winform的差不多。第二次查询一样能获得表单内的值。

那么asp.net mvc中怎么实现呢?用什么来保存 表单数据呢?记得原来写java的时候我是用session这样笨拙的方法来保存查询提交后的方法来保存用户查询条件的。那么在asp.net mvc中我们该怎么实现呢?

页面代码:

<html>
<body>
<form id=”form1″ method=”post” action=”/Dept/Dept” runat=”server”>
部门名称:
<input id=”deptname” name=” deptname “ type=”text” value='<%=ViewData [“deptname “] %>‘/>
部门编号:
<input id=”deptcode” name=” deptcode “ type=”text” value='<%=ViewData [“deptcode “] %>‘/>
<input id=”btnquery” type=”submit” value=”查询 “/>
<table class=”TableBlock” width=”100%”>
<tr>
<th>编号</th>
<th>部门名称</th>
</tr>
<asp:MvcRepeater ID=”MvcRepeater1″ Key=”deptlist” runat=”server”>
<ItemTemplate>
<tr>
<td style=”width:5;”><%# Eval(code)%></td>
<td style=”width:10;”><%# Eval(name)%></td>
</tr>
</ItemTemplate>
</asp:MvcRepeater>
</table>
<div class=”pager” style=”width:100%;text-align:right;”>
<div class=”pager” align=”left” style=”float: left; width: 40%;”>
<%=+ ((Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo>)ViewData [deptlist]).TotalPageCount + + ((Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo>)ViewData [deptlist]).TotalItemCount + %></div>
<div align=”right” class=”pager” style=”width: 60%; float: left;”> <%=Html.Pager<DepartmentInfo> ((Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo>)ViewData [deptlist], new PagerOptions() { PageIndexParameterName = id, CurrentPagerItemWrapperFormatString = <span class=\cpb\> {0}</span>, NumericPagerItemWrapperFormatString = <span class=\item\> {0}</span>, CssClass = pages, SeparatorHtml = “”,IsPost=true })%></div>
</div>
</form>
</body>
</html>

首先用到了Repeater,在mvcRepeater的使用需要我们重写一下。如果想用for循环来实现也可以。我们 继承Repeater然后重写OnLoad(EventArgs e) 方法得到Controller中放入ViewData的数据。我们添加一个公开的属性来取得对应ViewDate的值。

Repeater重写:

public string Key { get; set; }
//绑定数据
protected override void OnLoad(EventArgs e)
{
this.DataSource = (base.Page as ViewPage).ViewData[this.Key];

this.DataBind();

base.OnLoad(e);
}

这样就得到我们想要的MVC中的Repeater,因为Repeater必须放在runat=”server”form中所以这里action没 有使用UrlHepler给我们提供的方法来写。

我们把查询条件放入ViewData为了提交后的保存与显示。

<input id=”deptname” name=” deptname “ type=”text” value='<%=ViewData [“deptname“] %>‘/>

后台保存:

public ActionResult Dept (int? id)
{
ViewData [
deptlist] = BindTable(id);
return View();
}
protected Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo> BindTable(int? id)
{
int countPage = 0;
List
<DepartmentInfo> dt = db.SelectPageToList(GetSelectSearch(), 10, id ?? 1, out countPage);
Webdiyer.WebC ontrols.Mvc.PagedList
<DepartmentInfo> p = new Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo>(dt, id ?? 1, 10, countPage);
return p;
}
protected virtual SelectSqlSection GetSelectSearch()
{
SelectSqlSectio n select
= db.GetSelectSqlSection();
select.OrderBy (DepartmentInfo.__ordernumber.Asc);
if (!string.IsNullOrWhiteSpace(Request[deptname]))
{
select.Where(DepartmentInfo.__name.Like(% + GetFormValue(deptname) + %));
}
if (!string.IsNullOrWhiteSpace(Request[deptcode]))
{
select.Where(DepartmentInfo.__code.Like(% + GetFormValue(deptcode) + %));
}
return select;
}
private object GetFormValue(string name)
{
ViewData [name]
= Request[name];
return ViewData[name];
}

这里出现问题了,在查询时候的确可 以获得表单的值,也可以这样保存显示,那么查询后点分页怎么办?分页可是a标签,难道让a标签也提交么?

OK,那么我们就来实现a标签的提交,我们就来给它分页时做提交功能。

因为每次分页都提交表单可能不是各个场景都需要,这里我对 PagerOptions类扩展了2个属性一个是 ispost(分页是否提交,默认是false FormName(提交表单id,这里默认是 asp.net生成的form1)。

再来看怎么生成控件到页面,我们看PagerBuilder类,找到GeneratePagerElement方法,看最后一句String.Format (“<a href='{0}’>{1}</a>”, url, item.Text));默认是生成只带连接的a标签,我们来改造他吧。

我们重新写这个方法名字就叫GeneratePagerElementPost,我们把a 标签的href执行一段脚本,把刚才 那句替换为 String.Format(“<a href=’JavaScript:_PagePostSubmit (\”{0}\”)’>{1}</a>”, url, item.Text));

_PagePostSubmit这 个js方法 就是用来点击a标签进行表单的提交的。那么我们看这个方法是怎么实现和生成到页 面的。找到RenderPager方法,我们拉到方法最 后看到如下代码,这里是添加脚本到客户端。

if (!string.IsNullOrEmpty(pagerScript))

pagerScript = “<script language=\”JavaScript\” type=\”text/JavaScript\”>” + pagerScript + “</script>”;

在这个方面上面添加一下代码:首先我们判断下客户端是否需要每次分页都提交页面,然后加入我们的_PagePostSubmit这个js方法

if (_pagerOptions.IsPost)

{

//通过 _pagerOptions.FormName获得用户选定表单名称,修改其 action,然后提交。

pagerScript += ” function _PagePostSubmit(href){ document.forms[‘” + _pagerOptions.FormName + “‘].action=href;document.forms[‘” + _pagerOptions.FormName + “‘].submit();}”;

}

Ok,这样每个 a标签都能提交表单了,我们在页面添加下面代码就完成了查询+分页的实现

<%=Html.Pager<DepartmentInfo> ((Webdiyer.WebControls.Mvc.PagedList<DepartmentInfo>)ViewData [deptlist], new PagerOptions() { PageIndexParameterName = id, CurrentPagerItemWrapperFormatString = <span class=\cpb\> {0}</span>, NumericPagerItemWrapperFormatString = <span class=\item\> {0}</span>, CssClass = pages, SeparatorHtml = “”,IsPost=true })%>

把刚加的 IsPost属性变为 true,默认FormName=form1这里就没有在赋值了。

实现DEMO:ASP.NET MVC查询+分页 DEMO

修改后的MVCPAGER: ModifyPostMvcPagerSrc

[转载]Memcached 两款.NET客户端的郁闷事儿

mikel阅读(1131)

[转载]Memcached 两款.NET客户端的郁闷事儿 – 汤家大院 – 博客园.

不久以后就要负责一个比较大的项目,有多大?反正就是挺大的。现在处于筹备阶段,我主要负责系统框架搭建,在系统缓存这一块决定采用Http运 行时缓存+memcached。

memcached 以前用过几次 不过也是小打小闹型,尚未正式大型应用过。这次也算是个难得的练手机会吧。memcached服务器打算分布在web应用服务器以及数据库服务器上。

(两台服务器有点花大手笔了 两台Dell PowerEdge R810 自定义了配置 大约单台6.5万)。

关于Memcached的.NET 客户端的选择这一块,主要有两款候选库,Memcached.ClientLibrary(discuz .net版本企业版使用的缓存客户端) 以及 Enyim 。

这两款类库都比较好用,后者使用更加方便,只需简单的配置。我选择了Enyim。

在测试的时候发现了一个共同的问题,假如在使用多个Memcached服务时,当其中一台服务器网络不通(其它至少存在一个可用的 Memcached服务)的情况下,

Memcached.ClientLibrary 的缓存功能失效,Enyim 在缓存操作的时候实例化socket对象时没有进行连接超时的处理(Memcached.ClientLibrary处理了)。

一般都要等待10秒以上线程才能继续,线程被卡住不放了。在以往的应用中都是 memcached 与 web 共存在一台服务器上,所以没遇到过这个问题,

但是这次打算 web 服务器上开一个memcached实例,数据库服务器上开一个memcached实例,所以才关注到了这个问题。一般情况下这个问题也不会有太大影响,

但是心里总是感觉不爽。不打算使用Memcached.ClientLibrary ,所以找了 Enyim 的源代码,打算自己修改一下。

翻看了一下源代码, Enyim 的问题主要存在于 Enyim.Caching.Memcached.PooledSocket,该类主要用于创建socket 连接 。

以下是构造函数

01 internal PooledSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, Action<PooledSocket> cleanupCallback)
02
03 {
04
05 this.endpoint = endpoint;
06
07 this.cleanupCallback = cleanupCallback;
08
09
10
11 this.socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
12
13
14
15 this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, connectionTimeout == TimeSpan.MaxValue ? Timeout.Infinite : (int)connectionTimeout.TotalMilliseconds);
16
17 this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, receiveTimeout == TimeSpan.MaxValue ? Timeout.Infinite : (int)receiveTimeout.TotalMilliseconds);
18
19
20
21 // all operations are "atomic", we do not send small chunks of data
22
23 this.socket.NoDelay = true;
24
25
26
27 this.socket.Connect(endpoint);
28
29 this.inputStream = new BufferedStream(new BasicNetworkStream(this.socket));
30
31 }

由于Socket (我对Socket没啥研究 几乎就是文盲)对象没法设置连接超时之类的属性(这下怎么办呀),并且在源代码中可以看出 this.socket.Connect(endpoint)

的时候没有做任何处理,导致当连接有问题的服务时出现了较长时间的线程等待。我在网上找啊找,找到了类似问题的解决方案,就是使用线程池。

网上找的代码修修改改 差不多能用了,创建了 Enyim.Caching.Memcached.SocketConnector,其中有一个核心的静态方法,用来创建Socket对象,并且运行定义 超时时间。

01 public static Socket GetConnectdSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, int millisecondsTimeout)
02
03 {
04
05 ConnectorState state = new ConnectorState();
06
07 state.Endpoint = endpoint;
08
09 state.ConnectionTimeout = connectionTimeout;
10
11 state.ReceiveTimeout = receiveTimeout;
12
13 ThreadPool.QueueUserWorkItem(new WaitCallback(SocketConnector.ConnectThreaded), state);
14
15 if (state.Completed.WaitOne(millisecondsTimeout, false))
16
17 {
18
19 if (state.Socket == null)
20
21 {
22
23 throw state.Exception;
24
25 }
26
27 return state.Socket;
28
29 }
30
31 state.Abort();
32
33 throw new SocketException(0x2af9);
34
35 }

然后修改PooledSocket的构造为:

01 internal PooledSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, Action<PooledSocket> cleanupCallback)
02
03 {
04
05 this.endpoint = endpoint;
06
07 this.cleanupCallback = cleanupCallback;
08
09 this.socket = SocketConnector.GetConnectdSocket(endpoint, connectionTimeout, receiveTimeout, 100);
10
11 this.inputStream = new BufferedStream(new BasicNetworkStream(this.socket));
12
13 }

我将连接超时设置为100毫秒,那个恶心的问题基本算是解决了。

[转载]asp.net mvc 2 简简单单做开发 实现基本数据操作操作RepositoryController

mikel阅读(756)

[转载]asp.net mvc 2 简简单单做开发 实现基本数据操作操作RepositoryController – 飞创cms – 博客园.

ASP.NET mvc 2 使用Linq to SQL 来操作数据库,基本实现面向对象编程,同样在操作数据是我们也可以使用面向对象的继承再加上泛型,是操作更加简单。代码简单,不详细说明,里面用到几个简 单的扩展方法,以后会详细介绍。如db.find<T>(t),db.findkey<T>(id)。这是对dbcontent 做了些扩展。

RepositoryController.cs 代码如下:

1 public class RepositoryController<T>: BaseController where T : class,new()
2 {
3 private Table<T> list()
4 {
5 return db.GetTable<T>();
6 }
7
8
9 public string orderby = Id desc;
10 public virtual ActionResult Index(T art)
11 {
12 ViewData[searchModel] = art;
13 var Model = db.Find<T>(art);
14 RecordCount = Model.Count();
15 Model=Model.OrderBy(orderby);
16
17 Model = Model.Skip((CurPage 1) * PageSize).Take(PageSize);
18
19 GetPager();
20 return View(index, Model);
21 }
22 [ValidateInput(false)]
23 public virtual ActionResult Add()
24 {
25
26 return View(new T());
27 }
28 [HttpPost]
29 [ValidateInput(false)]
30 public virtual ActionResult Add(T Model)
31 {
32 if (ModelState.IsValid)
33 {
34 try
35 {
36 list().InsertOnSubmit(Model);
37 db.SubmitChanges();
38 return RedirectToAction(index);
39 }
40 catch
41 {
42 return View(Model);
43 }
44 }
45 else
46 return View(Model);
47 }
48 [ValidateInput(false)]
49 public virtual ActionResult Edit(int id)
50 {
51 return View(db.FindKey<T>(id));
52 }
53 [HttpPost]
54 [ValidateInput(false)]
55 public virtual ActionResult Edit(int id, T Model)
56 {
57 try
58 {
59 var cate = db.FindKey<T>(id);
60 UpdateModel(cate);
61 db.SubmitChanges();
62 return RedirectToAction(index);
63 }
64 catch
65 {
66 return View(Model);
67 }
68 }
69 public virtual ActionResult Delete(int id)
70 {
71 list().DeleteOnSubmit(db.FindKey<T>(id));
72 db.SubmitChanges();
73 return RedirectToAction(index);
74 }
75
76
77 }
————————————————————————————
作者:王继坤
出处:http://www.wjk3.cn/
本文版权归作者和博客园共有,欢迎转 载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]javascript闭包

mikel阅读(977)

[转载]javascript闭包 – zhangle – 博客园.

官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点:
1.作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2.一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
简单的说,JavaScript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数 中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

function closure(){
var str = I’m a part variable.;
return function(){
alert(str);
}
}
var fObj = closure();
fObj();

在上面代码中,str是定义在函数closure中局部变量,若strclosure函数调用完成以后不能再被访问,则在函数执行完成后str将被释放。但是由于函数closure返回了一个内部函数,且这个返回的函数引用了str变 量,导致了str可能会在closure函数执行完成以后还会被引用,所以str所 占用的资源不会被回收。这样closure就形成了一个闭包。

事实上,当我们给自定 义的JavaScript类中的私有变量添加get/set函数时,已经用到了闭包。

function Class1(){
var vari;
this.getVari = function(){return vari;}
this.setVari = function(_vari){vari = _vari;}
}
var cls = new Class1();
cls.setVari(
test variable);
alert(cls.getVari());

在这个例子中,构造器中定义了变量vari,构造器执行结束后如果vari没有被其他外部能够应用的成员方法所引用时,这个变量将被回收。但 是我们给它定义了get/set函数以后,由于这两个内部函数可以被包含他们的函数Class1(类)的外部所访问,且变量vari被这两个函数所引用, 因此vari不会被回收。这样就形成了闭包。

JavaScript垃圾回收的原则是:如果一个对象不再被引用,那么这个对象会被垃圾 回收器回收。如果两个对象无干扰的互相引用,那么这两个对象也会被回收。

闭包在javascript编程中有重要的作用,如果使用恰当,可以为某些问题的解决带 来很多方便。但是如果使用不恰当,也会带来很多麻烦。

1.为执行的函数提供参数。
setTimeout可以延迟执行某个函数,原型如下: setTimeout(code,millisec)。其中第一个参数为需要执行的函数或者代码,第二个参数是延迟的毫秒数。常见用法:

function sayHello(){
alert(
hello world);
}
setTimeout(sayHello,
1000);

但是可能我们会需要一个通用一些的函数,而不仅仅是只会说“hello world”。我们写一个say()函数,给say传递一个需要说的内容的参数。但是在setTimeout中我们无法给需要延迟执行的函数传递参数。使 用闭包,我们可以这样做:

function say(words){
return function(){
alert(words)
}
}
setTimeout(say(
hello word),1000);
setTimeout(say(
I’m hungry,I’m need some food!),2000);

这样可以在调用setTimeout时给需要延迟执行的函数传递参数了。

2.将对象的方法与其他实例关联

比如我们在做一个多文件上传的程序,要求可以动态添加和删除文件:

function addFile(){
var fileInput = document.createElement(input);
fileInput.type
= file;
fileInput.name
= file;

var btnDel = document.createElement(input);
btnDel.type
= button;
btnDel.value
= 删 除;

btnDel.onclick = (function(){
//删除文件
return function(){
var c = _(fileContent);
c.removeChild(fileInput);
c.removeChild(btnDel);
}
})();

var fContent = _(fileContent)
fContent.appendChild(fileInput);
fContent.appendChild(btnDel);
}

在这个例子中,我们在删除按钮的点击时间关联的函数中删除对应的上传表单和按钮本身。由于表单和按钮都是动态生成,在事先并不知道删除按钮点击 后需要删除的内容是什么。但是我们可以使用javascript闭包的特性,在上传表单和按钮生成的时候将按钮的点击事件与上传表单实例及和按钮实例进行 关联。

3.模拟静态私有变量

Javascript本身并不支持面向对象的特性。但是我们可以通过 javascript的一些特性模拟实现javascript面向对象。
比如我们需要定义一个类,并且模拟静态私有变量。

var Class2 = (function(){
var s_var = 0; //静态私有变量
return function(){
this.getInstanceCount = function(){
return s_var;
}
//constructor
s_var++;
}
})()

var cls1 = new Class2();
alert(cls1.getInstanceCount());
//1

var cls2 = new Class2();
alert(cls1.getInstanceCount());
//2
alert(cls2.getInstanceCount()); //2

var cls3 = new Class2();
alert(cls1.getInstanceCount());
//3
alert(cls3.getInstanceCount()); //3

在这个例子中,我们用s_var记录Class2被实例化的次数,使用闭包,我们可以将s_var模拟为一个静态私有变量,每次Class2被实例化的时 候将s_var加1。

上例中我们使用了这样形式的一段代码,其中定义在外层函数内,内层函数外的成员类似于静 态成员。所以这样形式的代码我们可以把他叫做“静态封装环境”。

(function(){
return function(){
}
}
})()

参考文章地址:

http://baike.baidu.com/view/648413.htm
http://www.cnblogs.com/yangjian/archive/2009/09/24/1573176.html
http://www.cnblogs.com/chongzi/
http://www.360doc.com/content/09/1227/11/370235_12087397.shtml
http://softbbs.pconline.com.cn/9497825.html

[转载]asp.net mvc 2 简简单单做开发 自定义DropdownList控件

mikel阅读(878)

[转载]asp.net mvc 2 简简单单做开发 自定义DropdownList控件 – 飞创cms – 博客园.

ASP.NET mvc 2 给我们提供了强大的自定义功能,今天主要说下DropdownList自定义绑定字段显示,通过ViewData设定DropdownList的数据项。 自动绑定显示。实现的方式。在global.asax 中注册 FieldTemplateMetadataProvider,

ModelMetadataProviders.Current = new mvc.Models.FieldTemplateMetadataProvider();
通过返回的 FieldTemplateMetadata 。在MetaData中指定使用DropDownList的字段
[Display( Name=“”,Order=12)]
[Required]
[SearchFilter]
[DisplayName(“栏目”)]
[DropDownList(“Category”“Id”“Name”)]
public int Cid { getset; }

通过DropDownList指定 调用的模板为dropdownlist.ascx ,在dropdownlist.ascx 将默认的 ModelMetadata 转成FieldTemplateMetadata 获取 DropDownListAttribute 。

<script runat="server">
    DropDownListAttribute GetDropDownListAttribute()
    {
        FieldTemplateMetadata metaData = ViewData.ModelMetadata as FieldTemplateMetadata;
 
        return (metaData != null) ? metaData.Attributes.OfType<DropDownListAttribute>().SingleOrDefault() : null;
    }
</script>
 
  通过DropDownListAttribute 获得 ViewData的key ,绑定的文本对应的字段,值对应的字段,使用html.DropDownlist显示数据

DropdownList.ascx 代码

代码

<%@ Import Namespace=mvc.Models%>
<%@ Control Language=C# Inherits=System.Web.Mvc.ViewUserControl %>
<script runat=server>
DropDownListAttribute GetDropDownListAttribute()
{
FieldTemplateMetadata metaData
= ViewData.ModelMetadata as FieldTemplateMetadata;

return (metaData != null) ? metaData.Attributes.OfType<DropDownListAttribute>().SingleOrDefault() : null;
}
</script>
<% DropDownListAttribute attribute = GetDropDownListAttribute();%>
<% if (attribute != null) {%>
<%= Html.DropDownList(string.Empty, new SelectList(ViewData[attribute.ViewDataKey] as IEnumerable, attribute.DataValueField, attribute.DataTextField, Model), attribute.OptionLabel, attribute.HtmlAttributes) %>
<% }%>
<% else {%>
<%= Html.DisplayForModel() %>
<% }%>

自定义DropDownListAttribute 属性

代码

namespace mvc.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Routing;

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class DropDownListAttribute : Attribute, ITemplateField
{
private static string defaultTemplateName;

public DropDownListAttribute(string viewDataKey, string dataValueField) : this(viewDataKey, dataValueField, null)
{
}

public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField) : this(viewDataKey, dataValueField, dataTextField, null)
{
}

public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField, string optionLabel) : this(DefaultTemplateName, viewDataKey, dataValueField, dataTextField, optionLabel, null)
{
}

public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField, string optionLabel, object htmlAttributes) : this(DefaultTemplateName, viewDataKey, dataValueField, dataTextField, optionLabel, htmlAttributes)
{
}

public DropDownListAttribute(string templateName, string viewDataKey, string dataValueField, string dataTextField, string optionLabel, object htmlAttributes)
{
if (string.IsNullOrEmpty(templateName))
{
throw new ArgumentException(Template name cannot be empty.);
}

if (string.IsNullOrEmpty(viewDataKey))
{
throw new ArgumentException(View data key cannot be empty.);
}

if (string.IsNullOrEmpty(dataValueField))
{
throw new ArgumentException(Data value field cannot be empty.);
}

TemplateName = templateName;
ViewDataKey
= viewDataKey;
DataValueField
= dataValueField;
DataTextField
= dataTextField;
OptionLabel
= optionLabel;
HtmlAttributes
= new RouteValueDictionary(htmlAttributes);
}

public static string DefaultTemplateName
{
get
{
if (string.IsNullOrEmpty(defaultTemplateName))
{
defaultTemplateName
= DropDownList;
}

return defaultTemplateName;
}
set
{
defaultTemplateName
= value;
}
}

public string TemplateName { get; private set; }

public string ViewDataKey { get; private set; }

public string DataValueField { get; private set; }

public string DataTextField { get; private set; }

public string OptionLabel { get; private set; }

public IDictionary<string, object> HtmlAttributes { get; private set; }

public object GetSelectedValue(object model)
{
return GetPropertyValue(model, DataValueField);
}

public object GetSelectedText(object model)
{
return GetPropertyValue(model, !string.IsNullOrEmpty(DataTextField) ? DataTextField : DataValueField);
}

private static object GetPropertyValue(object model, string propertyName)
{
if (model != null)
{
PropertyDescriptor property
= GetTypeDescriptor(model.GetType()).GetProperties()
.Cast
<PropertyDescriptor>()
.SingleOrDefault(p
=> string.Compare(p.Name, propertyName, StringComparison.OrdinalIgnoreCase) == 0);

if (property != null)
{
return property.GetValue(model);
}
}

return null;
}

private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
{
return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
}
}
}

自定义DataAnnotationsModelMetadata

代码

public class FieldTemplateMetadata : DataAnnotationsModelMetadata
{
public FieldTemplateMetadata(DisplayAttribute aa, DataAnnotationsModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName, DisplayColumnAttribute displayColumnAttribute, IEnumerable<Attribute> attributes) : base(provider, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute)
{
Attributes
= new List<Attribute>(attributes);
Display
= aa;
}

public IList<Attribute> Attributes
{
get;
private set;
}
public DisplayAttribute Display { get; set; }
}

自定义 DataAnnotationsModelMetadataProvider

代码

public class FieldTemplateMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
DataAnnotationsModelMetadata result
= (DataAnnotationsModelMetadata) base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

string templateName = attributes.OfType<ITemplateField>()
.Select(field
=> field.TemplateName)
.LastOrDefault();
List
<System.Attribute> attributeList = new List<System.Attribute>(attributes);
DisplayAttribute disp
= attributeList.OfType<DisplayAttribute>().FirstOrDefault();
if (disp != null)
{
result.ShortDisplayName
= disp.Order.ToString(); ;
result.Description
= disp.Description;
}

var data= (new FieldTemplateMetadata(disp, this, containerType, modelAccessor, modelType, propertyName, attributes.OfType<DisplayColumnAttribute>().FirstOrDefault(), attributes)

{
TemplateHint = !string.IsNullOrEmpty(templateName) ? templateName : result.TemplateHint,
HideSurroundingHtml
= result.HideSurroundingHtml,
DataTypeName
= result.DataTypeName,
IsReadOnly
= result.IsReadOnly,
NullDisplayText
= result.NullDisplayText,
DisplayFormatString
= result.DisplayFormatString,
ConvertEmptyStringToNull
= result.ConvertEmptyStringToNull,
EditFormatString
= result.EditFormatString,
ShowForDisplay
= result.ShowForDisplay,
ShowForEdit
= result.ShowForEdit,
DisplayName
= result.DisplayName,
Description
= result.Description,
ShortDisplayName
= result.ShortDisplayName,

});

SearchFilterAttribute searchFilterAttribute = attributes.OfType<SearchFilterAttribute>().FirstOrDefault();
if (searchFilterAttribute != null)
{
data.AdditionalValues.Add(
Search, searchFilterAttribute);
}

OrderByAttribute orderByAttribute = attributes.OfType<OrderByAttribute>().FirstOrDefault();
if (orderByAttribute != null)
{
data.AdditionalValues.Add(
OrderBy, orderByAttribute);
}
return data;
}
}

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

[转载]asp.net mvc 2 简简单单做开发 自定义Controller基类

mikel阅读(1090)

[转载]asp.net mvc 2 简简单单做开发 自定义Controller基类 – 飞创cms – 博客园.

以前使用ASP.NET时总是自定义一个基类来继承Page类,来实现一些页面中常用的操作来减少代码。ASP.NET mvc 2 里没有分页功能,就在基类里实现分页的功能吧,在页面中定义分页常用的变量,如 RecordCount、PageSize、CurPage等。通过GetPager() 把分页字符串赋给ViewData[“Page”],view页面中直接输出ViewData[“page”]。

实例代码 BaseController.cs

1 public class BaseController : Controller
2 {
3 //linq数据操作类db
4 public DB db = new DB();
5 public int RecordCount = 0;
6 public int PageSize = 10;
7
8 public int CurPage
9 {
10 get
11 {
12 return DNTRequest.GetInt(page, 1);
13 }
14 }
15 public void GetPager()
16 {
17 int PageCount = (int)Math.Ceiling(RecordCount/ ((double)PageSize));
18 ViewData[Page] = Utils.GetPageNumbers(CurPage, PageCount, GetUrl(), 5);
19 }
20 public string GetUrl()
21 {
22 string url = Request.Url.ToString();
23 url = url.Substring(url.LastIndexOf(/) + 1);
24
25 Regex reg = new Regex(@”&page=([0-9]+), RegexOptions.IgnoreCase);
26 Match m = reg.Match(url);
27 if (m.Success)
28 {
29 url = url.Replace(m.Groups[0].Value, “”);
30 }
31 reg = new Regex(@”\?page=([0-9]+), RegexOptions.IgnoreCase);
32 m = reg.Match(url);
33 if (m.Success)
34 {
35 url = url.Replace(m.Groups[0].Value, ?1=1);
36 }
37 return url;
38 }
39 }

ArticleController.cs

代码

public class ArticleController : BaseController
{
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
var cate
=db.Category.ToList();
cate.Insert(
0,new Category() {Id=0, Name=未设置});
ViewData[
category] = cate;
base.OnResultExecuting(filterContext);

}

public ActionResult Index(Article art)
{

ViewData[searchModel] = art;
var article
= db.Find<Article>(art);
var list
= db.Article.Where(d =>d.title.Contains(22));
RecordCount
= article.Count();
article
= article.Skip((CurPage 1) * PageSize).Take(PageSize);
GetPager();
return View(index, article);
}

//public ActionResult Index()
//{
// ViewData[“searchModel”] = new Article();
// var article = from d in db.Article
// select d;
// RecordCount = article.Count();

// article = article.Skip((CurPage-1)*PageSize).Take(PageSize);
// GetPager();
// return View(“index”,article);

//}
public ActionResult Add()
{
Article art
= new Article();
art.CreateTime
= DateTime.Now;
return View(art);
}
[HttpPost]
[ValidateInput(
false)]
public ActionResult Add(Article art)
{
try
{
if (this.ModelState.IsValid)
{
db.Article.InsertOnSubmit(art);
db.SubmitChanges();
return RedirectToAction(index);
}
else
{
return View(art);
}
}
catch(Exception e)
{
return Content(e.Message);
}

}
public ActionResult Edit(int id)
{
return View(db.Article.FirstOrDefault(d=>d.Id==id));
}
[HttpPost]
[ValidateInput(
false)]
public ActionResult Edit(int id,Article art1)
{
try
{
Article art
=db.Article.FirstOrDefault(d=>d.Id==id);
UpdateModel(art);
db.SubmitChanges();
return this.RedirectToAction(index);
}
catch
{
return View(art1);
}
}
public ActionResult Delete(int id)
{
db.Article.DeleteOnSubmit(db.Article.FirstOrDefault(d
=> d.Id == id));
db.SubmitChanges();
return RedirectToAction(index);
}

}

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

——–

[转载]asp.net mvc 2 简简单单做开发 通用增删改基本操作通用页面

mikel阅读(865)

[转载]asp.net mvc 2 简简单单做开发 通用增删改基本操作通用页面 – 飞创cms – 博客园.

ASP.NET mvc 2能使我们重复的工作中解脱出来,增删改等基本数据操作,都可以简单的实现。ASP.NET mvc 2 也借鉴不少ASP.NET Dynamic Data里的功能,通过实体类,只需要简单的操作即可以生成网站。我个人感觉,看似简单不过真正的用到开发中会遇到很多问题。自定义性太差。而 ASP.NET MVC 2里提供了很好的方式,页面的实现可以通过,自定义字段、自定义页面来实现。mvc 2 view的查找方式  “~/Views/{1}/{0}.aspx”, “~/Views/{1}{0}.ascx”,“~/Views/Shared/{0}.aspx”, “~/Views/Shared/{0}.ascx” ,把通用的页面放到”~/Views/Shared 文件下 。为了通用实体类采 dynamic来自动实现。 下面是 Index的代码,默认支持自定义查询,数据分页等基本功能。

1 <%@ Page Title=“” Language=C# MasterPageFile=~/Views/Shared/Admin.Master Inherits=System.Web.Mvc.ViewPage<dynamic> %>
2 <%@ Import Namespace=mvc.Models %>
3 <asp:Content ID=Content1 ContentPlaceHolderID=TitleContent runat=server>
4 Index
5 </asp:Content>
6
7 <asp:Content ID=Content2 ContentPlaceHolderID=MainContent runat=server>
8 <div id=headImg>
9 <img src=/content/adminimages/01.gif alt=“” /><%:ViewData[NavTitle]%>
10 </div>
11 <div id=cont2>
12 <div class=form clearfix>
13
14 <form id=form1 method=get>
15 <div id=Search class=clearfix>
16 <%=Html.DisplayFor(m => ViewData[searchModel], tool,“”)%>
17
18 <li class=add>
19 <%: Html.ActionLink(添加, Add) %>
20 </li>
21 </div>
22 </form>
23 <table class=tb>
24 <% int i = 0; foreach (var art in Model)
25 {
26 i++;
27 if (i == 1)
28 {
29 %>
30 <tr class=tbhead>
31 <%=Html.DisplayFor(m => art, header, di)%>
32
33 <th>操作</th>
34 </tr>
35 <%} %>
36 <tr>
37 <%=Html.DisplayFor(m => art, rows, di)%>
38 <td style=width:60px>
39 <%: Html.ActionLink(编辑, Edit, new { id = art.Id })%> <%: Html.ActionLink(删除, Delete, new { id = art.Id }, new { onclick = return confirm(‘你确定要删除 吗?’) })%>
40 </td>
41 </tr>
42 <%} %>
43 </table>
44
45 <div class=page>
46 <%=ViewData[page] %>
47 </div>
48 </div>
49 </div>
50 </asp:Content>
51

编辑页面Edit.aspx

代码

<%@ Page Title=“” Language=C# MasterPageFile=~/Views/Shared/Admin.Master Inherits=System.Web.Mvc.ViewPage<dynamic> %>

<asp:Content ID=Content1 ContentPlaceHolderID=TitleContent runat=server>
Edit
</asp:Content>

<asp:Content ID=Content2 ContentPlaceHolderID=MainContent runat=server>
<%Html.EnableClientValidation(); %>
<div id=headImg>
<img src=/content/adminimages/01.gif alt=“” /><%:ViewData[NavTitle]%>
</div>
<div id=cont2>
<div class=form clearfix>
<div>
<%: Html.ActionLink(返回列表, Index) %>
</div>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>

<%=Html.EditorForModel() %>
<p class=submit style=margin-left:100px;>
<input type=submit value=保存 />
</p>

<% } %>

</div>
</div>
</asp:Content>

添加记录页面Add.aspx

代码

<%@ Page Title=“” Language=C# MasterPageFile=~/Views/Shared/Admin.Master Inherits=System.Web.Mvc.ViewPage<dynamic> %>

<asp:Content ID=Content1 ContentPlaceHolderID=TitleContent runat=server>
Add
</asp:Content>

<asp:Content ID=Content2 ContentPlaceHolderID=MainContent runat=server>
<%Html.EnableClientValidation(); %>

<div id=headImg>
<img src=/content/adminimages/01.gif alt=“” /><%:ViewData[NavTitle]%>
</div>
<div id=cont2>
<div class=form clearfix>
<div>
<%: Html.ActionLink(返回列表, Index) %>
</div>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>

<%=Html.EditorForModel() %>
<p class=submit style=margin-left:100px;>
<input type=submit value=保存 />
</p>

<% } %>

</div>
</div>

</asp:Content>

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

————————————————————————

[转载][jQuery]使用jQuery.Validate进行客户端验证(中级篇-下)

mikel阅读(1031)

[转载][jQuery]使用jQuery.Validate进行客户端验证(中级篇-下)——不使用微软验证控件的理由 – kyo-yo – 博客园.

在上一篇文章使用jQuery.Validate 进行客户端验证(中级篇-上)中我介绍了JQuery.Validate的3种验证方式,今天这篇中级-下则是在上一篇的基础上继续介绍 JQuery.Validate的一些常用的验证使用方法。

今天主要以使用JQuery.Validate后会遇到的问题为介绍内容,主要介绍以下几点:

1、在使用上一篇中第2种方式,以JSON的格式编写验证规则,影响了正常的class使用,如何处理?

2、在ASP.NET下,所有的按钮都会提交form表单,所以都会引发验证,如何处理?

3、我希望验证的提示信息可以在统一的地方显示,如何处理?

4、我在开发的过程中,我不确定所编写的规则是否正确,如何进行调试?

5、我使用的是微软AJAX控件,想监控dropdownlist是否选择,为何不起作用?

6、radiobox,checkbox,listbox如何进行高级应用?如何指定选择数量?

来看下第1点:在使用上一篇中第2种方式,以 JSON的格式编写验证规则,影响了正常的class使用,如何处理?具体见Middle- 4.aspx

首先看下使用第2种方式是如何编写验证规则的:

<asp:TextBox ID=”txtPwd” TextMode=”Password” runat=”server” CssClass=”{required:true,minlength:6,messages:{required:’你不输入密码怎么行 呢?’,minlength:’密码太短啦至少6位’}}”></asp:TextBox>

可以看到这样写验证规则虽然简单,但是如果我要为这个控件应用其他样式怎么办?所以现在就是处理这个问题的时候了,在页面的头部加上一句代码:

jQuery.metadata.setType(“attr”, “validate”);

由于这种验证规则方式需要依赖jQuery.metadata才可以正常运作,所以我们需要在jQuery.metadata上做文章,分析下 jQuery.metadata的代码,可以看到,默认情况下它是检测控件的class属性:

defaults : {
type: ‘class’,
name: ‘metadata’,
cre: /({.*})/,
single: ‘metadata’
}

那我们可不可以更改这个属性呢?肯定是可以的,就是在页面上加上那句代码,更改其检测的属性。

接着我们还需要修改下页面中的代码,将原来所有的”CssClass”改为我们更改的检测属性”validate”、

这样就很好的更改了验证规则所存放的属性了。

第2点:ASP.NET下,所有的按钮都会提交 form表单,所以都会引发验证,如何处理?(具体见Middle-4.aspx中 btnNoValidate按钮

在实际的开发当中,一个页面上总会有N个按钮,由于ASP.NET的机制特性,所有的控件都会回发页面,也就提交了表单,但是此时整个表单都被 jQuery.Validate所监控,所以只要页面中有某个地方不符合验证规则,任何回发页面的操作都会被拦截住,但是实际上我们需要引发验证的按钮只 有1或者2个,而其他按钮不需要,这时我们就要想办法了。

其实很简单,就是为不需要引发验证的控件加个样式”cancel”即可,代码如下:

<asp:Button ID=”btnNoValidate” runat=”server” Text=”点我不会引发验证哦” CssClass=”cancel” />

怎么样很简单吧?

第3点:我希望验证的提示信息可以在统一的地方显 示,如何处理?(具体见Middle-5.aspx

在开发的过程当中,会有一些特殊的需求,就比如页面上使用了tab页面,而提交按钮就一个,这时就需要将验证提示信息统一放在一个位置,好方便查 看,如图:

pic21

要实现这个效果只需在JS编写验证规则时添加:

errorPlacement: function(error, element) {
error.html(error.html()+”<br/>”);
error.appendTo(“#errorContainer”);
}

error是一个label对象里面包含了错误消息,element则是验证未通过的对象元素,通过errorPlacement可以方便的将验证 提示信息统一放入一个位置。

第4点:我在开发的过程中,我不确定所编写的规则是 否正确,如何进行调试?(具体见Middle-5.aspx

这个就比较简单了,jQuery.Validate默认已经为我们考虑过了,只需在JS编写规则时添加一个属性:

Debug:true

这样就表示现在在调试,这时不会提交表单。

第5点:我使用的是微软AJAX控件,想监控 dropdownlist是否选择,为何不起作用?(具体见Middle-5.aspx中的性别

在使用微软AJAX控件中的dropdownlist级联时,比如省市区联动,如果省没有选择,则市和区都是灰的,是disabled状态,是被禁 用的,类似代码如下:

<asp:DropDownList ID=”DropDownList1″ runat=”server” CssClass=”required” disabled=”true”>
<asp:ListItem></asp:ListItem>
<asp:ListItem Value=”1″>男</asp:ListItem>
<asp:ListItem Value=”0″>女</asp:ListItem>
</asp:DropDownList>

我这边是强制把这个DropDownList禁用了,这时如果为这个控件加上“required”将不会有任何反应,因为在 jQuery.Validate代码中默认是不验证的,具体代码见jQuery.Validate.js414行:

not(“:submit, :reset, :image, [disabled]”)

所以为了方便我们使用,我们修改下代码,将[disabled]”去除,改为:

not(“:submit, :reset, :image”)

这样再刷新下页面,验证就起作用了。

第6点:radiobox,checkbox,listbox 如何进行高级应用?如何指定选择数量?(具体请见radio-checkbox-select- demo.html

这点我直接引用了官方关于radiobox,checkbox,listbox应用的例子,因为官方的例子已经写的非常好了。

以上就是使用jQuery.Validate进行客户端验证中级篇-下,本文就jQuery.Validate在使用上遇到的问题进行了介绍(都是 我在实际项目中碰到的,进行一个总结,难免有遗漏,如果有过jQuery.Validate开发经验的朋友欢迎指点),具体可以下载源代码查看。

PS:中级篇总算写完了,下面就是高级篇的应用了, 高级篇主要会讲:如何扩展验证方式,分组验证,AJAX验证,敬请期待!

源代码下载:点我下载

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