2010-09-09 7 views
6

Pour nombre d'années, je faisais des formulaires web ASP.NET développement j'ai été gâté par une bibliothèque propriétaire, qui m'a permis de faire des choses comme:Modèle Binder dans ASP.NET WebForms

UpdateToObject(ControlsCollection, obj) 
    UpdateFromObject(ControlsCollection, obj) 

Code Conceptuellement a fait quelque chose de très semblable à ce que fait le classeur MVC, c'est-à-dire que les valeurs affichées du formulaire en entrée lui permettent de remplir un objet personnalisé. Fondamentalement, il a libéré développeur de faire du code de singe, comme

employee.Name = txtName.Text; 
employee.DOB = DateTime.Parse(txtDOB.Text); 

et ainsi de suite ..

Maintenant, cette bibliothèque exclusive n'est pas disponible sur le nouveau projet, je suis impliqué, et il est un des formulaires Web projet . Donc, je me demande s'il y a un moyen d'utiliser System.Web.Mvc.DefaultModelBinder dans le contexte de formulaires Web. L'objectif est d'obtenir une population de contrôles simple et facile à partir des objets de domaine et de retour, idéalement avec des annotations de validation prises en compte. Si cela n'est pas possible, quelqu'un pourrait me diriger vers une solution open source pour répondre à ce besoin. Je n'ai vraiment pas envie de réécrire un tel code.

Merci d'avance.

Répondre

1

Sherlock, vous rencontrerez quelques problèmes en essayant d'utiliser le ModelBinder de MVC puisqu'ils s'appuient sur un ControllerContext.

J'ai répondu à une question similaire plus tôt ChangeType, Convert - Converting from one type to another mais c'est vraiment ce que vous cherchez.

Vérifiez ce post de blog sur mon blog ChangeType – Changing the type of a variable in C#

Essentiellement, vous obtenez une seule méthode appelée ChangeType<T> qui retourne la valeur du paramètre que vous recherchez de façon fortement typé ou une valeur par défaut si la le paramètre n'existe pas.

Maintenant, en ce qui concerne les classes personnalisées (principalement les classes de type DTO), si cela ne vous dérange pas d'utiliser la réflexion, j'ai une solution qui gérera également la plupart des classes personnalisées. La classe DtoBinder mentionnée vers la fin du travail de volonté bien. Essentiellement, les 3 dernières listes de codes contiennent tout le code dont vous aurez besoin pour gérer presque tous les besoins que vous avez dans un scénario d'application Web classique. De plus, il est extensible, donc si vous avez besoin d'implémenter votre propre classeur, vous pouvez le faire très simplement et enregistrer votre classeur avec RequestBinder à partir de n'importe où dans votre application. Par conséquent, si vous ne voulez pas utiliser la réflexion pour certains objets DTO fréquemment utilisés, vous pouvez implémenter un classeur pour le type et l'enregistrer et à partir de ce point, il utilisera votre classeur personnalisé. À bien des égards, il est similaire au MVC ModelBinder dans son concept.

Edité -

Ci-dessous un fichier .cs avec un tas de classes que je l'ai utilisé dans le passé pour faire exactement ce dont vous avez besoin. Le premier MsPropertyAssignerProvider est celui avec lequel vous travaillez depuis votre page.

Vous pouvez itérer sur vos contrôles et appeler la méthode GetPropertyAssigner en lui passant le nom de type du contrôle. Cette méthode renvoie une instance d'un ObjectPropertyAssigner qui possède une méthode appelée SetPropertyValue que vous pouvez transmettre à votre instance d'objet et à l'instance de contrôle.

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 classe d'accompagnement sont énumérés ci-dessous

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); 
    } 
    } 

Désolé, peu importe ce que je fais l'éditeur salit complètement la liste de code. Mais j'espère que cela aide.

+0

Seuls les 1er et dernier paragraphes sont quelque peu pertinents à la question posée. Cela ne me dérange pas d'utiliser la réflexion. C'est ainsi que la bibliothèque propriétaire a fonctionné. – Sherlock

+0

Je suppose que dans votre cas, parce que vous travaillez avec des contrôles, la solution est un peu plus impliquée. La classe DtoBinder peut créer une instance de votre objet Dto et affecter toutes les valeurs de propriété à une collection de NameValues. Donc, ce que vous devez faire est d'assembler cette collection à partir des noms et des valeurs du contrôle et de le remettre à DtoBinder. –

+0

Juste modifié ma réponse originale avec quelques classes supplémentaires que j'ai utilisées dans le passé. –

1

Ne seriez-vous pas en mesure d'utiliser AutoMapper pour quelque chose comme ça? Il suffit de configurer vos cartes et il va créer de nouveaux objets et copier les valeurs dans les.

0

Il s'agit d'une question assez ancienne, mais je suis tombé dessus tout en essayant de comprendre comment le classeur par défaut fonctionne réellement.

J'ai un projet sur CodeProject qui fait réellement ce que vous voulez (ed), have a look.

À la votre!

Questions connexes