visual vista tutorial studio proyecto net mvc modelo form espaƱol ejemplo crear controlador asp asp.net-mvc-3 asp.net-mvc-2 custom-model-binder custom-binding

asp.net-mvc-3 - vista - tutorial asp net mvc



Carpeta de modelo personalizado para modelo interno (1)

El siguiente funciona para mi.

Modelo:

public enum AmPmEnum { Am, Pm } public class TimePicker { public TimeSpan Time { get; set; } public AmPmEnum AmPm { get; set; } } public class MainModel { public TimePicker TimePickerField { get; set; } }

Controlador:

public class HomeController : Controller { public ActionResult Index() { var model = new MainModel { TimePickerField = new TimePicker { Time = TimeSpan.FromHours(1), AmPm = AmPmEnum.Pm } }; return View(model); } [HttpPost] public ActionResult Index(MainModel model) { return View(model); } }

Ver ( ~/Views/Home/Index.cshtml ):

@model MainModel @using (Html.BeginForm()) { @Html.EditorFor(x => x.TimePickerField) <button type="submit">OK</button> }

Plantilla de editor personalizado ( ~/Views/Shared/EditorTemplates/TimePicker.cshtml ) que combina las propiedades Time y AmPm en un solo campo de entrada y que requerirá un enlace de modelo personalizado más adelante para dividirlas cuando se AmPm el formulario:

@model TimePicker @Html.TextBox("_picker_", string.Format("{0} {1}", Model.Time, Model.AmPm))

y la carpeta modelo:

public class TimePickerModelBinder : IModelBinder { public object BindModel( ControllerContext controllerContext, ModelBindingContext bindingContext ) { var key = bindingContext.ModelName + "._picker_"; var value = bindingContext.ValueProvider.GetValue(key); if (value == null) { return null; } var result = new TimePicker(); try { // TODO: instead of hardcoding do your parsing // from value.AttemptedValue which will contain the string // that was entered by the user return new TimePicker { Time = TimeSpan.FromHours(2), AmPm = AmPmEnum.Pm }; } catch (Exception ex) { bindingContext.ModelState.AddModelError( bindingContext.ModelName, ex.Message ); // This is important in order to preserve the original user // input in case of error when redisplaying the view bindingContext.ModelState.SetModelValue(key, value); } return result; } }

y finalmente registre su carpeta de modelo en Application_Start :

ModelBinders.Binders.Add(typeof(TimePicker), new TimePickerModelBinder());

Tengo un modelo como este:

public class MainModel { public string Id {get;set;} public string Title {get;set;} public TimePicker TimePickerField {get;set;} }

TimePicker es un modelo interno que se ve así:

public class TimePicker { public TimeSpan {get;set;} public AmPmEnum AmPm {get;set;} }

Estoy intentando crear un enlace de modelo personalizado para el modelo interno: TimePicker

La pregunta es: ¿cómo obtengo los valores en el TimePicker modelo personalizado que se envió en formulario a los campos del modelo TimePicker ?

Si trato de obtenerlo así:

var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

Acabo de obtener un value null .

No estoy seguro de cómo implementar la carpeta de modelo correctamente.

public class TimePickerModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } var result = new TimePicker(); var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (value != null) { bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value); try { //result = Duration.Parse(value.AttemptedValue); } catch (Exception ex) { bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message); } } return result; } }