I've encountered a strange issue....when I use UpdateModel()
or TryUpdateModel()
, everything works fine. When I try binding myself (e.g. MyObject.FirstName = collection["FirstName"]
), I get a "Object reference not set to an instance of an object"
error.
It's a little hard to explain, so I'll present the code:
[HandleError]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
try
{
Model.Event evnt = new Redline.RedlineTimeAttack.Model.Event();
//When this is uncommented everything works fine.
//TryUpdateModel<Model.Event>(evnt);
//this will eventually lead to problems
evnt.Description = collection["Description"];
evnt.EndDate = enddate;
evnt.EventName = collection["EventName"];
evnt.IsActive = collection["IsActive"].Contains("true");
evnt.StartDate = startdate;
evnt.TrackId = trackId;
evnt.WebContent = collection["WebContent"];
if (!evnt.IsValid)
{
foreach (var error in evnt.GetRuleViolations())
{
ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
}
//If there are no validation issues then no problem, redirecttoaction
//works properly
if (ModelState.IsValid)
{
model.Events.InsertOnSubmit(evnt);
model.SubmitChanges();
ViewData["ControlMode"] = "Edit";
return RedirectToAction("Edit");
}
else //returning to View so that user can correct issues causes a null reference error in the view (bombs at first Html.Textbox("ControlName"))
{
ViewData["Tracks"] = GetTracks();
return View("Create", evnt);
}
}
Here's the stack trace:
System.NullReferenceException was unhandled by user code
Message="Object reference not set to an instance of an object."
Source="System.Web.Mvc"
StackTrace:
at System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType)
at System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, IDictionary`2 htmlAttributes)
at System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, IDictionary`2 htmlAttributes)
at System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name)
at ASP.views_event_create_aspx.__RenderContent2(HtmlTextWriter __w, Control parameterContainer) in d:\TFSProjects\Redline Time Attack\Main\Source\Redline.RedlineTimeAttack.Web\Views\Event\Create.aspx:line 18
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in d:\TFSProjects\Redline Time Attack\Main\Source\Redline.RedlineTimeAttack.Web\Views\Shared\Site.Master:line 29
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Page.Render(HtmlTextWriter writer)
at System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
To fix "Object reference not set to an instance of an object," you should try running Microsoft Visual Studio as an administrator. You can also try resetting the user data associated with your account or updating Microsoft Visual Studio to the latest version.
The error means that your code is trying to access/reference an object that is a null valued object that is not there in memory.
A NullReferenceException exception is thrown when you try to access a member on a type whose value is null . A NullReferenceException exception typically reflects developer error and is thrown in the following scenarios: You've forgotten to instantiate a reference type.
An Object is an instance of a Class , it is stored some where in memory. A reference is what is used to describe the pointer to the memory location where the Object resides.
I found some insight here: http://forums.asp.net/p/1396019/3006051.aspx
If you don't want to use Builtin Model Binding, then to use Bultin Validation (SanjaySutar want to use), for every ModelError you add, you will need to add a ModelValue: ModelState.AddModelError("Name", "Bad Name");
ModelState.SetModelValue("Name", ValueProvider["Name"]);
So I updated my code like so:
ModelState.SetModelValue("Description", new ValueProviderResult(ValueProvider["Description"].AttemptedValue, collection["Description"], System.Globalization.CultureInfo.CurrentCulture));
ModelState.SetModelValue("EventName", new ValueProviderResult(ValueProvider["EventName"].AttemptedValue, collection["EventName"], System.Globalization.CultureInfo.CurrentCulture));
ModelState.SetModelValue("EndDate", new ValueProviderResult(ValueProvider["EndDate"].AttemptedValue, collection["EndDate"], System.Globalization.CultureInfo.CurrentCulture));
ModelState.SetModelValue("StartDate", new ValueProviderResult(ValueProvider["StartDate"].AttemptedValue, collection["StartDate"], System.Globalization.CultureInfo.CurrentCulture));
ModelState.SetModelValue("TrackId", new ValueProviderResult(ValueProvider["TrackId"].AttemptedValue, collection["TrackId"], System.Globalization.CultureInfo.CurrentCulture));
ModelState.SetModelValue("WebContent", new ValueProviderResult(ValueProvider["WebContent"].AttemptedValue, collection["WebContent"], System.Globalization.CultureInfo.CurrentCulture));
The reason I am doing this is because I wanted to a. have all (or as much as possible) validation done in my Business Object, including required fields, and b. I wanted my own messages in the validation summary (e.g. "FieldX is a required field." instead of "A value is required."). If there's a better way to do this, please see my other question: ASP.NET MVC - Custom validation message for value types
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With