我正在使用步骤(控制器)开发类似向导的东西,并使用DerivedModel1
,DerivedModel2
等继承自BaseModel
并使用额外属性扩展它们。
模型 - 只有数据,没有业务逻辑。由控制器操作中的服务执行的所有逻辑,例如_step1Service.GetRelated(model.id)。
现在我不仅要验证模型(对于这种情况有ValidationAttribute
),还要修复BaseModel
中的无效数据:
public class BaseModel
{
public DateTime StartDate {get;set;}
}
StartDate
应该比今天更大。用户可以选择无效日期而不是验证错误应用程序应该修复此值(重置为默认值?)。
在我的第一次尝试中,我添加了用于验证/更正StartDate
的服务并在每个操作中调用:
public ActionResult Index(DerivedModel1 model)
{
_svc.fixModel(model);
if(!ModelState.IsValid)
{
return View();
}
... do stuff with valid data
}
但不喜欢这样,因为必须将此行添加到每个控制器和操作中。
然后我将此更正添加到StartDate
setter。它看起来更好,但这打破了流行的MVC范式,所有逻辑应该在控制器中(或者我可能误解了什么?)
我在考虑这个问题的可能解决方案:ActionFilterAttribute,自定义ModelBinder?但不确定这是正确的方式,是否有效。
你怎么看待它?
答案 0 :(得分:1)
你必须实现IModelBinder才能实现这一目标。
首先定义您的自定义模型绑定器:
public class MyCustomModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Get the raw attempted value from the value provider
DateTime incomingDate = (DateTime) bindingContext.ValueProvider.GetValue("datefield").AttemptedValue;
//validate and correct date here ...
return new BaseModel{ DateMember = incomingDate };
}
}
然后注册您的自定义模型绑定器:
protected void Application_Start()
{
ModelBinders.Binders.Add(typeof (BaseModel), new MyCustomModelBinder());
}
和您的控制人员:
public ActionResult YourAction([ModelBinder(typeof(MyCustomModelBinder )] BaseModel model)
{
return Content("Ok");
}
答案 1 :(得分:0)
验证和业务规则之间存在差异。对象可以(通常应该)负责确保它们自己处于有效状态。