Bind a business object to an ASP. NET Form Control Using Reflection. Release Date: 12/10/2004 | Updated on: 12/10/2004
John Dyer
Dallas Theological Seminary
Applicable:
Microsoft Visual Studio 2005 and earlier versions
ASP. Network 1.1
C #Programming Language
Visual Basic programming language
Abstract:Use reflection as a single lineCodeBind business objects to ASP. NET web forms to reduce complexity and errors. (This article contains links to English sites. Note that in the example file,ProgramThe comments are in English. In this article, the comments are translated into Chinese to facilitate your understanding .)
Download the msdformbinding. MSI sample file.
Content on this page
|
Introduction |
|
Simplify and shorten the form code |
|
Start: retrieve the attribute list from reflection |
|
Bind object property values to controls |
|
Set the value of an unknown control with a known property |
|
Reversal Process: bindcontrolstoobject |
|
Expansion of performance and formbinding Solutions |
|
Conclusion |
|
References |
Introduction
among the most common tasks of Web developers, one task is to be executed repeatedly: create a simple form for updating database tables. We will create a list page and a form page. The list page displays records in the form of tables. The form page contains the appropriate form controls used for various database fields. Many developers also use business objects that represent database tables to organize code into multi-layer designs. If you use a Business Object ( document ) to represent a database table ( documents ), the Code for many forms looks as follows:
<SCRIPT runat = "server"> protected void page_load (Object SRC, eventargs e) {If (! Ispostback) {document = documents. getdocument (request. querystring ["entid"]); title. TEXT = document. title; active. checked = document. active; createddate. TEXT = document. createddate. tostring (); authorid. findbyvalue (document. authorid. tostring ()). selected = true ;//... htmlbody. TEXT = document. htmlbody ;}} protected void savebutton_click (Object SRC, eventargs e) {document = documents. getdocument (request. querystring ["entid"]); document. title = title. text; document. active = active. checked; document. createddate = convert. todatetime (createddate. text); document. authorid = convert. toint32 (authorid. selecteditem. value );//... and so on document. htmlbody = htmlbody. text; documents. update (document) ;}</SCRIPT>
Back to Top
Simplify and shorten the form code
In the above Code, each control is converted explicitly and set to the correct attribute of the Form Control. Depending on the number of properties and Form Controls, this part of code may become longer and difficult to manage. The code should also contain error correction for type conversionListcontrol, Which will further increase complexity. Even if the form is generated by a code generation tool (such as Eric J. Smith's excellent codesmith), it is easy to introduce errors when any custom logical relationship is required.
With reflection, you can use only one line of code to bind all the attributes of the Business Object to the corresponding form control, reducing the number of lines of code and enhancing readability. After the establishment of the reflection system, the above Code will be simplified:
Protected void page_load (Object SRC, eventargs e) {If (! Ispostback) {document = documents. getdocument (request. querystring ["entid"]); formbinding. bindobjecttocontrols (document) ;}} protected void save_click (Object SRC, eventargs e) {document = documents. getdocument (request. querystring ["entid"]); formbinding. bindcontrolstoobject (document); statements. update (document );}
This code can be used for all standard ASP. NET controls (Textbox,Dropdownlist,CheckboxAnd many third-party controls (such as free textbox and calendar popup ). Regardless of the number of Business Object Attributes and Form Controls, this line of code provides all the functions required, as long as the Form Control ID matches the Business Object attribute name.
Back to Top
Start: retrieve the attribute list from reflection
First, we need to check the properties of the Business Object and find the ASP. Net Control with the same ID as the property name of the business object. The following code forms the foundation for binding search:
Public class formbinding {public static void bindobjecttocontrols (Object OBJ, control container) {If (OBJ = NULL) return; Type objtype = obj. getType (); propertyinfo [] objpropertiesarray = objtype. getproperties (); foreach (propertyinfo objproperty in objpropertiesarray) {control = container. findcontrol (objproperty. name); If (control! = NULL) {// processing control ...}}}}
In the above Code, the methodBindobjectstocontrolsAccept the Business Object OBJ and a container control. The container control is usually the current web formPageObject. If the version used changes the ASP. NET 1.x masterpages of the control nesting order at runtime, you must specifyContentControl. This is in ASP. NET 1.x,FindcontrolMethod for nested controls and named containers.
In the above Code, we obtainTypeAnd then useTypeTo obtainPropertyinfoObject array. EachPropertyinfoThe object contains information about the attributes of the business object and the ability to obtain and set values from the business object. We use the foreach loop to check the attributes of the attributes with the Business Object (Propertyinfo. Name) The container of the ASP. Net Control corresponding to the ID attribute. If a control is found, the property value is bound to the control.
Back to Top
Bind object property values to controls
Most of the operations in the process are performed in this phase. We need to fill in the found control with the property value of the object. One way is to create an IF... else statement for each control type. Derived fromListcontrol(Dropdownlist,Radiobuttonlist,CheckboxlistAndListBox. If the widget isListcontrol, We can use itListcontrolAnd then set the selected items:
Control control = container. findcontrol (objproperty. Name); If (control! = NULL) {If (control is listcontrol) {listcontrol = (listcontrol) control; string propertyvalue = objproperty. getvalue (OBJ, null ). tostring (); listitem = listcontrol. items. findbyvalue (propertyvalue); If (listitem! = NULL) listitem. Selected = true;} else {// process other control types }}
Unfortunately, other control types are not derived from the parent class. The following public controls have. TextString attributes:Textbox,LiteralAndLabel. However, this property is not derived from the public parent class, so you need to convert each control type separately. We also need to convert other control types, suchCalendarControls to use the appropriate properties (inCalendarIn the example, yesSelecteddateAttribute ). To include all standard ASP. NET Form Controls and access the correct properties of the form controls, there is no need for too many lines of code.
If (control is listcontrol) {listcontrol = (listcontrol) control; string propertyvalue = objproperty. getvalue (OBJ, null ). tostring (); listitem = listcontrol. items. findbyvalue (propertyvalue); If (listitem! = NULL) listitem. selected = true;} else if (control is checkbox) {If (objproperty. propertytype = typeof (bool) (checkbox) control ). checked = (bool) objproperty. getvalue (OBJ, null);} else if (control is calendar) {If (objproperty. propertytype = typeof (datetime) (calendar) control ). selecteddate = (datetime) objproperty. getvalue (OBJ, null);} else if (control is textbox) {(textbox) control ). te XT = objproperty. getvalue (OBJ, null). tostring ();} else if (control is literal) (//... and so on. It can also be used for tags and other attributes .}
This method fully covers the standard ASP. NET 1.x controls. From this perspective, we have all the functionsBindobjecttocontrolsMethod. But at the same time, the application scope of this method is limited, because it only takes into account the built-in ASP. NET 1.x control. To support new ASP. NET 2.0 controls or use any third-party controlsFormbindingProject, and add the control type to the IF... else list.
The solution to this problem is to use reflection for the second time to view the properties of each control and find out whether the control has the property type corresponding to the property type of the business object.
Back to Top
Set the value of an unknown control with a known property
As described above, some controls share string attributes.. Text, Most Form Controls use this property in essentially the same way. This attribute is used to obtain and set user input data. A large number of controls also use other public attributes and property types. The following are some of these attributes:. SelecteddateOfDatetimeAttribute, which is used in many calendar and date selector controls.. CheckedIt is used in a boolean control.. ValueIt is common in hidden controls. These four attributes (String text,String Value,Bool checkedAndDatetime selecteddate) Is the most common control property. If the system can be designed to bind any control type to these attributes, our binding method applies to any control that uses those four attributes.
In the following code, we will use reflection for the second time (this time for Form Controls, rather than for Business Objects) to determine whether it has any common attributes. If yes, set the property value of the business object to the property of the control. As an example, we will iterate the entire propertyinfo array and find. Text. If the control has this property, data is sent from the Business Object to the property of the control.
If (control is listcontrol ){//...} else {// obtain the type and attribute of the control // type controltype = control. getType (); propertyinfo [] controlpropertiesarray = controltype. getproperties (); // query. text properties // foreach (propertyinfo controlproperty in controlpropertiesarray) {If (controlpropertiesarray. name = "text" & controlpropertiesarray. propertytype = typeof (string) {// set the control. text property // controlproperty. setvalue (control, (string) objproperty. getvalue (OBJ, null), null );}}}
If. Text, UsePropertyinfoClassGetvalueMethod to retrieve the value from the business object attributes. Then, use. TextAttributeSetvalueMethod. Here, we also use the type command to set the property of the control to typeof (string), and use the (string) symbol to explicitly convert the value from the property.
to complete the bindobjecttocontrols method, we also need to process other public attributes, that is, . checked , . selecteddate and . value . In the following code, we package the control property search to an auxiliary method called findandsetcontrolproperty to simplify the code.
If (control is listcontrol ){//...} else {// get control attributes // type controltype = control. getType (); propertyinfo [] controlpropertiesarray = controltype. getproperties (); bool success = false; success = findandsetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "checked", typeof (bool); If (! Success) Success = findandsetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "selecteddate", typeof (datetime); If (! Success) Success = findandsetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "value", typeof (string); If (! Success) Success = findandsetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "text", typeof (string);} Private Static void findandsetcontrolproperty (Object OBJ, propertyinfo objproperty, control, propertyinfo [] controlpropertiesarray, string propertyname, type) {// iterate foreach (propertyinfo controlproperty in controlpropertiesarray) in the entire control attribute {// check the matched name and type if (controlpropertiesarray. name = "text" & controlpropertiesarray. propertytype = typeof (string) {// set the property of the control to // The Business Object Property Value controlproperty. setvalue (control, convert. changetype (objproperty. getvalue (OBJ, null), type), null); Return true ;}} return false ;}
The order of the above attribute checks is very important, because some controls have multiple of the above attributes, but we only want to set one. For example,CheckboxControls. TextAttributes are also available. CheckedAttribute. In this example, we want to use. CheckedAttribute instead. TextAttribute. CheckedIn the order of attribute search. In any case, if a control property with the correct name and type is found, set the property of the control to the value of the business object property.
From this perspective, we have all the functionsBindobjecttocontrolsMethod. With this method, we can call any combination of classes and controls anywhere on the aspx form, which is indeed effective. Now, we need to create a method to reverse when submitting the form. We need to retrieve the new value from the control that represents the user input, instead of setting the value of the control property to the value of the business object.
Back to Top
Reversal Process: bindcontrolstoobject
InBindcontrolstoobjectMethod, we will start in the same way, that is, retrieve the attribute list from the business object, and then useFindcontrolMethod to find the control with an ID that matches the object property. If the control is found, the value is retrieved and returned to the business object. This section will also containListcontrolBecause these controls have public interfaces. We will use another helper method to search for and retrieve the value in the control, and then return the value to the business object.
Public static void bindcontrolstoobject (Object OBJ, control container) {type objtype = obj. getType (); propertyinfo [] objpropertiesarray = objtype. getproperties (); foreach (propertyinfo objproperty in objpropertiesarray) {If (control is listcontrol) {listcontrol = (listcontrol) control; If (listcontrol. selecteditem! = NULL) objproperty. setvalue (OBJ, convert. changetype (list. selecteditem. value, objproperty. propertytype), null);} else {// get control attributes // type controltype = control. getType (); propertyinfo [] controlpropertiesarray = controltype. getproperties (); bool success = false; success = findandgetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "checked", typeof (bool); If (! Success) Success = findandgetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "selecteddate", typeof (datetime); If (! Success) Success = findandgetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "value", typeof (string); If (! Success) Success = findandgetcontrolproperty (OBJ, objproperty, control, controlpropertiesarray, "text", typeof (string) ;}} Private Static void findandgetcontrolproperty (Object OBJ, propertyinfo objproperty, control, propertyinfo [] controlpropertiesarray, string propertyname, type) {// iterate foreach (propertyinfo controlproperty in controlpropertiesarray) in the entire control attribute) {// check the matched name and type if (controlpropertiesarray. name = "text" & controlpropertiesarray. propertytype = typeof (string) {// set the property of the control to // the property value of the business object try {objproperty. setvalue (OBJ, convert. changetype (controlproperty. getvalue (control, null), objproperty. propertytype), null); Return true;} catch {// The data from the Form Control // cannot be converted to // objproperty. propertytype return false ;}}return true ;}
After the two methods are completed, the form syntax is simplified, as described in the preceding simplified and simplified form code. The type conversion and Error Correction of each property and control are automatically performed. The two methods (BindobjecttocontrolsAndBindcontrolstoobject) Provides great flexibility for developers to create forms. They can also be used to handle the following common solutions:
• |
If you add a new property to a business object and want to access the new property on the form, developers only need to add the control to the page and set the Control ID as the name of the new property,FormbindingMethod will process all the rest. |
• |
If a developer needs to change the type of the control used for a specific property, for exampleTextboxTo change to a third-party HTML editor control, he/she only needs to ensure that the new control has one of the preceding attributes (for example. Text), The form will work in exactly the same way as before. |
• |
Use allTextboxThe widget can also quickly generate a form, but the input will still be converted to the correct type applicable to the business object attributes. For example, you can useTextboxControl to replaceCalendarControl or a third-party date selector control. If you enter the datetime string as the valueTextboxOf. TextConvert the value in the property to datetime, just as it is on the calendar ControlSelecteddateSame attributes. If youTextboxChanged to the date selector control, and the logical relationship remains unchanged. |
• |
By changing all controlsLiteralYou can also quickly create a "View" page.LiteralOf. TextThe property will be set as the value of the business object property, just as it isTextboxSame. |
• |
In the actual solution, the form also contains other data types and custom configurations. The code used to process these specific operations can be placed inBindobjecttocontrolsAndBindcontrolstoobject. |
Back to Top
Expansion of performance and formbinding Solutions
Some developers may want to know whether the performance degradation caused by reflection is worthwhile. In my tests, I used objects with seven attributes (INT categorentid, bool active, datetime created, int categoryid, String title, string author, and string htmltext,BindobjecttocontrolsIt takes about 1/3 milliseconds,BindcontrolstoobjectIt takes about 1 ms. These values are run 1000 times in a loop.BindobjecttocontrolsAndBindcontrolstoobjectMethod. For common "add" and "edit" forms solutions, such performance should not cause any major problems, and it can indeed improve the development speed and flexibility.
Although this method applies to almost every form, you may need to modify the above Code. In some schemes, the control to be used by developers may not use one of the above attributes as its main interface. In this case, you need to updateFormbindingTo include the property and type.
Back to Top
Conclusion
These two typesFormbindingMethod (BindobjecttocontrolsAndBindcontrolstoobject) Can be used to greatly simplify the form code, and provide maximum flexibility for ASP. NET form development. I have benefited a lot from their use and hope your team can also benefit from them.
Back to Top
References
• |
ASP. NET unleashed |
• |
Programming Microsoft ASP. NET |
Author Profile
JOHN Dyer is the top Web Developer of Dallas theological seminary and is responsible for guiding their prestigious Online Training Program, which is built on the Community Server of telligent system. He is also the author of freetextbox, a widely used ASP. net html editor. This control brings economic benefits to many people except him. In his spare time, he studied for a master's degree in Theology in Dallas, and was preparing for a wedding in January 1, 2005.