3

Working on my first MVC ASP.NET project. I am wondering how I can update the model using user's inputs.

Let's say I have a model PersonModel.cs

public class PersonModel
{
    int personID;
    string firstName;
    string lastName;
    string favoriteColor;

    public PersonModel(int personID){
    this.PersonID=personID;
    //..Fetching data from DB to fill firstName and lastName using personID
    //At this point, personID,firstName and lastName are set, only the favoriteColor is missing
    }
}

Now my controller:

public class PersonController : Controller
{
    public ActionResult Index() {
    PersonModel person = new PersonModel(this.UserId());

    return View(person);
}

In my View :

@using Portail.Models
@model PersonModel

@ViewBag.Title = "Welcome page"

<h2> Hello @Model.firstName @Model.lastName </h2>        

For now it's working fine, displaying the first and last names of the user, according to the values in the DB.

I would like the user to choose a color in a list and then set this color as the favoriteColor variable in the model, and then update the DB with it. For example, by adding a drop down list:

<select>
  <option value="red">Red</option>
  <option value="blue">Blue</option>
  <option value="green">Green</option>
  <option value="yellow">Yellow</option>
</select>

How can I update my model by setting the chosen color for favoriteColor ?

Note that this is just an example, for the project I am working on I need to update a couple of variables, not just one like it's the case here. Also, it's confidential data so I don't want to pass anything in URL.

ekad
  • 14,436
  • 26
  • 44
  • 46
Melodie Gauthier
  • 685
  • 3
  • 12
  • 35

2 Answers2

4

Assuming PersonModel has a public property named FavoriteColor as below

public class PersonModel
{
    ....
    .... // other properties and methods
    ....

    public string FavoriteColor { get; set; }
}

You can add name="FavoriteColor" attribute to the <select> tag, place the <select> tag inside Html.BeginForm, and add a submit button like below

@using (Html.BeginForm("Index", "Person"))
{
    <select name="FavoriteColor">
      <option value="red">Red</option>
      <option value="blue">Blue</option>
      <option value="green">Green</option>
      <option value="yellow">Yellow</option>
    </select>
    <input type="submit" name="Save" value="Save" />
}

then add a new Index action method with [HttpPost] attribute and PersonModel as the parameter in your controller

[HttpPost]
public ActionResult Index(PersonModel model) 
{
    // here model.FavoriteColor will be what's selected in the dropdownlist

    // update your database here

    return View(model);
}

When you click the submit button, the HttpPost action method above will be executed and the value of model.FavoriteColor will be what you select in the dropdownlist. After that you can use that value to update your database.

The above code only demonstrates how to submit favorite color from your view. If you need the person id to update the database, then you need to add a hidden field that holds the person id value inside Html.BeginForm block

@using (Html.BeginForm("Index", "Person"))
{
    @Html.HiddenFor(m => m.PersonID)
    <select name="FavoriteColor">
      <option value="red">Red</option>
      <option value="blue">Blue</option>
      <option value="green">Green</option>
      <option value="yellow">Yellow</option>
    </select>
    <input type="submit" name="Save" value="Save" />
}

and you can get the person id in model.PersonID in your HttpPost action method.

Once you understand the above, you should learn to use Html.DropDownListFor to populate the dropdownlist. This would be a good place to start: Populating a razor dropdownlist from a List<object> in MVC

Community
  • 1
  • 1
ekad
  • 14,436
  • 26
  • 44
  • 46
  • Thanks! It didn't work at first, the favoriteColor was null for the model object but once I added {get; set} (public string favoriteColor { get; set; }) in PersonModel.cs it worked :) – Melodie Gauthier Aug 19 '16 at 20:01
  • Good to know you figured it out :), the key is the name attribute of the input tags must match the model's property name. Using `Html.TextBoxFor`, `Html.HiddenFor`, and `Html.DropDownListFor` will make sure they are always the same, in case the property name is changed in the model. – ekad Aug 19 '16 at 20:07
0

In your controller, you'll need to create an Index method, but decorated with an HttpPost attribute, like this:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(PersonModel model)
    {
        //validate and store the model somehow
        if (ModelState.IsValid)
        {
            var person = _dbcontext.Persons.SingleOrDefault(p => p.personId == model.personID);
            if(person != null)
            {
                person.favoriteColor = model.favoriteColor;
                _dbcontext.SaveChanges();
            }
        }
        return View();
    }

Your view would have need to have a hidden field and a form something like so:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(model => model.personID)
    <div class="form-horizontal">
        <h4>PersonModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.favoriteColor, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.favoriteColor, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.favoriteColor, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

This example uses a textbox, but you can use the DropDownFor HtmlHelper to accomplish what you're trying to do. Hopefully, this gets you on the right track.

Matt M
  • 3,699
  • 5
  • 48
  • 76