asp.net-mvc - tutorial - tag helpers asp net core
¿Cómo convertir una solicitud http en el objeto correcto? (3)
En mi proyecto ASP.Net MVC3, he creado un ModelBinder que enlaza un modelo base. En mi vista, creo un objeto a partir de un modelo que hereda de mi modelo base. Ahora quiero saber qué modelo se creó mediante reflejo en mi ModelBinder cuando presiono el botón de enviar, pero ¿cómo?
ModelBinder:
public class MBTestBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//need to know which Model was created -> convert into the right object
//reflection?
}
}
Modelos:
[ModelBinder(typeof(MBTestBinder))]
public class MBTest
{
public string Name { get; set; }
public MBTest() {}
}
public class MBAbl : MBTest
{
public MBAbl() {}
public string House { get; set; }
}
Ver:
@model ModelBinderProject.Models.MBTest
@using (Html.BeginForm("Index", "Home")) {
<fieldset>
<div class="editor-field">
@Html.EditorForModel(Model)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
Controlador:
public ActionResult Create(MBTest testItem)
{
//on init get a view from a class that hast inherit the class MBTest
if (testItem.Name == null ) testItem = new MBAbl();
return View(testItem);
}
editar:
con bindingContext.ValueProvider.GetValue("House")
puedo obtener el valor del formulario, pero bindingContext.ModelType
cree que mi modelo es MBTest
Finalmente lo resolví con la solución de llevar el nombre del modelo en mi modelo y crear dinámicamente el modelo correcto en el encuadernador. Si conoces una mejor solución porfavor muéstrame :-)
HomeController:
// CREATE
public ActionResult About(MBTest testItem)
{
if (testItem == null)
{
testItem = new MBAbl();
testItem.Model = "MBAbl";
}
return View(testItem);
}
Modelos:
public class MBTest
{
public MBTest() {}
[HiddenInput]
public string Model { get; set; }
public string Name { get; set; }
}
public class MBAbl : MBTest
{
public MBAbl() {}
public string House { get; set; }
}
public class MBAb2 : MBTest
{
...
}
ModelBinder:
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null) throw new ArgumentNullException("controllerContext");
if (bindingContext == null) throw new ArgumentNullException("bindingContext");
//string ''Model'' is needed in the base class
var modelType = bindingContext.ValueProvider.GetValue("Model");
if (modelType != null && !string.IsNullOrEmpty(modelType.AttemptedValue))
{
string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
Type classtype = Type.GetType(string.Format("{0}.Models.{1}", projectName, modelType.AttemptedValue));
PropertyInfo[] properties = classtype.GetProperties();
var classObject = classtype.GetConstructor(new Type[] { }).Invoke(null);
foreach (PropertyInfo propertie in properties)
{
var value = bindingContext.ValueProvider.GetValue(propertie.Name).AttemptedValue;
classtype.GetProperty(propertie.Name).SetValue(classObject, value, null);
}
return classObject;
}
return null;
}
Prueba esto:
public class ModelBinder : DefaultModelBinder, IModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
var type = Type.GetType("Namespace.a.b." + typeValue.AttemptedValue.ToString());
var model = Activator.CreateInstance(type);
//Change the model
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
bindingContext.ModelMetadata.Model = model;
//Here, we used the default model binder of the mvc
return base.BindModel(controllerContext, bindingContext);;
}
}
Verifique la documentación de ModelBindingContext .
Editado basado en comentarios
public class MBTestBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var result = bindingContext.ValueProvider.GetValue("Name");
if (result == null || string.IsNullOrEmpty(result.AttemptedValue))
return new MBAbl();
else
return new MBTest();
}
}