Reputation: 550
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
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
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