假设我想允许在页面上选择我们的实体(来自下拉列表等),让我们说产品.结果我可能收到这个:
public ActionResult SelectedAction(Guid productId)
{
}
但是,我想使用模型绑定器的功能,所以我编写模型绑定器以从存储库获取我的产品,而不是使用
public ActionResult SelectedAction(Product product)
{
if (ModelState.IsValid) {} else {}
}
如果产品无效,我的模型绑定器会将模型状态设置为false.
现在,这种方法存在问题:
>使用强类型方法(如Html.ActionLink(c => c.SelectedAction(id))并不总是很容易,因为我们需要传递Product,而不是id.
>无论如何,将实体用作控制器参数并不好.
>如果模型状态无效,并且我想重定向并显示错误,我无法保留所选产品!因为绑定的产品没有设置,我的ID不存在.我想做RedirectToAction(c => c.Redisplay(product))但当然这是不可能的.
现在,好像我回来使用“Guid productId”作为参数……但是,我想提出并讨论一个解决方案.
public class EntityViewModel<T> where T : BaseEntity
{
public EntityViewModel(Guid id)
{
this.Id = id;
}
public static implicit operator EntityViewModel<T>(T entity)
{
return new EntityViewModel<T>(entity.Id);
}
public override string ToString()
{
return Id.ToString();
}
public Guid Id { get; set; }
public T Instance { get; set; }
}
现在,如果我使用
public ActionResult SelectedAction(EntityViewModel<Product> product)
{
if (ModelState.IsValid) {} else {}
}
所有问题都解决了:
>如果我只有Id,我可以传递只有Id设置的EntityViewModel.
>我不使用实体作为参数.而且,我
可以在另一个ViewModel中使用EntityViewModel作为属性.
>我可以将EntityViewModel传递回RedirectToController,它将保留其Id值,这将是
重新显示给用户以及验证消息(感谢MVCContrib和ModelStateToTempData / PassParametersDuringRedirect).
模型绑定器将从存储库获取实例,并将设置模型状态错误,如“数据库中未找到”等.我可以使用ActionLink之类的东西(c => c.Action(Model.MyProductViewModelProperty)).
问题是,这里有任何缺点吗?我看不出有什么不好但我还是MVC的新手,可能会错过一些重要的事情.也许有更好和认可的方式?也许这就是为什么每个人都使用实体ID作为输入参数和属性?
最佳答案 总的来说,这对我来说是一个很好的选择……
作为替代方案,您可以将POCO用于您的viewmodel然后我认为所有3个问题都将自动解决.您是否看过允许实体进行DTO处理的Automapper项目?通过将ViewModel与EntityModel分离,这将为您提供更大的灵活性,但实际上取决于您正在构建的应用程序的复杂性.
MVC的ViewDataExtensions可能也很有用,而不是创建自定义容器来保存各种viewmodel对象,正如您在数字2中提到的那样.
MVCContrib的ModelStateToTempData应该适用于任何可序列化的对象(必须可以为任何进程外的会话状态提供程序序列化,例如SQL,Velocity等),所以你可以使用它,即使没有包装你的实体类也不行吗?