public partial class BBSPost {
public bool IsValid {
get { return (GetRuleViolations().Count() == 0); }
}
public IEnumerable<RuleViolation> GetRuleViolations() {
if (String.IsNullOrEmpty(Title))
yield return new RuleViolation("标题必须输入", "Title");
if (String.IsNullOrEmpty(Content))
yield return new RuleViolation("内容必须输入", "Content");
yield break;
}
partial void OnValidate(ChangeAction action) {
if (!IsValid)
throw new ApplicationException("Rule violations prevent saving");
}
}
RuleViolation是一个辅助类,很简单。
复制代码 代码如下:
public class RuleViolation {
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
public RuleViolation(string errorMessage) {
ErrorMessage = errorMessage;
}
public RuleViolation(string errorMessage, string propertyName) {
ErrorMessage = errorMessage;
PropertyName = propertyName;
}
}
在写action的时候,捕获SubmitChanges操作的异常,然后给ModelState里添加自定义验证逻辑的异常,ModelState会把添加进去的异常传递给View层,供View层使用。
复制代码 代码如下:
try {
var db = new BBSDbContext(GlobalHelper.Conn);
post.PostUser = User.Identity.Name;
//其它赋值操作
db.BBSPosts.InsertOnSubmit(post);
db.SubmitChanges();
ModelState.Clear();
}
catch (Exception ex) {
ModelState.AddModelErrors(post.GetRuleViolations());
ModelState.AddModelError("exception", ex);
}
默认的ModelState没有AddModelErrors方法,只有AddModelError方法,我们是后来给他加了一个扩展方法,如下
public static class ModelStateHelpers {
public static void AddModelErrors(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors) {
foreach (RuleViolation issue in errors) {
modelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
}
}
在View层使用了Html.ValidationMessage方法在合适的位置输出错误描述,如果View呈现的时候ModelState里有错误的话,会自动显示相应的错误描述,代码示例如下。
复制代码 代码如下:
<p>
<label for="Title">
标题:</label>
<%= Html.TextBox("Title", null, new { style = "width:700px;" })%>
<%= Html.ValidationMessage("Title") %>
</p>
<p>
<label for="Content">
内容:</label>
<%= Html.TextArea("Content", null, new { style = "width:700px;height:100px;" })%>
<%= Html.ValidationMessage("Content")%>
</p>
5、LINGQ TO SQL的分页
SQLSERVER 2005有很强悍的分页函数,LINQ TO SQL对其有很好的支持,IQueryable<T>的Skip和Take方法最终就生成分页的SQL,先写如下的一个帮助类(取自NerdDinner),这个类的属性很简单,见名知意,就不介绍了。
复制代码 代码如下:
public class PaginatedList<T> : List<T> {
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) {
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int) Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize)); //这句会停止延迟加载,把数据加载到内存里
}
public bool HasPreviousPage {
get {
return (PageIndex > 0);
}
}
public bool HasNextPage {
get {
return (PageIndex+1 < TotalPages);
}
}
}
使用起来很简单,用LINQ TO SQL得到一个IQueryable后,再用其New一个PaginatedList就表示一个已分页的数据集了
复制代码 代码如下: