ASP.NET Web Binder Model

For several years I have been developing ASP.NET web forms. I was spoiled by my own library, which allowed me to do things like:

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

The conceptual code did something very similar to what the MVC Model Binder does, i.e. the data exposed in the form as input will populate the user object. In principle, he freed the developer from executing monkey code, for example

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

etc.

Now this proprietary library is not available in the new project that I am associated with, and this is a web forms project. So I'm wondering if there is a way to use System.Web.Mvc.DefaultModelBinder in the context of web forms. The goal is to achieve a simple and simple set of controls from and to domain objects, ideally with validation annotations. If this is not possible, can someone point me to an open source solution to solve this problem. I really don't want to rewrite such code.

Thanks in advance.

+6
webforms defaultmodelbinder
source share
3 answers

Sherlock, you will encounter some problems trying to use ModelBinder from MVC, as they rely on ControllerContext.

I answered a similar question before ChangeType, Convert - Converting from one type to another , but this is really what you are looking for.

Check out this blog post on your blog ChangeType - changing a variable type in C #

Essentially, you get a single method called ChangeType<T> that returns the value of the parameter you are looking for in a strongly typed way or the default value if the parameter does not exist.

Now, with regard to custom classes (mainly DTO class classes), if you don't mind using reflection, then I have a solution that will handle most custom classes. The DtoBinder class mentioned at the end of the work will be well executed.

In fact, the last 3 code lists contain all the code you need to handle almost all of your needs in a typical web application scenario. In addition, it is extensible, so if you need to implement your own binder, you can do it very simply and register your binder with RequestBinder from anywhere in your application.

So, if you do not want to use reflection for some commonly used DTO objects, you can implement a binder for the type and register it, and from now on, your custom binder will be used on it. In many ways, this is similar to the MVC ModelBinder in concept.

Edited -

Below is a single .cs file with a bunch of classes that I used in the past to do exactly what you need. The first MsPropertyAssignerProvider is the one with which you will work from your page.

You will iterate over the controls and call the GetPropertyAssigner method, passing it the name of the control type. This method returns an instance of ObjectPropertyAssigner, which has one SetPropertyValue method, which you can pass to the object instance and control instance.

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

The accompanying class is shown below.

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

Sorry, no matter what I do, the editor completely messed up the code list. But I hope this helps.

+1
source share

Could you not use AutoMapper for something like that? Just set up your maps and create new objects and copy them into them.

+1
source share

This is a rather old question, but I came across it, trying to understand how the default connecting device really works.

I have a CodeProject project that really does what you want (ed) to see .

Hooray!

0
source share

All Articles