Html.EditorFor not updating after Post [duplicate] - c#

This question already has answers here:
View not updating after post
(3 answers)
Closed 4 years ago.
I am doing something fundamentally wrong. I have created a simple example of my problem.
I have a simple class as follows:
public class Example
{
public string Text { get; set; }
}
I have created two methods on my controller
This is the view page you hit. It creates a new Example object.
public ActionResult Example()
{
var model = new Example {
Text = "test"
};
return View(model);
}
Then the post back when the form is submitted
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
model.Text += "a";
return View(model);
}
The view is as follows:
#model Stackoverflow.Example
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>#Model.Text</h1>
#Html.EditorFor(model => model.Text);
<input type="submit" value="Save" />
}
When I first visit the page the heading and the text box have the same value
I press submit and the page loads again. The title has updated but the text box has the same value.
Why is the #Html.EditorFor(model => model.Text); not getting the updated value?

When you post a model back to an ActionResult and return the same View, the values for the model objects are contained in the ModelState. The ModelState is what contains information about valid/invalid fields as well as the actual POSTed values. If you want to update a model value, you can do one of the following two things:
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
ModelState.Clear();
model.Text += "a";
return View(model);
}
or
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
var newValue = model.Text += "a";
ModelState["Text"].Value = new ValueProviderResult(newValue,newValue, CultureInfo.CurrentCulture)
return View(model);
}

You need to clear the model state on post method of controller
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Example(Example model)
{
ModelState.Clear();
model.Text += "a";
return View(model);
}

Related

TextBoxFor default value and keep edited value after validation fail

Razor code like:
#Html.TextBoxFor(Model => Model.Name, new { #Value = student.t_Name })
and I using .NET MVC's model validation in Controller,
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
return View(); // when validation failed
}
My situation is I have a edit function, for example:
original data:
birthday: 1992-05-26
after edited:
birthday: 1992-05-32
after I submit this to Controller and make model validation, it will validate fail, and return to previous view(the view before form submit),
I want it shows
birthday:1992-05-32
instead of
birthday:1992-05-26
You should set ViewModel values that come to your controller like this:
public ActionResult YourControllerMethod(YourViewModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
ViewData.Model = model; //where model is your controller model
return View(); // when validation failed
}
}
You would need to pass the current posted model instance back to view when returning back View something like:
public ActionResult YourAction(SomeModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
return View(model);
}
}

get a variable passed to my controller from a textbox

