asp.net-mvc – TimeSpan的MVC编辑器模板
我想在我的模型中将一组文本框(小时,分钟和秒)绑定到TimeSpan.我不想在我的模型中添加小时,分钟和秒,我宁愿不将它们作为参数传递给action方法.
我发现了一些关于使用编辑器模板的讨论,但找不到一个好的例子. 解决方法
有两种方法可以做到这一点.第一种方法是实现IModelBinder,这需要您将TimeSpan作为单独的参数传递给您的操作,然后将模型的TimeSpan属性设置为它:
[HttpPost] public ActionResult Index(YourViewModel model,[ModelBinder(typeof(TimeSpanModelBinder))] TimeSpan ts) { model.LengthOfTime = ts; // do stuff } 第二个是从DefaultModelBinder派生,然后允许您直接绑定到您的模型: [HttpPost] public ActionResult Index([ModelBinder(typeof(TimeSpanModelBinder))] YourViewModel model) { // do stuff } 实现IModelBinder的优点是您不需要定义自定义属性来标记您的属性.您也不需要在运行时动态查找模型上的属性. 从DefaultModelBinder派生的优点是,只要您使用自定义属性,它就适用于您拥有的任何模型,因此如果您需要在多个位置使用它,则可以保持操作的一致性. 第一种方法:实现IModelBinder 对于这种方法,实现IModelBinder只是意味着为BindModel方法创建一个实现: public class TimeSpanModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof(TimeSpan)) return null; int hours = 0,minutes = 0,seconds = 0; hours = ParseTimeComponent(HoursKey,bindingContext); minutes = ParseTimeComponent(MinutesKey,bindingContext); seconds = ParseTimeComponent(SecondsKey,bindingContext); return new TimeSpan(hours,minutes,seconds); } public int ParseTimeComponent(string component,ModelBindingContext bindingContext) { int result = 0; var val = bindingContext.ValueProvider.GetValue(component); if (!int.TryParse(val.AttemptedValue,out result)) bindingContext.ModelState.AddModelError(component,String.Format("The field '{0}' is required.",component)); // This is important bindingContext.ModelState.SetModelValue(component,val); return result; } private readonly string HoursKey = "Hours"; private readonly string MinutesKey = "Minutes"; private readonly string SecondsKey = "Seconds"; } 注意对bindingContext.ModelState.SetModelValue的调用.此方法可确保在需要在表单上重新显示模型时,使用正确的数据重新填充模型.这很重要,因为如果用户提交的数据验证失败,它会保留再次填写所有表单字段的默认功能. 第二种方法:从DefaultModelBinder派生 您需要做的第一件事是创建一个自定义属性,您将使用该属性来标记要绑定到的模型的属性: [AttributeUsage(AttributeTargets.Property,AllowMultiple = false)] public class TimeSpanComponentAttribute : Attribute { public override bool Match(object obj) { return obj.GetType() == typeof(TimeSpan); } } 然后,您将在视图模型中使用它,如下所示: public class YourViewModel { [Required] public string SomeRequiredProperty { get; set; } [TimeSpanComponent] public TimeSpan LengthOfTime { get; set; } } 然后,这允许我们在自定义模型绑定器中查找使用该属性标记的属性: public class TimeSpanModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext) { var model = this.CreateModel(controllerContext,bindingContext,bindingContext.ModelType); bindingContext.ModelMetadata.Model = model; var target = model.GetType() .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => Attribute.IsDefined(p,typeof(TimeSpanComponentAttribute))) .Single(); if (target == null) throw new MemberAccessException(PropertyNotFound); int hours = 0,bindingContext); target.SetValue(model,new TimeSpan(hours,seconds)); return base.BindModel(controllerContext,bindingContext); } public int ParseTimeComponent(string component,component)); // Again,this is important bindingContext.ModelState.SetModelValue(component,val); return result; } private readonly string HoursKey = "Hours"; private readonly string MinutesKey = "Minutes"; private readonly string SecondsKey = "Seconds"; private readonly string PropertyNotFound = "Could not bind to TimeSpan property. Did you forget to decorate " + "a property with TimeSpanComponentAttribute?"; } 请注意我们如何在BindModel中根据自定义属性找到正确的属性.此外,在我们完成对属性的绑定之后,对BindModel基本版本的调用允许默认模型绑定器处理其他所有内容. 注意 两种方法都假设您的文本框的名称分别为小时,分钟和秒.如果不是,只需更改3个私有字符串的值即可. 我通过这个编辑改变了很多,所以如果我错过了什么,请告诉我. 感谢您提出这个问题 – 我从中学到了很多东西. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-web-api – WebAPI重定向不起作用?
- 如何在ASP.NET中获取原始请求体?
- asp.net-mvc – MVC,FluentValidation和Ninject的单元测试接
- asp.net-mvc – 如何使用Html.Action?
- ABP官方文档(三十二)【MVC Controllers】
- asp.net-mvc – 刷新数据库更改页面
- 玩转VSCode-完整构建VSCode开发调试环境
- asp.net-web-api – 如何创建角色并将用户添加到ASP.NET MV
- .net – 为什么我的剃刀视图抱怨“}预计”升级到剃刀2/mvc
- T-SQL Enhancement in SQL Server 2005[上篇]