2010-09-09 52 views
6

對於幾年我做的ASP.NET Web形式的發展,我被一個專有庫被寵壞了,這讓我做這樣的事情號:模型綁定在ASP.NET web表單

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

概念代碼做了一件非常類似於MVC Model Binder所做的,即給定表單的張貼值作爲輸入,它將填充自定義對象。基本上它釋放開發商從做猴子代碼如

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

等..

現在,這個專有庫不可用在新項目我參加,這是一個Web表單項目。所以我想知道在Web表單的上下文中是否有使用System.Web.Mvc.DefaultModelBinder的方法。目標是實現來自域對象和後面的控制的簡單且容易的控制,理想情況下考慮到驗證註釋。 如果這樣做是不可能的,那麼有人可以將我指向開源解決方案來解決這一需求。我真的不想重寫這樣的代碼。

在此先感謝。

回答

1

Sherlock,你會遇到一些問題,試圖從MVC使用ModelBinder,因爲它們依賴於ControllerContext。

我以前回答過類似的問題ChangeType, Convert - Converting from one type to another但它確實是你在找什麼。

退房這篇博客我的博客上 ChangeType – Changing the type of a variable in C#

從本質上講,你會得到一個名爲ChangeType<T>一個方法,返回你在一個強類型的方式尋找參數,或者如果缺省值的值參數不存在。

現在就自定義類(主要是DTO類型類)而言,如果您不介意使用反射,那麼我也有一個解決方案來處理大多數自定義類。 DtoBinder類很好地提到了意願工作的結尾。

本質上,最後3個代碼清單包含您需要的所有代碼,以便處理典型Web應用程序場景中幾乎所有的需求。另外它是可擴展的,所以如果你需要實現你自己的綁定,你可以很簡單地做到這一點,並從您的應用程序的任何位置註冊您的綁定與RequestBinder。

因此,如果您不想對某些常用的DTO對象使用反射,則可以爲該類型實現一個活頁夾並進行註冊,並從該點開始使用您的自定義活頁夾。在許多方面,它與概念上的MVC ModelBinder相似。

編輯 -

下面是一個使用的.cs一堆類,我已經在過去用來做正是你需要的文件。第一個MsPropertyAssignerProvider是你在頁面中使用的那個。

您將迭代您的控件並調用GetPropertyAssigner方法,並將其傳遞給控件的類型名稱。此方法返回ObjectPropertyAssigner的一個實例,該實例有一個名爲SetPropertyValue的方法,您可以將對象實例和控件實例傳遞給該方法。

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

所附類下面列出

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

對不起,不管我做什麼編輯器完全弄亂了代碼清單。但我希望這有助於。

+0

只有第一段和最後一段與提出的問題有些相關。我不介意使用反射。這是專有圖書館的工作方式。 – Sherlock 2010-11-09 03:56:55

+0

我想你的情況是因爲你正在使用控件,解決方案涉及更多一點。 DtoBinder類可以創建Dto對象的實例併爲給定的NameValues集合分配所有屬性值。所以你需要做的是從控件的名字和值中組合這個集合,並把它傳遞給DtoBinder。 – 2010-11-09 07:05:53

+0

剛剛編輯了我原來的答案,並附加了我以前使用過的其他類。 – 2010-11-09 07:18:26

1

難道你不能使用AutoMapper來做這種事嗎?只需設置你的地圖,它會創建新的對象並將值複製到它們中。

0

這是一個相當古老的問題,但我試圖弄清楚默認的模型綁定器是如何工作的。

我在CodeProject上有一個項目,它實際上做了你想要的(編輯),have a look

乾杯!