Dynamic form with no real OOP or objects? - c#
I am tacking a large refactor of a project, and I had asked this question to confirm/understand the direction I should go in and I think I got the answer that I wanted, which is not to throw away years worth of code. So, now begins the challenge of refactoring the code. I've been reading Martine Fowler and Martin Feathers' books, and they have a lot of insight, but I am looking for advice on the ultimate goal of where I want the application to be.
So to reiterate the application a little bit, its a dynamic forms system, with lots of validation logic and data logic between the fields. The main record that gets inserted is the set of form fields that is on the page. Another part of it is 'Actions' that you can do for a person. These 'Actions' can differ client by client, and there are hundreds of 'Actions'. There is also talk that we can somehow make an engine that can eventually take on other similar areas, where a 'person' can be something else (such as student, or employee). So I want to build something very de-coupled. We have one codebase, but different DBs for different clients. The set of form fields on the page are dynamic, but the DB is not - it is translated into the specific DB table via stored procs. So, the generic set of fields are sent to the stored proc and the stored proc then decides what to do with the fields (figure out which table it needs to go to). These tables in fact are pretty static, meaning that they are not really dynamic, and there is a certain structure to it.
What I'm struggling specifically is how to setup a good way to do the dynamic form control page. It seems majority of the logic will be in code on the UI/aspx.cs page, because its loading controls onto the webpage. Is there some way I can do this, so it is done in a streamlined fashion, so the aspx.cs page isn't 5000 lines long? I have a 'FORM' object, and one of the properties is its' 'FIELDS'. So this object is loaded up in the business layer and the Data layer, but now on the fron end, it has to loop through the FIELDS and output the controls onto the page. Also, someway to be able to control the placement would be useful, too - not sure how do get that into this model....
Also, from another point of view - how can I 'really' get this into an object-oriented-structure? Because technically, they can create forms of anything. And those form fields can represent any object. So, for example, today they can create a set of form fields, that represent a 'person' - tomorrow they can create a set of form fields that represent a 'furniture'. How can I possibly translate this to to a person or a furniture object (or should I even be trying to?). And I don't really have controls over the form fields, because they can create whatever....
Any thought process would be really helpful - thanks!
How can I possibly translate this to to a person or a furniture object
(or should I even be trying to?)
If I understand you correctly, you probably shouldn't try to convert these fields to specific objects since the nature of your application is so dynamic. If the stored procedures are capable of figuring out which combination of fields belongs to which tables, then great.
If you can change the DB schema, I would suggest coming up with something much more dynamic. Rather than have a single table for each type of dynamic object, I would create the following schema:
Object {
ID
Name
... (clientID, etc.) ...
}
Property {
ID
ObjectID
Name
DBType (int, string, object-id, etc.)
FormType ( textbox, checkbox, etc.)
[FormValidationRegex] <== optional, could be used by field controls
Value
}
If you can't change the database schema, you can still apply the following to the old system using the stored procedures and fixed tables:
Then when you read in a specific object from the database, you can loop through each of the properties and get the form type and simple add the appropriate generic form type to the page:
foreach(Property p in Object.Properties)
{
switch(p.FormType)
{
case FormType.CheckBox:
PageForm.AddField(new CheckboxFormField(p.Name, p.Value));
break;
case FormType.Email:
PageForm.AddField(new EmailFormField(p.Name, p.Value));
break;
case FormType.etc:
...
break;
}
}
Of course, I threw in a PageForm object, as well as CheckboxFormField and EmailFormField objects. The PageForm object could simply be a placeholder, and the CheckboxFormField and EmailFormField could be UserControls or ServerControls.
I would not recommend trying to control placement. Just list off each field one by one vertically. This is becoming more and more popular anyway, even with static forms who's layout can be controlled completely. Most signup forms, for example, follow this convention.
I hope that helps. If I understood your question wrong, or if you'd like further explanations, let me know.
Not sure I understand the question. But there's two toolboxes suitable for writing generic code. It's generics, and it's reflection - typically in combination.
I don't think I really understand what you're trying to do, but a method using relfection to identify all the properties of an object might look like this:
using System.Reflection;
(...)
public void VisitProperties(object subject)
{
Type subjectType = subject.GetType();
foreach (PropertyInfo info in subjectType.GetProperties()
{
object value = info.GetValue(subject, null);
Console.WriteLine("The name of the property is " + info.Name);
Console.WriteLine("The value is " + value.ToString());
}
}
You can also check out an entry on my blog where I discuss using attributes on objects in conjunction with reflection. It's actually discussing how this can be utilized to write generic UI. Not exactly what you want, but at least the same principles could be used.
http://codepatrol.wordpress.com/2011/08/19/129/
This means that you could create your own custom attributes, or use those that already exists within the .NET framework already, to describe your types. Attributes to specify rules for validation, field label, even field placement could be used.
public class Person
{
[FieldLabel("First name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(1)]
[FormRow(1)]
public string FirstName{get;set;}
[FieldLabel("Last name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(2)]
[FormRow(1)]
public string LastName{get;set;}
}
Then you'd use the method described in my blog to identify these attributes and take the apropriate action - e.g. placing them in the proper row, giving the correct label, and so forth. I won't propose how to solve these things, but at least reflection is a great and simple tool to get descriptive information about an unknown type.
I found xml invaluable for this same situation. You can build an object graph in your code to represent the form easily enough. This object graph can again be loaded/saved from a db easily.
You can turn your object graph into xml & use xslt to generate the html for display. You now also have the benefit of customising this transform for differnetn clients/versions/etc. I also store the xml in the database for performance & to give me a publish function.
You need some specific code to deal with the incoming data, as you're going to be accessing the raw request post. You need to validate the incoming data against what you think you was shown. That stops people spoofing/meddling with your forms.
I hope that all makes sense.
Related
Create object names dynamically
I am building web service in C# for a particular application, I have a XML definition of module. I have created a class called Field that holds the properties of all fields on a module. What I would like to do is create the field objects but name them dynamically then add them to a list of some sort. So when I reference them from the client it would be like this: Module.Fields.MyDynamicName.FieldProperty Is this possible to do? and could anyone point me in the right direction on how to do this. Hope my question makes sense.
Basically you need to design for "deferred design", which means you do not know at compile time what the design is, but you still need to accommodate it. There are probably a few ways but what I have done in the past is use a dictionary list of Key/Value pairs to store fields. Using serialization (I prefer Json) you can shove just about anything into a string and store it as the Value, then deserialize it when you need it.
Building a string representation of an object using a "mask" or user supplied Format String
I'm not really sure what tags should be on this sort of question so feel free to give me some suggestions if you think some others are more suited. I have a dynamic object with an unknown number or properties on it, it's from a sort of dynamic self describing data model that lets the user build the data model at runtime. However because all of the fields holding relevant information to the user are in dynamic properties, it's difficult to determine what should be the human readable identifier, so it's left up to the administrator. (Don't think it matters but this is an ASP.NET MVC3 Application). To help during debugging I had started decorating some classes with DebuggerDisplayAttribute to make it easier to debug. This allow me to do things like [DebuggerDisplay(#"\{Description = {Description}}")] public class Group to get a better picture of what a specific instance of an object is. And this sort of setup would be perfect but I can't seem to find the implementation of this flexibility. This is especially useful on my dynamic objects because the string value of the DebuggerDisplayAttribute is resolved by the .NET framework and I have implementations of TryGetMember on my base object class to handle the dynamic aspect. But this only makes it easier for development. So I've added a field on what part of my object is still strongly typed and called it Title, and I'd like to let the administer set the implementation using their own format, so to speak. So for example they might build out a very simplistic rental tracking system to show rentals and they might specify a format string along the lines of "{MovieTitle} (Due: {DueDate})" I would like that when they save the record to add some logic to first update the Title property by resolving the format string to substitute each place holder with the value of the appropriate property on the dynamic object. So this might resolve to a title of "Inception (Due: May 21, 2011)", or a more realistic scenario of a format string of "{LastName}, {FirstName}" I don't want the user to have to update the title of a record when they change the first name field or the last name field. I fully realize this will likely use reflection but I'm hoping some one out there can give me some pointers or even a working example to handle complex format strings that could be a mix if literal text and placeholders. I've not had much luck looking for an implementation on the net that will do what I want since I'm not really sure what keywords would give me the most relevant search results?
You need two things: 1) A syntax for formatting strings You have already described a syntax where variables are surrounded by bracers, and if you want to use that you need to build a parser that can parse that. Perhaps you also want to add ways to specify say a date or a number format. 2) Rules for resolving variables If there is a single context object you can use reflection and match variable names to properties but if your object model is more complex you can add conventions for searching say a hierarchy of objects. If you are planning to base your model objects on dynamic chances are that you will find the Clay library on CodePlex interesting.
3 layer architechture and little details like dropdown lists
So I am refactoring a little application as an example to get more practice. The purpose of the application (let's say) is to collect the data from a "sign up new user" form, save it in the database. The only limitation I have is I have to use a special custom Data Access class which communicates directly with the database and returns the data (if applicable) in a DataTable object. I have a question regarding a little details on a form and how do they fit in into the layer architecture. For example, my form has a drop down list that's fed from the database, but at the same time drop down list doesn't represent an object per SE (unlike a User that is a object, there is a class User that has multiple methods, data members etc). I don't want to have calls to the stored procedure right there in the code behind but I also do not wish to overdo on abstraction. What would be an elegant way to take care of these little details w/o creating a class abstraction galore. Hope I am being clear
Funny you should ask that. I went through that issue here. These other Stack Overflow Questions that I've answered that show other parts (tangentially related): Getting ListView Data Items from Objects Working with ListViews Concatenating Properties in a DropDownList
An option for getting non-object data to the UI is to create one or more lookup classes that are a bucket or "service" for getting odd bits of data for things like drop down lists etc... Example: myDDL.DataSource = Lookup.GetAllCountries(); // GetAllCountries is a static method // set name/value fields etc... myDDL.DataBind(); Using this methodology, you can still support tier separation. It's not object oriented or elegant, but it is very practical.
I don't know what's best practice, but what I do is I have a utility class that has a method that takes as arguments a DropDownList object and an enum, so I do FillDropDown( ddlistPhoneType, DropDownTypes.PhoneTypes ); The utility class fills the dropdowns sometimes from the database, other times from XML, and occasionally some hardcoded values. But at least the GUI doesn't have to worry about that.
What is the most appropriate design for an object who's database key is made up of multiple columns?
Suppose I have a table in my database that is made up of the following columns, 3 of which uniquely identify the row: CREATE TABLE [dbo].[Lines] ( [Attr1] [nvarchar](10) NOT NULL, [Attr2] [nvarchar](10) NOT NULL, [Attr3] [nvarchar](10) NOT NULL, PRIMARY KEY (Attr1, Attr2, Attr3) ) Now, I have an object in my application that represents one of those lines. It has three properties on it that correspond to the three Attr columns in the database. public class Line { public Line(string attr1, string attr2, string attr3) { this.Attr1 = attr1; this.Attr2 = attr2; this.Attr3 = attr3; } public Attr1 {get; private set;} public Attr2 {get; private set;} public Attr3 {get; private set;} } There's a second object in the application that stores a collection of these line objects. Here's the question: What is the most appropriate design when referencing an individual line in this collection (from a caller's perspective)? Should the caller be responsible for tracking the index of the line he's changing and then just use that index to modify a line directly in the collection? Or...should there be method(s) on the object that says something to the effect of: public GetLine(string attr1, string attr2, string attr3) { // return the line from the collection } public UpdateLine(Line line) { // update the line in the collection } We're having a debate on our team, because some of us think that it makes more sense to reference a line using their internal index in the collection , and others think there's no reason to have to introduce another internal key when we can already uniquely identify a line based on the three attributes. Thoughts?
Your object model should be designed so that it makes sense to an object consumer. It should not be tied to the data model to the greatest extent practical. It sounds like it is more intuitive for the object consumer to think in terms of the three attributes. If there are no performance concerns that speak to the contrary, I would let the object consumer work with those attributes and not concern him with the internal workings of data storage (i.e. not require them to know or care about an internal index).
I think the base question you are encountering is how much control the user of your API should have over your data, and what exactly you expose. This varies wildly depending on what you want to do, and either can be appropriate. The question is, who is responsible for the information you wish to update. From what you have posted, it appears that the Line object is responsible the information, and thus I would advocate a syntax such as Collection.GetLine(attr1, attr2, attr3).UpdateX(newX) and so forth. However, it may be that the collection actually has a greater responsibility to that information, in which case Collection.UpdateX(line, newX) would make more sense (alternatively, replace the 'line' arg with 'attr1, attr2, attr2'). Thirdly, it is possible, though unlikely (and rarely the best design IMHO) that the API user is most responsible for the information, in which case an approach you mentioned where the user handles tracking Line indices and directly modifies information.
You do not want the calling object to "track the index of the line he's changing" - ever. This makes your design way too interdependent, pushes object-level implementation decisions off onto the users of the object, makes testing more difficult, and can result in difficult to diagnose bugs when you accidentally update one object (due to key duplications) when you meant to update another. Go back to OO discipline: the Line object that you are returning from the GetLine method should be acting like a real, first class "thing." The complication, of course, comes if you change one of the fields in the line object that is used as part of your index. If you change one of these fields, you won't be able to find the original in the database when you go to do your update. Well, that is what data hiding in objects is all about, no? Here is my suggestion, have three untouchable fields in the object that correspond to its state in the database ("originalAttr1", "originalAttr2", "originalAttr3"). Also, have three properties ("attr1", "attr2", "attr3") that start out with the same values as the originals but that are Settable. Your Getters and Setters will work on the attr properties only. When you "Update" (or perform other actions that go back to the underlying source), use the originalAttrX values as your keys (along with uniqueness checks, etc.). This might seem like a bit of work but it is nothing compared to the mess that you'll get into if you push all of these implementation decisions off on the consumer of the object! Then you'll have all of the various consumers trying to (redundantly) apply the correct logic in a consistent manner - along with many more paths to test. One more thing: this kind of stuff is done all the time in data access libraries and so is a quite common coding pattern.
What is the most appropriate design when referencing an individual line in this collection (from a caller's perspective)? If the caller is 'thinking' in terms of the three attributes, I would consider adding an indexer to your collection class that's keyed on the three attributes, something like: public Line this[string attr1, string attr2, string attr3] { get { // code to find the appropriate line... } } Indexers are the go-to spot for "How Do I Fetch Data From This Collection" and, IMO, are the most intuitive accessor to any collection.
I always prefer to just use a single column ID column even if there is a composite key that can be used. I would just add an identity column to the table and use that for look up instead. Also, it would be faster because query for a single int column would perform better than a key spanned across three text columns. Having a user maintain some sort of line index to look up a line doesn't seem very good to me. So if I had to pick between the two options you posed though, I would use the composite key.
If the client is retrieving the Line object using three string values, then that's what you pass to the getter method. From that point on, everything necessary to update the object in the database (such as a unique row ID) should be hidden within the Line object itself. That way all the gory details are hidden from the client, which protects the client from damaging it, and also protects the client from any future changes you might make to the dB access within the Line object.
Viewing a database over Collections, ORM Lists
I've been researching to find out how and what to use to get say the name's of the fields in a class, then to invoke that class and get the properties of the class, as in the field values. Give you an example, Say if I one to get one value from one record from one table, I would create an object of that class as in; DBTable<cars> cartable = new DBTable<cars>(1) //passing 1 is a dataset number cartable.GetLastRec(); OR cartable.Attributes.Key.carIdx // record index cartable.GetKeyRec(); // Now I print the value Console.WriteLine("Car number: " + cartable.Attributes.Data.number; It's easy to get one record, it's like an Object Orientated Database but not sure if it isn't, I don't have any knowledge of the database system, just that the classes are used to talk to a DLL file and pass some numbers. so far I've been testing with collections, inheriting, ORM, and nothing seams to be able to describe the very simple process going on, Even dynamic invoking objects and iterating over it's attributes What I hope do is; Datagridview => Table Classes => DLL entry points => Database If anyone has had the same challenge or maybe I have the wrong approach here, but completely lost at this stage, Any Idea's welcome Thanks in Advance btw: I'm using VS2005, .NET 2.0
The only way to do this is by providing your own PropertyDescriptorCollection. A search here or on Google, should point you in the correct direction.