一.写作前提
最近正在做一个Asp.Net MVC2的Project,用到了Linq to SQL,但是对于如何在MVC2中使用 Linq to SQL 生成的强类型加注Data Annotation,我们都知道在MVC2中我们可以定义自己的Model,然后给Model加Data Annotation,从而在View中可以实现完美的Client Validation(这些Data Annotation也我们也可以去自己定义)。但是对于Linq to SQL 生成的强类型,我们有两个问题,第一,应该如何实现它的Data Annotation;第二,当我们的Database结构发生改变时,我们通常需要把Linq to SQL里相应的对象先删除,然后再重新映射,这时我们如何保证我们加的Data Annotation只需要进行最小的改动就可以完成对新映射的支持?
下面我们就上面的问题进行分析和提出我们的解决方案。
二.通常MVC的做法
首先我们来做一个比较,自定义Model加Annotation,如表1所示:
图表1:Product Class 的定义
1 public class Product
2 {
3 [DisplayName("Product Name")]
4 [Required(ErrorMessage="Product Name is Required.")]
5 [StringLength(50,ErrorMessage="Max Length of Product Name can not greater than 50 characters.")]
6 public string Name
7 {
8 get;
9 set;
10 }
11
12 [DisplayName("Product Type")]
13 [Required(ErrorMessage = "Product Type is Required.")]
14 [StringLength(20, ErrorMessage = "Max Length of Product Name can not greater than 20 characters.")]
15 public string Type
16 {
17 get;
18 set;
19 }
20 }
Controller 定义如图表2所示:
图表2:Product Controller的使用
1 public class ProductController : Controller
2 {
3 public ActionResult CreateProduct()
4 {
5 this.ViewData.Model = new Product();
6 return View();
7 }
8
9 [HttpPost]
10 public ActionResult CreateProduct(Product p)
11 {
12 if (this.ModelState.IsValid)
13 {
14 //Save Data
15 }
16 else
17 {
18 this.ViewData.Model = p;
19 }
20 return View();
21 }
22 }
在Site.Master中加入如图表3所示:
图表3:Enable Client Validation
1 <script type="text/javascript" src="<%=Url.Content("~/Scripts/MicrosoftAjax.js") %>" ></script>
2
3 <script type="text/javascript" src="<%=Url.Content("~/Scripts/MicrosoftMvcValidation.js") %>" ></script> <% Html.EnableClientValidation(); %>
View代码如图表4所示:
图表4:View中对Product的应用
1 <%using (Html.BeginForm())
2 { %>
3 <p>
4 <%=Html.LabelFor(Model => Model.Name)%>
5 <%=Html.TextBoxFor(Model => Model.Name)%>
6 <%=Html.ValidationMessageFor(Model => Model.Name)%>
7 </p>
8 <p>
9 <%=Html.LabelFor(Model => Model.Type)%>
10 <%=Html.TextBoxFor(Model => Model.Type)%>
11 <%=Html.ValidationMessageFor(Model => Model.Type)%>
12 </p>
13 <input type="submit" value="Submit" />
14 <%} %>
上面我们定义了Model Product,定义了两具属性,分别是Name和Type,并且给他们加了Annotation(注意:DisplayName是 System.ComponentModel命名空间下面的),Asp.net MVC2在做Validation的时候,他会根据我们所加注的这些Annotation对对应的Property进行验证。然后我们在 Site.Master指定他们进行Client端验证,在Create Product 的View中我们加以应用,当我们点Submit的时候,它并没有做Postback,并且帮我们做了所需求的 Validation,如图表5所示,这使得我们MVC的开发更方便、更简洁,同时也带了更好的视觉效果。
图表5:View调用的结果
三.Linq to SQL 在MVC2的问题与本文解决方案
Ok,上面是我们传统的做法,但是在我们的项目中使用的是Linq to SQL,之所以使用Linq to SQL,是因为我们只需要把Database中的Table、 Stored Procedure或者Function等拖到我们的Linq to SQL文件中,他就会帮我们生成对应的强类型文件,方便我们的使用,特别是在Asp.Net MVC中的使用。 但是我们如何给Linq to SQL生成的类类型加Data Annotation呢?
首先我们可以简单的想,直接在Linq to SQL 生成的cs文件中引用System.ComponentModel.DataAnnotations,然后在对应的Property中加我们所需要的 Annotatio,从理想的状态来讲,我们说这个方案是可行的,但是前提条件是你所设计的Table、Stored Procedure或者Function 结构不会再更改,因为当我们Linq to SQL里的对象在Database的结构发生变化时,我们需要删除Linq to SQL文件中的对象,然后从Database重新的拖入,以生成更新后的强类型文件,那么我们之前加入的Annotation也会被删除掉,后果就是我们需要重新加注Data Annotation,这样会增加我们很大的工作量, 那么我们如何来解决这样的问题呢?
在Linq to SQL中,如果你的Database的表的名称是T_PRODUCT,那么当你把表插入到Linq to SQL的文件中生,他会帮我们生成对应名称为T_PRODUT的Class。如图表6所示:
图表6:Database Table在Linq to SQL中显示
我们的解决方案是定义一个新的Class(我们这里叫ProductAnnotation),然后在里面加入哪些需要加注Annotation的Properties(Property的名字需要和T_PRODUCT表中的字段相同),如图表7所示:
图表7:为T_PRODUCT表定义Data Annotation
1 public class ProductAnnotation
2 {
3 [DisplayName("Product Name")]
4 [Required(ErrorMessage = "Product Name is Required.")]
5 [StringLength(50, ErrorMessage = "Max Length of Product Name can not greater than 50 characters.")]
6 public string Name { get; set; }
7
8 [DisplayName("Product Type")]
9 [Required(ErrorMessage = "Product Type is Required.")]
10 [StringLength(20, ErrorMessage = "Max Length of Product Name can not greater than 20 characters.")]
11
12 public string Type { get; set; }
13 }
可以看出,这和我们之前定义的那Product没有多大差别,关键在于这里面只需要加入那些我们需要的字段,例如表里的Oid我们不需要,那么就没有必要放进来,这使用我们的设计更加自由。上面我们定义完了所需要的Annotation,也解决了本文开始的第一个问题。下面我们需要做的事情就是把定义的这个包含Annotation的Class和我们的T_PRODUCT表进行绑定,方法如图表8所示:
图表8:联合(绑定)Data Annotation到Linq to SQL中T_PRODUCT Class
1 [MetadataType(typeof(ProductAnnotation))]
2 public partial class T_PRODUCT
3 {
4
5 }
上面 partial的意思就是对T_PRODUCT表进行部分定义,关键在于在它的上面有一个MetadataType的 Atrribute,并且里面所引用的正是我们上面所定义的Class,System.ComponentModel.DataAnnotations命名空间下的MetadataType Attribute的作用就是将两个进行整合,但是Asp.Net MVC 去读那些Validation的时候,他就会去从我们定义的ProductAnnotation中对应的字段去读取。
假设我们把Database中T_PRODUCT表中的Name改成了ProductName,我们需要把Linq to SQL的中对应的表重新拖入,生成新的强类型Class,到我们的ProductAnnotation Class中修改相应的名称即可,而无须重新加注所有字段了,其它修改类似,这也就解决了本文的问题。
以上就是我们的解决方案,他实现的效果和我们上面所实现 的效果是一样的。
四.总结
通过对Asp.Net MVC2 Data Annotation的分析,介绍了如何通过实现对Linq to SQL加注Data Annotation。通过上面的分析主要了解了如下内容:
Asp.Net MVC2中利用Data Annotation定义Validation的使用。
实现对Linq to SQL生成的强类型Class加Validation的方法
本文作者:未知