When I click the submit button on my form, I get a null reference exception error during the reload following the submit event, that is generated by my dropdownlist.
The data loads fine during initial load. It is my understanding that the data is maintained by convention and should be retained.
I also looked at the modelstate and the error for the required field was raised and the error message exists inside the ModelState object.
But, it looks like this convention is not working for this dropdown. So, this line below raises the error:
#Html.DropDownListFor(m => m.Company.DeptId, Model.DeptList)
What am I doing wrong?
The value for the posted model property (DeptId) is retained, but the contents of the property DeptList are not since they were not posted back. Only the properties on the model that correspond to form elements that are posted can be reconstituted on the model. On error you'll need to repopulate any properties of the model that don't correspond to inputs in the view so that the view renders properly.
Related
I am trying to add an empty ListBox to my Razor view page to store run time values. But It gives me an error message saying There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'myListBox'. I am aware that there is such viewdata. But, when I do the same with textbox, it works.
#Html.TextBox("myTextBox")//works alright, displays a textbox
#Html.ListBox("myListBox") // gives error
How to display an empty listbox and why the above method works for textbox but for listbox?
Just found a workaround to create an empty ListBox by passing an empty SelectList but still wondering why the original one did not work.
#Html.ListBox("myListBox", new SelectList(new[] {""}));
In MVC 3 app I have a few conditional elements in the controller. for example I have a number say "10" which has met the model state requirements but I have a if statement that checks if the number "10" exists in another table. Should it exist the data is submited but should it not exist I return the view and would like to return a error message.
My question is what would be the best way of displaying a error in this situation. I have looked at returning a viewbag message but I would like to style the error message with a box and by adding this style to the view it always gets displayed which is a problem.
You could add the error message to the modelstate:
ModelState.AddModelError("somekey", "some error message");
and inside your view display error messages using the validation summary helper:
#Html.ValidationSummary(false)
You could of course add a string property to your view model and set its value in case of error. Then inside the view check whether the model property has a value and if it does display the error messages inside a custom styled element. It seems a bit like a wheel reinvention assuming you could simply append the error message to the modelstate but worth mentioning.
I'm working on an ASP.NET MVC2 app. I've come to realize a very surprising, yet amazing thing that MVC does behind the scenes having to do with the ModelState and model binding. I have a ViewModel which has a whole bunch of data - some fields being part of a form while others are simply part of the UI. On HttpPost, my Action method uses the DefaultModelBinder which attempts to bind the whole model, but only fields which were part of the form are successfully deserialized - all others remain null. That's fine and understandable. If the ModelState is invalid, I need to refresh the model from the db and bind those particular form fields before returning to the same edit view to display those associated ModelState validation errors.
Here's where my amazement and curiosity comes. It was my assumption that in order for me to bind the form fields with the refreshed model, I needed to make a call to either UpdateModel() or TryUpdateModel<>(), passing in the newly refreshed model. For example:
[HttpPost]
public ActionResult EditDetail(EditDetailItemModel model)
{
if (model.IsValid)
{
// Save the results to the db
return RedirectToAction(...)
}
// Can't simply "return View(model)". Not all fields in EditDetailItemModel
// were part of the form - thus they returned null. Have to refresh
// model from the db.
var refreshedModel = RefreshModelFromDB();
// Is this line necessary?????
TryUpdateModel<EditDetailItemModel>(refreshedModel);
return View(refreshedModel);
}
But, what I found was that if I simply returned refreshedModel to the view WITHOUT making a call to TryUpdateModel<>(), the refreshed model was automatically bound with the form field values posted!! Hence, the TryUpdateModel<>() is not needed here!
The only way I can make any sense of it is that since the ModelState is in an invalid state, once I returned the view with the refreshed model, the "MVC rendering engine" looped through the ModelState errors and bound those property values with my refreshed model. That is simply AWESOME! But, I want proof as to this assumption. I can't find documentation regarding this anywhere on the web. Can anyone either confirm my hypothesis of WHY/HOW this AWESOME auto binding behavior is occuring and/or educate me as to why/how it's happening, hopefully backed up with some online documentation links so I understand more fully what's going on under the covers?
public ActionResult EditDetail(EditDetailItemModel model)
That line will perform model binding. Think of ActionMethod parameters as always being populated by a call to UpdateModel.
You are not seeing refreshedModel's values in the view, you are seeing the ModelState entries and values from EditDetailItemModel.
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);
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.