Creating html controls on the fly (reflection?) - c#

The first part of my web app was creating an interface where the user can create field names and the data type to associate with the field names.
Now I need to create the 2nd part which is pulling those field names from the database along with the data types associated with them and creating html controls on the fly using those fields names/data types. For example, if one of the field names is "birthdate" and the data type is "datetime", then my view should automatically create a html textbox with name attribute "birthdate". If a field name is "Active" and the data type is a boolean, the view should automatically create a checkbox with name attribute "Active". Anyone have any suggestions on how to do this in MVC? I'm assuming I need to use reflection and that when I have to post back to data, I will have to send back a json object.

you can use mvc htmlhelpers. for example a flexible htmlhelper for dropdownlist that accept collection and other parameters. another htmlhelper to get collection and delivers listbox and .....
and in your view you can use of this htmlhelpers by their types.

I didn't create my own htmlhelpers, but I did something similar. I used string builder to dynamically create the html in the get method of my controller and then posted that to the view.

Related

Binding to a name that is not a legal C# variable name

I'm using the Google ReCaptcha element on a form. ReCaptcha adds a parameter to the POSTed parameters named g-recaptcha-response, which the controller needs to retrieve. Since this parameter name is not a legal C# variable name, it seems that the only way to retrieve its value is via Request.Params["g-recaptcha-response"] (rather than via model binding to a property in the view model).
Now, my problem is that elsewhere in the POSTed parameters I have a couple of form fields that may contain HTML markup. I have annotated the associated properties in my view model with [AllowHtml], which prevents the model binder from throwing an HttpRequestValidationException if the user enters HTML markup into the form. But [AllowHtml] apparently only works in the model binder. If the user has entered HTML markup into the form, then I get an HttpRequestValidationException when I reference Request.Params to fetch the ReCaptcha response.
As near as I can tell, the only way I can fetch the ReCaptcha response while still allowing HTML markup in selected POST parameters is to use go through the pain of writing a custom model binder (e.g. https://stackoverflow.com/a/4316327/1637105) to allow me to bind a property in my view model to an alias (in my case, a property name that is not a valid C# variable name).
The point of this question is just to confirm that I really do need to go to the pain of implementing a custom model binder.
Any suggestions or alternate solutions are more than welcome!
EDIT:
It occurs to me that another solution would be to figure out a way to fetch the value from the POSTed parameters without triggering (or while handling) the HttpRequestValidationException.
You can use the Unvalidated property of Request to access values without triggering Request Validation. for example
var captcha = Request.Unvalidated.Form["g-recaptcha-response"];

How to display access model/viewmodel's fields programmatically in View in ASP.NET MVC

Background
My ASP.NET MVC application allows users to create custom reports and select things like fields to display, order of fields etc. A View should be able to read those custom report configurations and display the model fields accordingly.
Example
1) Let's say we have a model called Person - Id, Name, Age, Address, Height.
2) Let's say the custom report configuration is in a model called CustomReportConfig - Shows only Age, Name and height (in that order).
Now, what should happen in the View is something like (assuming there exists a ViewModel that contains both Person and CustomReportConfig)
foreach(string fieldName in #model.ViewModel.CustomReportConfig)
#model.ViewModel.Person.**fieldName**
As you notice, the fieldName part in the above code is a string variable but in Views this should be statically typed.
Question
Is it possible to use a variable for the fieldName part in #model.Person.fieldName in the above code?
Note: I understand that this can be done by if else conditions for each field or reflection or creating a generic DataTable type of object in ViewModel etc but I'm wondering it there's a better way to do it by just creating the the fieldName in #model.Person.fieldName programmatically.
Perhaps keep a list of fields / property names, and use reflection to grab the property?
Probably a neater way to do it would be to keep a list of objects that each implement some interface, and then just loop over the list.
foreach (IMyCustomInterface obj in #model.ViewModel.CollectionOfCustomReportConfigs)
#obj.ToRenderedString()

MVC form view for eav database

I want to write a form to submit data about people that could have a greatly varying amount of fields, it is getting this data from an eav database. My idea was to write a model with a Dictionary of parameters. Something like
public class MyModel
{
public Dictionary<string,string> Parameters {get;set;}
}
Where the key would be the parameter name and the value would be the value. Then in the view I would just create a Html.TextBoxFor(...) each parameter in the dictionary and submit the form. The model would also handle stuff like populating the dictionary etc.
Another intern told me I should just use json and ajax/angularjs. The form isn't smart at all, just a big list of fields you have to fill in then submit.
Is there a downside to doing it just in razor and server code in this case?
If you are just editing preexisting data, you don't have to add any new data, then doing it with pure razor should be just fine, check this question, I think it will help you. However if you have dynamically add or delete, some pairs then this approach will not be enough and you should consider listening to the other intern.

How to get HTML annotations from DataAnnotations from a class that is not part of a model?

How do I get hold of the html annotations (data-val="true" data-val-required="Required") from a class that is not part of the whole PAGE model.
I use the class to populate a GridView that has it's values stored in a Session Variable.
When I use TextBoxFor(x=>x.Name) for the gridview, I do not get the html annotations generated like in the rest of the page.
The code below does not help me at all.
var metadata = ModelMetadata.FromLambdaExpression(expression,helper.ViewData);
string prefix = ExpressionHelper.GetExpressionText(expression);
You should not make any calls to Session object from inside the view. Instead you should express this data as part of your viewmodel and fill it in controller.
In fact, you should not use any data that's not part of your viewmodel.

DataForm, DropBox and data annotations (description and such)

I've got a DataForm in which I replace some TextBox fields with DropBoxes to imitate a lookup using the AutoGeneratingField event.
However, when I do that, I loose any data annotations that could otherwise be used (such as a description which I specified in my data model).
Is there a way to get these values from the data model without resorting to auto-generated fields? The DataFormAutoGeneratingFieldEventArgs parameter doesn't seem to contain them.
Set the DataField.PropertyPath property to the name of the model property with metadata.

Categories