MVC - How to change the value of a textbox in a post? - asp.net-mvc

After a user clicks the submit button of my page, there is a textbox that is validated, and if it's invalid, I show an error message using the ModelState.AddModelError method. And I need to replace the value of this textbox and show the page with the error messages back to the user.
The problem is that I can't change the value of the textbox, I'm trying to do ViewData["textbox"] = "new value"; but it is ignored...
How can I do this?
thanks

You can use ModelState.Remove(nameOfProperty) like:
ModelState.Remove("CustomerId");
model.CustomerId = 123;
return View(model);
This will work.

I didn't know the answer as well, checked around the ModelState object and found:
ModelState.SetModelValue()
My model has a Name property which I check, if it is invalid this happens:
ModelState.AddModelError("Name", "Name is required.");
ModelState.SetModelValue("Name", new ValueProviderResult("Some string",string.Empty,new CultureInfo("en-US")));
This worked for me.

I have a situation where I want to persist a hidden value between POST's to the controller. The hidden value is modified as other values are changed. I couldn't get the hidden element to update without updating the value manually in ModelState.
I didn't like this approach as it felt odd to not be using a strongly typed reference to Model value.
I found that calling ModelState.Clear directly before returning the View result worked for me. It seemed to then pick the value up from the Model rather than the values that were submitted in the previous POST.
I think there will likely be a problem with this approach for situations when using Errors within the ModelState, but my scenario does not use Model Errors.

Related

Html.Textbox helper not setting the value of textbox in MVC5 Razor

I am using MVC5 ASP.Net with Razor Engine for a view that has following html helper for displaying a textbox and setting its value to ViewBag.SearchText.
When user inputs text into this textbox and view posts back, then the value is set correctly according to value in ViewBag.SearchText, but when in controller's action the ViewBag.SearchText = string.Empty, then textbox still retains its original value rather than an empty string.
Is this how the Html helper for textbox is supposed to behave Or I am missing something, and how could I set the value of textbox to an empty string? This is quite strange since the ViewBag.SearchText value is an empty string when I step through code in Visual Studio 2013.
#Html.TextBox("SearchText", (string)ViewBag.SearchText)
UPDATE 1:
I found that using the code Model.Clear() at start of the controller action solved this problem. However, I found another way to just clear that part of ModelState that is used to populate the textbox after postback. The key in ModelState is the id of the textbox, which is 'SearchText'.
The code for this is as below.
ModelState.SetModelValue("SearchText", new ValueProviderResult(null,string.Empty,
System.Globalization.CultureInfo.InvariantCulture));
That's by default (ModelState retains the value on post back).
You can use ModelState.Clear() before setting ViewBag.SearchText = ""; and returning the view. However use with caution because clearing ModelState can have unexpected results if your using validation

Model value wrong in generated view

Ran into a very strange problem here using MVC3 and razor.
The app I'm putting together shows a series of interview questions. I have a view for a question (the content of the question comes from the viewmodel). So after I post back from one question it is possible I will be returning the same question view (but using a different viewmodel instance).
In the viewmodel I have a long property like so:
public long QuestionID { get; set; }
I was trying to use a hidden input field to store the value in the view:
#Html.HiddenFor(m => m.QuestionID)
My problem is that as I go from question to question the hidden field is not changing in the final generated html. It remains the value of the first questionID in all further questions. All the other content is changing just fine and I have a couple other hidden fields that are working fine. I have verified the correct values in the controller where the model is generated. I can set a breakpoint in the razor file and I can see the model is as it should be with the correct QuestionID. I tried using #Html.TextBoxFor as well and I have the same problem. When I manually make a hidden field like below it works fine, and this is what is really bothering me.
<input type="hidden" id="QuestionID" name="QuestionID" value="#Model.QuestionID" />
Any idea why this is happening?
After a form post, MVC keeps track of the posted values in ModelState. Even if you change the values of your model, the HiddenFor helpers will use the ModelState value first. This is due to the fact that binding may have failed, or binding may be a complex object and the string value in ModelState is what they actually entered.
You can solve this by using
ModelState.Remove("QuestionID");
or, if you really just want to treat it as a completely new page,
ModelState.Clear();

