4

I am using ASP.NET MVC and there's a need to creates new views during runtime based on user selections. These views once created, need to be saved in storage so that they can be reused. I prefer these views to be strongly typed. Naturally the model class for each new view doesn't exist and these classes will have new properties according to what the user creates.

For example, if a user selects a textbox and wants it to be used for firstname, eventually I would like to have a class created dynamically with a public property called FirstName... and so on. Everything is created on the fly.

I would like to get ideas on how to approach this. Would Dynamic Source Code Generation and Compilation work for this workflow or is this complicating it more than it should?

Update:
One use case is if a form is needed to be created based on a user selection of a database table. If there are hundreds of tables, I won't be creating hundreds of views. I know I can maybe use a gridview in this example but for all the cases, a dynamic view is more appropriate.

Tony_Henrich
  • 42,411
  • 75
  • 239
  • 374
  • Why don't you use generic views and models? – brainless coder Jun 04 '15 at 00:14
  • I will have form elements which bind to the model class – Tony_Henrich Jun 04 '15 at 00:23
  • You can use custom binders as mentioned here http://stackoverflow.com/questions/1487005/asp-net-mvc-model-binder-for-generic-type?answertab=active#tab-top and http://bradwilson.typepad.com/blog/2010/10/service-location-pt9-model-binders.html – brainless coder Jun 04 '15 at 00:29
  • 2
    You're asking the wrong questions. You've already decided you want to follow a specific approach, and you have no idea how to make that work, so you're asking how to make that approach work... but in reality you need to be asking about how to solve your actual problem (which is not necessarily dynamic code generation). What you should be doing is asking about the features you actually want to develop.. not the technology you want to implement. Can you explain exactly what you want to do, and what its purpose is? – Erik Funkenbusch Jun 04 '15 at 01:44
  • 2
    @Erik I want to create views on the fly. I already explained why this is needed. Users could be creating forms in real time based on what they want to see. Then I said I would like to have the elements bound to a model class so that they can be easily saved and reused. These are the features. Then I asked if code generation is a good approach. I think I made myself clear. Maybe you need to ask specific questions if you don't understand what I am trying to say. – Tony_Henrich Jun 04 '15 at 02:33
  • 4
    "Creating forms in real-time based on what they want to see" doesn't imply that you need any code generation of any kind. I was asking for specifics because that's way too vague. For instance, you could simply have a collection of "CustomForm" objects in your model, and these can be a hierarchy of derived types all in a base collection. You can then use Editor and Display templates to render those types, no code generation required, and you still get strong typing. This is my point in that you're immediately jumping to an implementation that is uncalled for, and complex. – Erik Funkenbusch Jun 04 '15 at 03:48

1 Answers1

1

Your user selections are data, not code:

  • Create data-structures based on the user selections.
  • Save them in a database for later.
  • Write a view which takes those data-structures (as a model) and displays them.
  • EditorTemplates can be used to display each individual control, using strongly-typed views.

Data

 public class Page
 {
     public List<Control> Controls { get; set; }
 }

 public class Textbox : Control
 {
     public string Label { get; set; }
     public string Value { get; set; }
 }

Page.cshtml

@model Page

@for (int i 0; i < Model.Controls.Count; i++)
{
     // Render using the EditorTemplate view for the control's type
     @Html.EditorFor(m => m.Controls[i])
}

EditorTemplates/Textbox.cshtml

@model Textbox

@Html.HiddenFor(m => m.ControlId)

@Html.LabelFor(m => m.Value, Model.Label)
@Html.TextBoxFor(m => m.Value)