0

I am currently working on creating an MVC4 application where I want controls to be generated automatically from the database rows.

I have the table in my database containing the questions and the control type in which it should be answered by the user.

I am just thinking of a logic like

  1. Where I can get the database rows in a dataset and then foreach it, then checking the type of control it belongs and then creating the control in my View.

This is my Controller action:

Public ActionResult Index()
{
    // get the rows from the table 
    foreach(Iterate the rows)
    {
        if(controllerType1)
        {
            //stmnts
        }

        if(controllerType2)
        {
            //stmnts
        }       
    }
    return View();
}

This is just an idea of how can we build the solution. If I am going in the right way please guide me, else I am eager to know the possibilities where I can build my solution in different ways :).

3
  • 1
    You database should not contain a field for control type, but rather a field for question type (e.g. multiple choice,yes/no, text etc). Are you intending to group the types? (ie. all text, followed by all multiple choice etc? Commented Jun 15, 2015 at 10:28
  • You could do something with inheritance and editor templates (like MultipleChoiceQuestion : Question), so your controller nor your view don't have to know anything about what kind of question they're returning or rendering. This way the template will render the question in the proper way. Commented Jun 15, 2015 at 10:29
  • If there is an editor template. It would be really useful :) Commented Jun 15, 2015 at 11:25

1 Answer 1

2

You can create a editor template and pass the control list as model to the template and in the template you can iterate that list to generate the control. As i have shown below.

1->Create a class for Control Information.

public class ControlInfo
    {
        public string ControlType { get; set; }
        public string ControlID { get; set; }
        public string ControlName { get; set; }
        public string ControlValue { get; set; }
        public string ControlLabel { get; set; }
        public bool IsChecked { get; set; }
    }

2->Create an Editor Template (Partial view with control name say CustomControl.cshtml) in \Views\Shared\EditorTemplates path.

   @model List<MvcApplication2.Models.ControlInfo>
    <table>

        @foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
        {
            <tr>
                <td>@ControlInfo.ControlLabel</td>
                <td>
                @switch (ControlInfo.ControlType.ToLower())
                {
                    case "textbox":

                        <input type="text" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" />
                        break;
                    case "checkbox":
                        if (ControlInfo.IsChecked)
                        {
                            <input type="checkbox" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" checked="checked" />
                        }
                        else
                        {
                            <input type="checkbox" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" checked="checked" />
                        }

                        break;
                    default:
                        break;
                }
                </td>

            </tr>
        }

    </table>

3->Create a model for main view (say HomeModel).

 public class HomeModel
    {
        public List<ControlInfo> ControlList { get; set; }

        public void PolulateControlList()
        {
            //You can fill this list from database. 
            // For example i have filled the list manually.
            ControlList = new List<ControlInfo>();
            ControlList.Add(new ControlInfo() {ControlType="TextBox",ControlName="tbox1", ControlID="tbox1", ControlLabel="Name",  ControlValue="Martin"   });

            ControlList.Add(new ControlInfo() { ControlType = "CheckBox", ControlName = "cbox1", ControlID = "cbox1", ControlLabel="Is Correct", ControlValue = "Yes", IsChecked=true });
        }
    }

4->Consume the editor template in the main view as.

 @model  MvcApplication2.Models.HomeModel    
    @{
        ViewBag.Title = "Home Page";
    }

    @Html.EditorFor(model=>model.ControlList,"CustomControl")

5-> Call the main view in the controller ( Index here).

public ActionResult Index()
        {
            HomeModel ModelObj = new HomeModel();
            ModelObj.PolulateControlList();
            return View(ModelObj);
        }

Edit 1: For getting the posted value you need to modify the Editor Templates as below. The model properties whose name is equal to the name of the control posted as name value collection , will get automatically binded by the model binder of the mvc frame work, so for each property in the control collection i have created hidden tags and one input tag for the input value.

@model List<MvcApplication2.Models.ControlInfo>
<table>
    @{ var index = -1;}
    @foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
    {
        index++;
        <tr>
            <td>@ControlInfo.ControlLabel</td>
            <td>
                <input type="hidden" name="@("ControlList[" + index + "].ControlID")" value="@ControlInfo.ControlID" />
                <input type="hidden" name="@("ControlList[" + index + "].ControlLabel")" value="@ControlInfo.ControlLabel" />
                <input type="hidden" name="@("ControlList[" + index + "].ControlName")" value="@ControlInfo.ControlName" />
                <input type="hidden" name="@("ControlList[" + index + "].ControlType")" value="@ControlInfo.ControlType" />

                @switch (ControlInfo.ControlType.ToLower())
                {
                    case "textbox":

                        <input type="text" name="@("ControlList["+index+"].ControlValue")" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" />
                        break;
                    case "checkbox":
                         <input type="hidden" name="@("ControlList[" + index + "].ControlValue")" value="@ControlInfo.ControlValue" />
                        if (ControlInfo.IsChecked)
                        {
                            <input type="checkbox" name="@("ControlList[" + index + "].IsChecked")" id="@ControlInfo.ControlID" value="true" checked="checked" />
                        }
                        else
                        {
                            <input type="checkbox" name="@("ControlList[" + index + "].IsChecked")" id="@ControlInfo.ControlID" value="true" />
                        }

                        break;
                    default:
                        break;
                }
            </td>

        </tr>
    }

</table>

And in the main view you need to have form

@model  MvcApplication2.Models.HomeModel

@{
    ViewBag.Title = "Home Page";
}

@using(Html.BeginForm()){

@Html.EditorFor(model=>model.ControlList,"CustomControl")

 <input type="submit" name="name" value="Submit" />
}

And in controller you need to have corresponding post method

 [HttpPost]
        public ActionResult Index(HomeModel ModelObj)
        {
          // Your logic..........
            return View(ModelObj);
        }

This ModelObj will have the posted values.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot Priyank :) How will we get the posted values in the httppost index ActionMethod. Here we are using html controls in our editor template , is it possible to use aspx controls?
Yes you can get the posted value too. I will modify the the answer for that. It is possible to use the web form aspx control but not in the same manner that we use in the web form model. It is better not to use them as MVC has a lot of helper classes for controls and you can also find rich third party plugins for MVC helper or controls.
Spent hours looking for a solution to this problem of adding controls dynamically. Easy tutorial to follow. Great article Priyank

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.