Updating value provider prior to TryUpdateModel

Lets say we have a class with a property called PetsName. If it is left blank on the screen I want to update the value provider so if the user doesn't enter a pet name, we force 'unnamed'. This isn't the actual scenario.. this is of course a sample, so answers like 'just set default values on a webpage, etc' won't fit this scenario : )
The main issue is we want to update the values so when you update the model it will use whatever you have overridden. I guess one idea is to remove the value and add it. When I check ModelState, it does have the updated value, however when I call TryUpdateModel, the value is not updated. Its possible what Im doing below is indeed correct and there is another issue here but I figured I'd try this first. Thanks!
//Sample case:
[HttpPost]
public ActionResult Edit(PetOwner petOwner)
{
//If pets name is not set, force to "Unknown"
if(petOwner.PetsName=="")
{
//Tried this too ModelState.Remove("PetsName");
//ModelState.Add("PetsName", new ModelState());
ModelState["PetsName"].Value = new ValueProviderResult("Unnamed", "Unnamed", CultureInfo.CurrentCulture);
}
//Get the record/relationships from DB to merge with ModelState
PetOwner petOwnerToSave = from o in ctx.PetOwners where o.PetOwnerId == petOwner.PetOwnerId select o;
TryUpdateModel(petOwnerToSave);
//Save petOwnerToSave
}
The real issue behind the scenes here is that Html.HiddenFor wasn't displaying the correct value even though TryUpdateModel was updating a value in the model to give to the view.
The issue here is that the Html helpers assume if you are rendering a view after a post, there mustve been an error (otherwise you wouldve redirected back to the view with a GET method - hence the Post Redirect Get issue)
This is described in detail at:
http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx

How to clear the post data for a textbox in an ASP.NET MVC application?

By default, a textbox rendered using <%= Html.TextBox("somefield")%> uses the value from the post data, e.g. if you have validation errors on your page, the value is retrieved from the posted data and used for the value attribute.
Now, in a few cases I want to be able to clear that value, in other words I want the textbox to be blank, I don't want MVC to get the value from the posted data and uses it for the value attribute, how can I do? How can I clear the post data?
Thanks
ModelState.Remove("key");
Remove the value from the model state, like this:
ViewData.ModelState.Remove("somefield");
I found I had to both remove the ModelState and change the model, as if MVC tries ModelState first, then the model:
ModelState.Remove("key");
model.key = "";
And if you don't want to lose your Error state for the model, you can just change the value like this:
ModelState.SetModelValue("Captcha", new ValueProviderResult(null, string.Empty, System.Globalization.CultureInfo.InvariantCulture));
model.key = "";

Model not rendering model values after post

I have an ASP.NET MVC page that has a list of items...
//a vague representation
Model.someValue[0] Model.someHiddenValue[0]
Model.someValue[1] Model.someHiddenValue[1]
Model.someValue[2] Model.someHiddenValue[2]
All fields are optional, but they do have some validation, of which I am showing validation messages.
The problem is, when I submit once and return the original view instead of a redirect, the hidden fields are not getting their new value, but their new value is in the view model being passed to the view.
I am thinking the ModelState might be overriding the model as part of validation. I know I can do a redirect and bypass the problem, but I want be able to save part of the form and show validation errors for the rest. If there are no other solutions, I will simply validate the whole form and only save when all items are valid.
If values are present in ModelState, it shows them instead of the values in your model, since they represent the "last" known state provided from the user.
You should clear out ModelState if you're not actually intending the user to re-do their edits.
Did you try this?:
var newValue = new ValueProviderResult("value", "value", System.Globalization.CultureInfo.CurrentUICulture);
ModelState.SetModelValue("someHiddenValue", newValue);

Resources