C0d1ngJammer
C0d1ngJammer

Reputation: 550

Update Model in the Controller

So I just started to make a new mvc-project. I made a calendar (on my own) which displays the days of a month. It has two buttons which lets u get Back and Forth months in a year. So my problem is I have done null Javascript for it. The logic is in the Model.

Now everytime time sb. hits for example the Forth button the view creates a HttpPost which should send the Model with the logic to the controller.

The controller should update the value and sends the "new View" with the updated Model.

Here is a little Demo which explains my problem more easier. In this case I want to increment the (Model)-variable "Number" by 1 each time sb. hits the button. But I dont want to use Javascript. Is that possible.

Current State: If I hit the button Add the variable "Number" gets incremented by 1, only one time. Afterwards it just doesnt do anything. Somehow the model doest get updated back to the view. What am I doing wrong?

Model

public class TestModel
{
    public int Number = -10;
}

View

@model MyProject.Models.TestModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <h4>TestModel</h4>
        <hr />
    </div>
        @using (Html.BeginForm())
        {
            @Html.DisplayFor(model => model.Number)
            <p>
                <input id="BtnAdd" name="myButton" type="submit" value="Add" />
            </p>
        }
</body>
</html>     

Controller

public class TestController : Controller
{

    public TestModel currView = new TestModel();
    // GET: Test
    public ActionResult Index()
    {
        //Main
        return View(currView);
    }


    [HttpPost]
    public ActionResult Index(TestModel model)
    {
        model.Number += 1;
        //ModelState.Clear();
        //Somehow the model doesnt get passed correctly
        return View(model);
    }
}

Thanks for any help! =)

Upvotes: 1

Views: 14054

Answers (2)

Shyju
Shyju

Reputation: 218702

The problem is, every time you post the form, MVC will try to do model binding and for that it will create a new object of you TestModel class inside which you are setting the default value of this field as -10. So it will use that value.

Unless you change this field to a property with get and set , Model binder cannot set the value to it (from the posted data).

So change your view model like this

public class TestModel
{
    public int Number {set;get;};
}

Set the initial value in your GET action as needed

public ActionResult Index()
{
  var vm=new TestModel { Number =10 };    
  return View(vm);
}

When user submits the form, you need to send the updated value of Number from your form again.Keep the value in a hidden field inside your form so that it will be available with the new value.

@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.Number)
    @Html.DisplayFor(model => model.Number)
    <p>
       <input id="BtnAdd" name="myButton" type="submit" value="Add" />
    </p>
}

Also, since you are updating the value of the view model, you need yo clear the model-state dictionary. You may use the ModelState.Clear method to do that.

[HttpPost]
public ActionResult Index(TestModel model)
{
    model.Number = model.Number  +1;
    ModelState.Clear();
    return View(model);
}

Upvotes: 5

Slappywag
Slappywag

Reputation: 1223

You're using @Html.DisplayFor(model => model.Number), which will not pass your data back to the controller. Add a @Html.HiddenFor(model => model.Number) into the form in the view and then the hidden value will be passed back to the controller.

According to the Documentation for DisplayFor

If the property is typed as a primitive type (integer, string, and so on), the method renders a string that represents the property value.

A plain string will not be submitted in the form, whereas a hidden input will be.

Upvotes: 1

Related Questions