Kyl*_*fin 6 asp.net-mvc asp.net-mvc-2
我一直在使用ASP.NET MVC2进行一些实验,并遇到了一个有趣的问题.
我想在MVC应用程序中定义将用作模型的对象周围的接口.另外,我想通过使用验证属性标记此接口的成员来在功能上利用新的DataAnnotation.
所以,如果我的网站有一个"Photo"对象,我将定义以下界面:
public interface IPhoto
{
[Required]
string Name { get; set; }
[Required]
string Path { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我将定义以下实现:
public class PhotoImpl : IPhoto
{
public string Name { get; set; }
public string Path { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的MVC App控制器可能包含以下方法:
public class PhotoController : Controller
{
[HttpGet]
public ActionResult CreatePhoto()
{
return View();
}
[HttpPost]
public ActionResult CreatePhoto(IPhoto photo)
{
if(ModelState.IsValid)
{
return View();
}
else
{
return View(photo);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,为了将PhotoImpls绑定到这些操作方法中的参数,我可能会对DefaultModelBinder实现以下扩展:
public class PhotoModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if(bindingContext.ModelType == typeof(IPhoto))
{
IPhoto photo = new PhotoImpl();
// snip: set properties of photo to bound values
return photo;
}
return base.BindModel(controllerContext, bindingContext);
}
}
Run Code Online (Sandbox Code Playgroud)
除了我的控制器中的ModelState.IsValid属性似乎没有注意到IPhoto实现的[Required]属性中的无效值(例如,null)之外,所有内容似乎都运行良好.
我怀疑我忽略了在我的ModelBinder实现中设置一些重要的状态.任何提示?
我遇到过同样的问题.答案是在您的自定义模型绑定器中覆盖BindModel(),而不是重写CreateModel()...
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType)
{
if (modelType == typeof(IPhoto))
{
IPhoto photo = new PhotoImpl();
// snip: set properties of photo to bound values
return photo;
}
return base.CreateModel(controllerContext, bindingContext, modelType);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以让基础BindModel类做验证的东西:-)
在检查System.Web.MVC.DefaultModelBinder的源代码之后,看起来这可以使用稍微不同的方法来解决.如果我们更依赖于BindModel的基本实现,看起来我们可以构建一个PhotoImpl对象,同时仍然从IPhoto中提取验证属性.
就像是:
public class PhotoModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(IPhoto))
{
ModelBindingContext newBindingContext = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
() => new PhotoImpl(), // construct a PhotoImpl object,
typeof(IPhoto) // using the IPhoto metadata
),
ModelState = bindingContext.ModelState,
ValueProvider = bindingContext.ValueProvider
};
// call the default model binder this new binding context
return base.BindModel(controllerContext, newBindingContext);
}
else
{
return base.BindModel(controllerContext, bindingContext);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4100 次 |
| 最近记录: |