Linq + MVc 开发之数据验证

 

很多初学者也可能和我一样用过 Linq + Mvc 来开发。

开发的过程中也许遇到过很多的问题,特别是在没有人指导你的情况下。

这两天 MVC 的数据验证一直困惑着我,到现在为直我只知道把数据验证的代码写到 Model 里,而 在用Linq作底层的时候直接就用设计器来生成 实体类了,那是一个大文件,50多个表代码就达到2W多行。

现在的问题就出来了。

实体类是 Linq 设计器自动生成的,而 MVC 又要把 验证写到实体类里,那怎么办,难道要一个字段一个字段来添加吗? 那显然不对,虽然入行不深,但我感觉上就认为有更好的办法来解决这个问题。

上网找了半天 基本上都是你抄我我抄你,下载了些例子,可那些就只停留在 增删改查,根本就没什么验证代码在里面。

最后在群里问一些高手。得出的解决办法是写“部分类”,虽然 Linq 自动生成的代码我们不好改更不好维护,所以用 “部分类” 是个办法,在我看来现在应该 是最好的办法。

先贴上一篇文章,里面对 MVC 的数据验证讲的很细了

http://www.cnblogs.com/serviceboy/archive/2009/11/28/1612518.html

虽然得到高手的请教,可关键是人家没给代码。 编程这东西如果只是讲讲,那谁都可以是程序员,虽然没有直接代码,但至少知道 google 搜索的方向了。

后来看了一下这位高手的代码才有所觉悟,(汉,人家不贴代码,如果当时没有下载他的源码还真不知道怎么解决我的问题)

http://www.cnblogs.com/ZilchWei/archive/2010/08/11/1797652.html

 

先贴代码

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace LinqToSqlModel验证.Models
{
    [MetadataType(typeof(admin_tab))]
    public partial class admin
    {
    }
    [Bind(Exclude="id")]
    public class admin_tab
    {
        [Required(ErrorMessage="错误!用户名不能为空")]
        [StringLength(25,ErrorMessage="提示:用户名长度超过25")]
        public string username { get; set; }
        [Required(ErrorMessage = "错误!密码不能为空")]
        [StringLength(25, ErrorMessage = "提示:密码长度超过25")]
        public string password { get; set; }
    }
}

从他的整个源码中可以看出他也是用MVC+Linq 来开发的。最主要的他这里写到了验证。

不必改动 Linq 生成的实体,直接新建一个类来作验证就可以了。

这样的话验证问题就差不多解决了。

因为 MVC 有自动的类型验证工能,不过 提示的信息是 英文的,找了很久,先是在 验证类里 用正则表达式还是不行,提示的还是原来

 

 

的英文

最终把数据类型验证从验证类中删除了,但是找到另一个更好的办法即不用在验证里写正则,也不用多作其它的修改

http://space.cnblogs.com/question/13782/

1、首先添加 App_GlobalResources 文件夹。
2、添加一个资源文件,这里命名为 Message.resx
3、给资源添加键值 PropertyValueInvalid ,值为提示信息。
4、修改 Global.asax Application_Start() 方法,添加代码
DefaultModelBinder.ResourceClassKey = "Message";
ValidationExtensions.ResourceClassKey = "Message";

 

当然 最后还有事要作,自己结的库有50多张表啊,如果这样一个一个写到验证里那不累死,当然这是不可取的。花了些时间写了个 Codesmith 模版让他自动生成了

贴一下模版代码

 

<%-- 
Name:
Author: 
Description: 
--%>
<%@ CodeTemplate Language="C#"  ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="Template description here." %>
<%@ Property Name="NameSpaceOfModel" Type="System.String" Default="Model" Category="Object" Description="引用的实体类命名空间" %>
<%@ Assembly Name="System.Design" %>
<%@ Property Name="RemoveTablePrefix" Type="System.String" Default="tbl" Category="Object" Description="The prefix to remove from table names" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="System.Data" %>
<%@ Import Namespace="System.Data" %>
<%@ Assembly Name="System.Design" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Assembly Name="SchemaExplorer" %>

