2

I'm building an MVC web app to display a questionnaire to a user, and have them fill it out, and return those answers to a DB via a stored procedure.

The questions are set in the DB, and I populate a list of generic "Question" Models to send to the view.

The problem is that data that I don't bind to a "Html.EditorFor" gets lost on post back to the controller (see screenshot).

Postback Screenshot

I don't want to display any unneccessary/sensitive information on the view, and I don't need to show all Model properties, but I do need the data in those properties to send back to the DB (E.G: TableID)

Model

public class QuestionModel
{
    public int ID { get; set; }
    public string Question { get; set; }
    public string Answer { get; set; }

    // Do not want to display these properties in the view
    public int TableID { get; set; }
    public string DBName { get; set; }
}

Controller

[HttpGet]
public ActionResult Index()
{
    //I've hardcoded the model for this example, but
    this data will be fetched from a DB via a stored procedure

    List<QuestionModel> list = new List<QuestionModel>();
    QuestionModel model1 = new QuestionModel
    {
        ID = 1,
        Question = "What is your name?",
        DBName = "Form 1",
        TableID = 1
    };
    list.Add(model1);
    QuestionModel model2 = new QuestionModel
    {
        ID = 2,
        Question = "What is your favourite colour",
        DBName = "Form 2",
        TableID = 2
    };
    list.Add(model2);

    return View(list);
}
[HttpPost]
public ActionResult Index(IList<QuestionModel> model)
{

    //Call stored procedure to return user input to DB
    return View();
}

View

@model IList<MVCQuestion.Models.QuestionModel>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    @{ 

        using (Html.BeginForm())
        {
            for(int i = 0; i < Model.Count; i++)
            {
                <h2>@Model[i].Question</h2>
                @Html.EditorFor(x => Model[i].Answer);
            }
            <input type="submit" value="Submit" />
        }
    }

</body>
</html>

A "hacky" solution to this is to bind each property to a "Html.EditorFor", and set those fields to "Read Only", and "Hidden", but I feel like that is a poor solution, and a major security risk.

Is there a better solution to this?

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
LeemLime
  • 21
  • 2
  • 4
    Well, if you want the data to come back from the client, you have to give it to the client. That's normally done using `@Html.HiddenFor`. Of course, you need to validate the input before using it – Camilo Terevinto Sep 02 '18 at 19:03
  • As above but I suspect you want to revisit your design regarding having the db name and table ID in the view model as well. Depending on how this needs to work you may be better inferring it or looking it up from the question ID or maybe have the user login and use the user details to look it up (eg if this is some kind of multi-tenancy). – Matt Sep 02 '18 at 19:08
  • Search about Model and ViewModel concept: for example https://stackoverflow.com/questions/4061440/asp-net-mvc-model-vs-viewmodel – Steve Sep 02 '18 at 19:13
  • If you are only doing a partial edit then you should either 1) separate the elements that can be edited and require the client to send all of them to be updated or 2) design your `update` stored proc to only update non-null values. In SQL Server and most other data bases you can use coalescing operators to do this. Just be sure to make sure the data you are updating has changed since you read it and showed it to the user. Optimistic locking can help you there. – No Refunds No Returns Sep 02 '18 at 20:08
  • Hi all, thanks for your responses! I've taken your comments on board, and have implemented the "@Html.HiddenFor", as well as a using a ViewModel, and data validation. Once again, thanks for taking time to help. – LeemLime Sep 03 '18 at 08:31

0 Answers0