Carpeta modelo en formularios web ASP.NET
webforms modelbinders (3)
¿No podría usar AutoMapper para algo como esto? Simplemente configure sus mapas y creará nuevos objetos y copiará los valores en ellos.
Durante varios años que desarrollé formularios web ASP.NET, una biblioteca propietaria me echó a perder, lo que me permitió hacer cosas como:
UpdateToObject(ControlsCollection, obj)
UpdateFromObject(ControlsCollection, obj)
Conceptualmente, el código hizo algo muy similar a lo que MVC Model Binder hace, es decir, dado los valores publicados del formulario como entrada, poblaría el objeto personalizado. Básicamente, liberó al desarrollador de hacer código mono como
employee.Name = txtName.Text;
employee.DOB = DateTime.Parse(txtDOB.Text);
y así..
Ahora, esta biblioteca propietaria no está disponible en el nuevo proyecto en el que estoy involucrado, y es un proyecto de formularios web. Entonces me pregunto si hay una forma de usar System.Web.Mvc.DefaultModelBinder
en el contexto de los formularios web. El objetivo es lograr una población simple y fácil de controles desde objetos de dominio y viceversa, idealmente con anotaciones de validación tomadas en consideración. Si no es posible, alguien podría indicarme una solución de código abierto para abordar esta necesidad. Realmente no tengo ganas de volver a escribir ese código.
Gracias por adelantado.
Esta es una pregunta bastante antigua, pero me topé con ella al tratar de descubrir cómo funciona realmente la carpeta de modelo predeterminada.
Tengo un proyecto en CodeProject que realmente hace lo que quiere (ed), eche un vistazo .
¡Aclamaciones!
Sherlock, te encontrarás con algunos problemas al tratar de usar el ModelBinder de MVC ya que dependen de un ControllerContext.
Respondí una pregunta similar antes ChangeType, Convert - Converting de un tipo a otro, pero es realmente lo que estás buscando.
Echa un vistazo a esta publicación de blog en mi blog ChangeType - Cambiando el tipo de variable en C #
Esencialmente, obtienes un único método llamado ChangeType<T>
que devuelve el valor del parámetro que estás buscando en una moda fuertemente tipada o un valor predeterminado si el parámetro no existe.
Ahora, en lo que respecta a las clases personalizadas (clases de tipo DTO principalmente), si no te importa usar el reflejo, entonces tengo una solución que también manejará la mayoría de las clases personalizadas. La clase de DtoBinder mencionada hacia el final del trabajo de la voluntad muy bien.
Esencialmente, los últimos 3 listados de códigos contienen todo el código que necesitará para manejar casi todas las necesidades que tenga en un escenario de aplicación web típico. Además, es extensible, por lo que si necesita implementar su propia carpeta, puede hacerlo de manera muy simple y registrar su carpeta con RequestBinder desde cualquier lugar de su aplicación.
Por lo tanto, si no desea utilizar la reflexión para ciertos objetos DTO de uso frecuente, puede implementar una carpeta para el tipo y registrarla, y desde ese momento utilizará su carpeta personalizada. En muchos sentidos, es similar a MVC ModelBinder en concepto.
Editado -
A continuación hay un archivo .cs con varias clases que he usado en el pasado para hacer exactamente lo que necesita. El primero MsPropertyAssignerProvider es con el que trabajaría desde dentro de su página.
Debería iterar sobre sus controles y llamar al método GetPropertyAssigner pasándole el nombre de tipo del control. Este método devuelve una instancia de ObjectPropertyAssigner que tiene un método llamado SetPropertyValue al que puede pasar su instancia de objeto y la instancia de control.
internal class MsPropertyAssignerProvider
{
private Hashtable propertyAssigners;
internal MsPropertyAssignerProvider()
{
propertyAssigners = new Hashtable();
RegisterPropertyAssigner(typeof(TextBox).ToString(), new TextBoxValueExtractor());
RegisterPropertyAssigner(typeof(DropDownList).ToString(), new DropDownListValueExtractor());
RegisterPropertyAssigner(typeof(Label).ToString(), new LabelValueExtractor());
RegisterPropertyAssigner(typeof(CheckBox).ToString(), new CheckBoxValueExtractor());
}
internal void RegisterPropertyAssigner(string identifier, IMsObjectPropertyAssigner assigner)
{
if (propertyAssigners.ContainsKey(identifier))
throw new DuplicatePropertyAssignerRegistrationException(identifier);
propertyAssigners.Add(identifier, assigner);
}
internal IMsObjectPropertyAssigner GetPropertyAssigner(string identifier)
{
return (propertyAssigners.ContainsKey(identifier)) ? (IMsObjectPropertyAssigner)propertyAssigners[identifier] : null;
}
}
La clase acompañante se enumera a continuación
public interface IMsObjectPropertyAssigner
{
void SetPropertyValue(object obj, System.Web.UI.Control control);
}
internal abstract class BaseValueExtractor : IMsObjectPropertyAssigner
{
protected MsReflectionHelper reflectionHelper = new MsReflectionHelper();
protected string FixStringForNumber(string stringValue)
{
if (stringValue.Length == 0)
return "0";
else
return stringValue;
}
public abstract void SetPropertyValue(object obj, System.Web.UI.Control control);
}
internal class TextBoxValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, System.Web.UI.Control control)
{
TextBox textBox = (TextBox)control;
PropertyInfo propInfo = reflectionHelper.GetPropertyInfo(obj, control.ID);
Type propType = propInfo.PropertyType;
if (propType == typeof(System.String))
reflectionHelper.SetPropertyValue(obj, control.ID, textBox.Text);
else if (propType == typeof(System.Int16))
reflectionHelper.SetPropertyValue(obj, control.ID, Int16.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Int32))
reflectionHelper.SetPropertyValue(obj, control.ID, Int32.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Int64))
reflectionHelper.SetPropertyValue(obj, control.ID, Int64.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Double))
reflectionHelper.SetPropertyValue(obj, control.ID, Double.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Single))
reflectionHelper.SetPropertyValue(obj, control.ID, Single.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else
reflectionHelper.SetPropertyValue(obj, control.ID, textBox.Text);
}
}
internal class DropDownListValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, System.Web.UI.Control control)
{
DropDownList dropDownList = (DropDownList)control;
reflectionHelper.SetPropertyValue(obj, control.ID, dropDownList.SelectedValue);
}
}
internal class LabelValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, Control control)
{
Label label = (Label)control;
reflectionHelper.SetPropertyValue(obj, control.ID, label.Text);
}
}
internal class CheckBoxValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, Control control)
{
CheckBox checkbox = (CheckBox)control;
reflectionHelper.SetPropertyValue(obj, control.ID, checkbox.Checked);
}
}
Lo siento, no importa lo que haga, el editor arruina por completo el listado de códigos. Pero espero que esto ayude.