/*
不作以下操作时,可以正确提示非空,长度,但类型错误却是英文。
1、首先添加 App_GlobalResources 文件夹。
2、添加一个资源文件,这里命名为 Message.resx
3、给资源添加键值 PropertyValueInvalid ,值为提示信息。
4、修改 Global.asax Application_Start() 方法,添加代码
DefaultModelBinder.ResourceClassKey = "Message"
ValidationExtensions.ResourceClassKey = "Message"
*/
using System;
using System.ComponentModel.DataAnnotations;

namespace Model
{
<%foreach(TableSchema SourceTable in SourceDatabase.Tables)
		{%>
    [MetadataType(typeof(<%=SourceTable.Name.Replace(RemoveTablePrefix,"")%>_ext))]
    public partial class <%=SourceTable.Name.Replace(RemoveTablePrefix,"")%>
    {
    }

    public class <%=SourceTable.Name.Replace(RemoveTablePrefix,"")%>_ext
    {   
    <% foreach (ColumnSchema column in SourceTable.Columns)  %>
    <% { %>
    <% if(column.AllowDBNull==false) %>
    <%{%>
        [Required(ErrorMessage = "错误!\"<%=GetColumnDes(column)%>\"不能为空")]
    <%}%>
    <% if(CSharpType(column)=="string") %>
     <%{%>
        [StringLength(<%=column.Size%>, ErrorMessage = "错误:\"<%=GetColumnDes(column)%>\"长度不能超过<%=column.Size%>")]
     <%}%>
        public <%=CSharpType(column)%> <%=column.Name%> {get;set;}
        
	<% } %> 
    }
    
    <%}%>
 }


<script runat="template">
    private DatabaseSchema _sourceDatabase;
    
    [Category("Database")]
    [Description("Database that the mapping file should be based on.")]
    public DatabaseSchema SourceDatabase {
        get { return _sourceDatabase; }
        set { _sourceDatabase = value; }
    }

//获取数据库字段的描述 column.Name
public string GetColumnDes(ColumnSchema column)
{
    if(column.Description.Trim().ToString()!=string.Empty)
    {
        return column.Description.Trim().ToString();
        }else
        return column.Name.ToString().Replace("_","");
    
}

//C#还回数据类型
public string CSharpType(ColumnSchema column)
{
	if (column.Name.EndsWith("TypeCode")) return column.Name;

	switch (column.DataType)
	{
		case DbType.AnsiString: return "string";
		case DbType.AnsiStringFixedLength: return "string";
		case DbType.Binary: return "byte[]";
		case DbType.Boolean: return "bool";
		case DbType.Byte: return "byte";
		case DbType.Currency: return "decimal";
		case DbType.Date: return "DateTime";
		case DbType.DateTime: return "DateTime";
		case DbType.Decimal: return "decimal";
		case DbType.Double: return "double";
		case DbType.Guid: return "Guid";
		case DbType.Int16: return "short";
		case DbType.Int32: return "int";
		case DbType.Int64: return "long";
		case DbType.Object: return "object";
		case DbType.SByte: return "sbyte";
		case DbType.Single: return "float";
		case DbType.String: return "string";
		case DbType.StringFixedLength: return "string";
		case DbType.Time: return "TimeSpan";
		case DbType.UInt16: return "ushort";
		case DbType.UInt32: return "uint";
		case DbType.UInt64: return "ulong";
		case DbType.VarNumeric: return "decimal";
		default:
		{
			return "__UNKNOWN__" + column.NativeType;
		}
	}
}
</script>

 

 

当然为了让验证生效,一定要在 Controller 类中作判断

public ActionResult XXX(SomeClass paramName)

{

if(!Model.IsValid)

{

return View();

}

……

}

posted @ 2010-12-07 16:39  wunaigong  阅读(744)  评论(0编辑  收藏  举报