I have a simple model I am using for a search page to do some validation:
public class Search {
[Required]
[DisplayName("Tag Number")]
[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Tag must be a number")]
public int HouseTag { get; set; }
i then have a simple view with a textbox and a submit button:
#model Search
#{
Layout = "~/_Layout.cshtml";
}
#using (Html.BeginForm("Search", "Inquiry", FormMethod.Get)){
#Html.LabelFor(m =>m.HouseTag)
#Html.TextBoxFor(m=>m.HouseTag, new { type = "Search", autofocus = "true", style = "width: 200px", #maxlength = "6" })
<input type="submit" value="Search" id="submit"/>
my controller is expecting a parameter of an id:
[HttpGet]
public ActionResult Search(int id){
ViewBag.Tag = id;
return View();
}
when i execute it with a number i get a null value being passed to the controller, causing things to blow up. I am using the model to control some of the properties of the search box for validation. I used to just have #Html.TextBox and it returned fine, but now that ive added the model, it doesnlt return anything.
You can set your parameter to a type of Search and then access the property in your action
[HttpGet]
public ActionResult Search(Search model){
ViewBag.Tag = model.HouseTag;
return View();
}
If it were me I'd make this a HttpPost or create a seperate action for this form so I wouldn't see the HouseTag text in the URL..
#using (Html.BeginForm("Search", "Inquiry", FormMethod.Post))
{
#Html.LabelFor(m => m.HouseTag)
#Html.TextBoxFor(m => m.HouseTag, new { type = "Search", autofocus = "true", style = "width: 200px", #maxlength = "6" })
<input type="submit" value="Search" id="submit" />
}
[HttpPost]
public ActionResult Search(Search model){
ViewBag.Tag = model.HouseTag;
return View();
}
You are expecting a parameter named id and you are passing HouseTag as the name of that parameter you should rename id to houseTag inside the Search method.
There's a couple of things going on here. First you are going to want to split your Get and Post actions. Also forms are only used in conjunction with POST's. You also don't need to name your action or controller unless you are sending the post to a different controller or action then the GET.
This is the get. It renders the form on the page. You don't need to put [HttpGet] on there, it is the default.
public ActionResult Search()
{
return View();
}
The following is going to post the form back to the server. the model binder will wire up the html form fields with your view model. since you have validators on the view model, you'll want to check that the model state is valid and re-show the view with the associated errors. You will need to add an #Html.ValidationMessageFor(...) into your view so that you actually see those errors.
[HttpPost]
public ActionResult Inquiry(Search search)
{
if (!ModelState.IsValid)
{
return View(search);
}
//so something with your posted model.
}

Change model property in post request asp.net mvc

I have one problem.
This is short example.
This is model.
public class MyModel
{
string Title{get;set;}
}
In view I write
#Html.TextBoxFor(model => model.Title)
This is controller.
public ActionResult EditNews(int id)
{
var model = new MyModel;
MyModel.Title = "SomeTitle"
return View("News/Edit", model);
}
//for post
[HttpPost]
public ActionResult EditNews(MyModel model)
{
//There is problem.When I do postback and
// change Title in this place,Title doesn't change in view textbox
//Only when I reload page it change.
model.Title = "NEWTITLE"
return View("News/Edit", model);
}
It won't change because by default (many think this is a bug) MVC will ignore the changes you make to the model in a HttpPost when you're returning the same View. Instead, it looks in the ModelState for the value that was originally served to the view.
In order to prevent this, you need to clear the ModelState, which you can do at the top of your HttpPost by doing:
ModelState.Clear();

Drop down list isn't working

Controller:
OnePersonAllInfoViewModel vModel = new OnePersonAllInfoViewModel();
vModel.PreferredContactType = new PreferredContactType();
ViewBag.PrefContactTypes = new SelectList(dbEntities.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID),
"PreferredContactTypeID", "PreferredContactType1",
vModel.PreferredContactType.PreferredContactTypeID);
View:
<div class="editor-label">
#Html.LabelFor(model => model.PreferredContactType.PreferredContactTypex)
</div>
#Html.DropDownListFor(model => model.PreferredContactType.PreferredContactTypeID,
ViewBag.PrefContactTypes as SelectList)
And I get this error on post back... There is no ViewData item of type 'IEnumerable' that has the key 'PreferredContactType.PreferredContactTypeID'
Any thoughts? Thanks!
In your HttpPost controller action you must repopulate the ViewBag.PrefContactTypes property the same way you did in your GET action if you redisplay the same view:
[HttpPost]
public ActionResult Process(OnePersonAllInfoViewModel model)
{
ViewBag.PrefContactTypes = ...
return View(model);
}
Also you seem to have defined some class that is suffixed with ViewModel. This leaves the reader to believe that you are using view models in your application and in the very next line you use ViewBag. Why? Why not take full advantage of the view model and its strong typing?
Just like this:
public class OnePersonAllInfoViewModel
{
public int PreferredContactTypeID { get; set; }
public IEnumerable<PreferredContactType> PrefContactTypes { get; set; }
}
and then in your GET action:
public ActionResult Index()
{
var model = new OnePersonAllInfoViewModel();
model.PrefContactTypes = dbEntities
.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID)
.ToList();
return View(model);
}
then the view:
#Html.DropDownListFor(
model => model.PreferredContactTypeID,
Model.PrefContactTypes
)
and the POST action:
[HttpPost]
public ActionResult Index(OnePersonAllInfoViewModel model)
{
if (!ModelState.IsValid)
{
// the model is invalid => we must redisplay the same view =>
// ensure that the PrefContactTypes property is populated
model.PrefContactTypes = dbEntities
.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID)
.ToList();
return View(model);
}
// the model is valid => use the model.PreferredContactTypeID to do some
// processing and redirect
...
// Obviously if you need to stay on the same view then you must ensure that
// you have populated the PrefContactTypes property of your view model because
// the view requires it in order to successfully render the dropdown list.
// In this case you could simply move the code that populates this property
// outside of the if statement that tests the validity of the model
return RedirectToAction("Success");
}

ASP.net MVC - Text Box value retains the value that was POSTed

I have a form in my MVC application that has a textbox. When the form is POSTed to the page, I make a modification to the model value and redisplay the view. The textbox still shows the value that was POSTed though.
Here is the code:
#using( Html.BeginForm() ) {
#Html.TextBoxFor( m => m.Foo )
<input type="submit" value="Save" />
}
public class TestController : Controller {
public ActionResult Index() {
return View();
}
[HttpPost]
public ActionResult Index(MyModel model) {
model.Foo += "bar";
return View(model);
}
}
Whatever is in the form (lets say I type in foo) I add "bar" and try to show the form again. But when the form is redisplayed all I see is foo. I remember reading something about why this is happening but can't seem to find it now. I know this is a poor example but I'm just trying to remember why it is doing this, and what the workaround is (other than redirecting). Is there a way to have it show the updated model value and not what the form value that was posted?
You can clear the model state and the helper should display the new value.
[HttpPost]
public ActionResult Index(MyModel model) {
model.Foo += "bar";
ModelState.Clear();
return View(model);
}

Categories