NHibernate ModelBinder for mvc3
所有源码在 https://github.com/luqizheng/Qi4Net
特色
- 支持DTO和Mapping Entity,并且会自动忽略没有Set的Property(包括集合属性也会被忽略)
- 支持Array,IList,IList<T>,Iesi.Collection.ISet<T>, Iesi.Collection.ISet, 但是并不支持System.Collection.Generic.ISet<T>
注意事项
- 获取的Mapping entity 都是Deatached的,所以如果包保存要使用Session.SaveOrUpdate的方法保存。
和一个持久化对象自动绑定
//持久化对象
//Qi4Net\src\Qi\MvcTest\Models\User.cs
public class User : DomainObject<Guid>
{
public string LoginId { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public override int GetHashCode()
{
return (Name + Password).GetHashCode();
}
}
//Qi4Net\src\Qi\MvcTest\Models\User.cs
public class User : DomainObject<Guid>
{
public string LoginId { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public override int GetHashCode()
{
return (Name + Password).GetHashCode();
}
}
Post上来的数据会自动set到User里面,而且是自动匹配类型(其实就是NHibernate.Type.IType,提供的方法进行转换) 。NHibernateBinder会自动忽略只有Get的方法,另外IList,ISet是不支持的,因为不能简单地Clear and Add.所以只能靠手工了
//D:\GitQi\Qi4Net\src\Qi\MvcTest\Controllers\UserController.cs
[HttpPost,Session]
public ActionResult Edit([ModelBinder(typeof(NHModelBinder))]User user)
{
SessionManager.Instance.CurrentSession.SaveOrUpdate(user);
return RedirectToAction("Index");
}
[HttpPost,Session]
public ActionResult Edit([ModelBinder(typeof(NHModelBinder))]User user)
{
SessionManager.Instance.CurrentSession.SaveOrUpdate(user);
return RedirectToAction("Index");
}
第二种,持久化对象是某个对象的其中一个。
是ChangeUserPasswordModel,而不是ChangePasswordModel,不太严谨,请见谅。
属性User是会默认使用IdFoundAttribute进行绑定的
//\Qi4Net\src\Qi\MvcTest\Models\ChangeUserPasswordModel.cs
public class ChangeUserPasswordModel
{
[Required]
public User User { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public class ChangeUserPasswordModel
{
[Required]
public User User { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
View要做稍稍处理,用HiddenFor是不行的。我用了
@Html.Hidden("User", this.Model.User.Id),其中"User"和
ChangeUserPasswordModel.User 名称是一样的。
//Qi4Net\src\Qi\MvcTest\Views\User\ChangePassword.cshtml
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>ChangeUserPasswordModel</legend>
@*请留意这里*@
@Html.Hidden("User", this.Model.User.Id)
<div class="editor-label">
@Html.LabelFor(model => model.NewPassword)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.NewPassword)
@Html.ValidationMessageFor(model => model.NewPassword)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ConfirmPassword)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ConfirmPassword)
@Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>ChangeUserPasswordModel</legend>
@*请留意这里*@
@Html.Hidden("User", this.Model.User.Id)
<div class="editor-label">
@Html.LabelFor(model => model.NewPassword)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.NewPassword)
@Html.ValidationMessageFor(model => model.NewPassword)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ConfirmPassword)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ConfirmPassword)
@Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
NHModelBinder默认的情况下,是用IdFoundAttribute进行查询的. 如果不是,那么就要对Model做一些处理。
public class ChangeUserPasswordModel
{
[Required]
{
[Required]
[Qi.Web.Mvc.PropertyFounder("LoginId",true)]
public User User { get; set; }
.....
}
假设User是使用LoginId进行查询的,那么就用NhModelFounderAttribute告诉NhModelBinder, 这个Property使用LoginId,进行查询的,后面的True告诉查询结构集合石唯一的,还是有多个,如果多个就用拿第一个。
当然也可以用 Hql,如:
[Required]
[NhModelFounder("From User u where u.Id=:User", "Guid")]
public User[] User { get; set; }
[NhModelFounder("From User u where u.Id=:User", "Guid")]
public User[] User { get; set; }
集合支持
暂时支持 IList<T>,IList, Iesi.Collection.ISet<T> Iesi.Collection.ISet,以及 Array,测试如下,可以参考
Qi4Net\src\Qi\MvcTest\Models\ListDemo.cs
[PropertyFounder("LoginId")]
public User[] UsersByLoginId { get; set; }
public User[] UsersById { get; set; }
[IdFounder]
public IList<Role> RolesByDeclareIdFounder { get; set; }
public Iesi.Collections.Generic.ISet<Role> RolesBySet { get; set; }
[HqlFounder("from User u where u.Name like :UserByHql or u.LoginId like :UserByHql", "String")]
public Iesi.Collections.Generic.ISet<User> UserByHql { get; set; }
public User[] UsersByLoginId { get; set; }
public User[] UsersById { get; set; }
[IdFounder]
public IList<Role> RolesByDeclareIdFounder { get; set; }
public Iesi.Collections.Generic.ISet<Role> RolesBySet { get; set; }
[HqlFounder("from User u where u.Name like :UserByHql or u.LoginId like :UserByHql", "String")]
public Iesi.Collections.Generic.ISet<User> UserByHql { get; set; }
已经发布了1.0,只能说基本能用。