随笔 - 62  文章 - 0  评论 - 7 
  2012年1月6日

ASP.NET MVC 3 Client-Side Validation Summary with jQuery Validation (Unobtrusive JavaScript)

When we were working with ASP.NET MVC 2, we needed to write our own JavaScript to get Client-Side Validation Summary with jQuery Validation plugin.
I am one of those unfortunate people still stuck with .NET Framework Runtime 2.0 and .NET Framework 3.5; meaning I am still on ASP.NET MVC 2.
So I will still keep on supporting by answering any question you may have with my original code.

 

Long awaited ASP.NET MVC 3 has been released, and it supports Client Side Validation Summary with jQuery out-of-the-box with new features likeUnobtrusive JavaScript.

 

1. _Layout.cshtml Template

Notice that I am using Protocol Relative URLs ( i.e., '//'.  Not 'http://' or 'https://' ) to reference script files and css files and you should use it too like that!
However, please note that IE7 and IE8 will download the CSS files twice so use it with judgement.

<!DOCTYPE html> <html> <head>     <title>@ViewBag.Title</title>     <link href="@Url.Content("~/Assets/Site.css")"  rel="stylesheet" type="text/css" />     <link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" media="screen" /> </head>  <body>     @RenderBody()      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"           type="text/javascript"></script>     <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"      type="text/javascript"></script>     <script src="//ajax.microsoft.com/ajax/jQuery.Validate/1.7/jQuery.Validate.min.js" type="text/javascript"></script>     <script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js" type="text/javascript"></script> </body> </html> 

 

2. MVC View Template

There are 3 things you *must* do exactly to get Client Side Validation Summary working.

  1. You must declare your Validation Summary **inside** the `Html.BeginForm()` block like below.
  2. You must pass `excludePropertyErrors: false` to the  Html.ValidationSummary()  method.
    @using (Html.BeginForm()) {     @Html.ValidationSummary(false, "Please fix these errors.");      <!-- The rest of your View Template -->  }
    Html.ValidationSummary(false"Please fix these errors.") generates the HTML code below.
    <div class="validation-summary-valid" data-valmsg-summary="true">     <span>Please fix these errors.</span>     <ul><li style="display:none"></li></ul> </div> 
    If you look into the jquery.validation.unobtrusive.js source code, you will understand why I said the Validation Summary declaration must be inside theHtml.BeginForm( ) block.
    On line #56 inside the function onErrors(form, validator) { // 'this' is the form element function, it retrieves the validation summary HTML node like below.
    var container = $(this).find("[data-valmsg-summary=true]")
    Basically, it looks for the validation summary HTML node **inside** the corresponding <form> tag.
    If you don't declare the validation summary block using Html.ValidationSummary(false"Please fix these errors.") using the false parameter, the data tag data-valmsg-summary="true" does NOT get generated, and the jQuery Validation Unobtrusive library won't be able to locate your validation summary to populate the error messages.
    This is needed because you may have multiple <form> tags on the entire page and the validation library needs to know exactly which validation summary block to insert the client-side validation error messages.
     
  3. You have to put the following two elements in the `<appSettings />` block of your Web.config file.
    <add key="ClientValidationEnabled"       value="true"/> <add key="UnobtrusiveJavaScriptEnabled"  value="true"/>


 

3. CSS Styles for Validation

As Anthony mentioned below in the comments, I forgot to mention about the CSS styles used by MVC framework for validation display.
The CSS class names below are pretty self-explanatory of what they do.

.input-validation-error { border: 1px solid #f00 } .input-validation-valid  { /* Optional: you can set whatever style you want */ } .field-validation-error { color: #f00 } .field-validation-valid { display: none } .validation-summary-errors { font-weight: bold; color: #f00 } .validation-summary-valid { display: none }

 

 

 

That is all you need to do.  Simple, right?
I will upload a sample project for download soon. 

Please let me know if you run into some issues.

 

 

P.S:
Without getting into too much technical details, I just wanted to let you know what I went through to get this to work.
I had to look into the ASP.NET MVC 3 RTM Source Code and the jquery.validate.unobtrusive.js source.

Initially, I thought I have to hack the jquery.validate.unobtrusive.js or something to get this to work.
But after digging into MVC3 RTM source, I found out how to do it.

 

posted @ 2012-01-06 16:24 Atom Yan 阅读(7) 评论(0) 编辑
看个博客要跨越 墙,唉!

Solve the MVC 3 Shortcut conflict with MVC 2 on Visual Studio 2010

October 10, 2011 by Mohamed Radwan


When we install MVC 3 on Visual Studio 2010, the shortcut for MVC 3 didn’t work and this because all shortcut are associated with MVC 2, we can solve this issue by many ways,

We can open–>Tool–>Option–>Enviroment–>Keyboard

Start search for the following items, and we will found each one has 2 items, so we will associate shortcut to the item that didn’t has:

  • ProjectandSolutionContextMenus.Project.Add.Controller Ctrl+M, Ctrl+C
  • ProjectandSolutionContextMenus.Project.Add.Area     Ctrl+M, Ctrl+A
  • EditorContextMenus.CodeWindow.AddView     Ctrl+M, Ctrl+V
  • OtherContextMenus.ASPXcontext.GoToController    Ctrl+M, Ctrl+G
  • Project.AddClass     SHIFT+ALT+C

We can also make another solution by removing MVC 2 Tool from Add Remove Program but this will make any existing MVC 2 application not be able to work, if you remove it by mistake you can install this tool again from VS2010 DVD, the tool name is VS2010ToolsMVC2.msi and can be fond  under WCU\ASPNETMVC


posted @ 2012-01-06 10:57 Atom Yan 阅读(4) 评论(0) 编辑
  2011年11月8日

2008-05-13 14:08 by Rainbow, 1092 visits, 收藏编辑
一、抽象类:
      抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。

 二、接口:
      接口是引用类型的,类似于类,和抽象类的相似之处有三点:
       1、不能实例化;
       2、包含未实现的方法声明;
       3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);

       另外,接口有如下特性:
接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。


      三、抽象类和接口的区别:
      1.类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做。。。”.抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中. 
      2.接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;     
      3.一个类一次可以实现若干个接口,但是只能扩展一个父类     
      4.接口可以用于支持回调,而继承并不具备这个特点.     
      5.抽象类不能被密封。   
      6.抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的. 
      7.(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。   
      8.抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。   
      9.好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。   
     10.尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知.(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则。   
     11.如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法.
   
      四、抽象类和接口的使用:
      1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。
      2.如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。
      3.如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。   
      4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。


 以下是我在网上看到的几个形象比喻,真的非常不错,呵呵:
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。(太精辟了。。)
2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。 门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染))。
看个例子:
假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

使用abstract class方式定义Door:

abstract class Door {

abstract void open();

abstract void close();

}

使用interface方式定义Door:

interface Door {

void open();

void close();

}

其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。

如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class和interface反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。

解决方案一:

简单的在Door的定义中增加一个alarm方法,如下:

abstract class Door {

abstract void open();

abstract void close();

abstract void alarm();

}

或者

interface Door {

void open();

void close();

void alarm();

}

那么具有报警功能的AlarmDoor的定义方式如下:

class AlarmDoor extends Door {

void open() { … }

void close() { … }

void alarm() { … }

}

或者

class AlarmDoor implements Door {

void open() { … }

void close() { … }

void alarm() { … }

这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。

解决方案二:

既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用abstract class方式定义;两个概念都使用interface方式定义;一个概念使用abstract class方式定义,另一个概念使用interface方式定义。

显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。

如果两个概念都使用interface方式来定义,那么就反映出两个问题:

1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?

2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:

abstract class Door {

abstract void open();

abstract void close();

}

interface Alarm {

void alarm();

}

class AlarmDoor extends Door implements Alarm {

void open() { … }

void close() { … }

void alarm() { … }

}

这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。

abstract class和interface是Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法,希望读者朋友能够细细体会

posted @ 2011-11-08 15:04 Atom Yan 阅读(9) 评论(0) 编辑
  2011年2月11日
[Obsolete("Message")]
posted @ 2011-02-11 17:05 Atom Yan 阅读(9) 评论(0) 编辑
  2011年1月31日
摘要: 1. delegate 委托可以理解为cxx 语言中的函数指针,标示了方法调用的回调函数的规范。强类型,便于编译时检查是它的最大优点,从此可以和void * 说再见了。2. event 事件用以delegate委托声明事件,标示响应该事件的回调函数必须符合其声明委托的定义3. lambda 表达式在.net世界中表现为匿名委托,之前又要提到匿名方法(函数)01publicclassTest{02publicvoiddelegateClose();//声明一个无参无返回值的委托03publiceventClose CloseEvent;//声明一个Close对应事件04}05staticvoid阅读全文
posted @ 2011-01-31 23:55 Atom Yan 阅读(98) 评论(1) 编辑
  2010年12月22日
摘要: Link: Attribute在.net编程中的应用(一) Attribute在.net编程中的应用(二) Attribute在.net编程中的应用(三) Attribute在.net编程中的应用(四) Attribute在.net编程中的应用(五) Attribute在.net编程中的应用(六) HQL: Hibernate 大全中的大全阅读全文
posted @ 2010-12-22 16:07 Atom Yan 阅读(9) 评论(0) 编辑
摘要: Link: http://msdn.microsoft.com/en-us/library/ms998558.aspx阅读全文
posted @ 2010-12-22 16:04 Atom Yan 阅读(37) 评论(0) 编辑
  2010年9月2日
摘要: WORD-word2007加入checkbox转载,原文地址:http://blog.sina.com.cn/s/blog_5ff5964a0100ej4d.html要在Office 2007中插入复选框,显示“开发工具”选项卡单击“Office 按钮”2007加入checkbox" border=0 alt=按钮图像 src="http://off...阅读全文
posted @ 2010-09-02 10:27 Atom Yan 阅读(491) 评论(0) 编辑
  2010年8月20日
摘要: 在Visual Studio 2008中增加了许多类似Word的功能,可提高代码编辑的效率。 1.渐进式搜索 (1)按Ctrl+I,显示一个搜索图标; (2)逐个字符输入,系统会逐字符匹配,并高亮显示搜索的文本。下图就是输入“sqlc”字符时的情况,系统将自动在文档中匹配输入的字符。 (3)再次按Ctrl+I,光标将跳至下一个匹配的文本; (4)按Ctrl+Shif...阅读全文
posted @ 2010-08-20 10:44 Atom Yan 阅读(117) 评论(0) 编辑