Reputation: 3955
In my mvc 3 web store app I have this model: Items, Products, Shipping, Users tables, where 1 Item contains 1 Product, 1 User, and 1 Shipping. I need to somehow create and edit items. With creating there are not many problems cause I can pass the "fields to fill" as parameters to Crete(Post) method. With editing there is one problem - Null Reference Exception occures. This is my code:
(controller):
I pass model (of type Item) to Edit Post method as a parameter and get product and shipping, that, I hope), I filled with values.
[HttpGet]
public ViewResult Edit(int itemId)
{
Item target = _itemsRepository.GetItem(itemId);
return View(target);
}
[HttpPost]
public ActionResult Edit(Item model)
{
Product p = model.Product;
Shipping s = model.Shipping;
// here goes some validation stuff
if (ModelState.IsValid)
{
_productRepository.UpdateProduct(p);
_shippingRepository.UpdateShipping(s);
return RedirectToAction("Content");
}
return View();
}
Strongly typed view (where I fill the form):
@model WebStore.WebStoreModels.Item
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Product</legend>
@Html.HiddenFor(i => i.ItemId)
<p>Name: </p>
<p>
@Html.EditorFor(i => i.Product.Name)
@Html.ValidationMessageFor(i => i.Product.Name)
</p>
// and so on
</fieldset>
<fieldset>
<legend>Shipping</legend>
<p>Cost: </p>
<p>
@Html.EditorFor(i => i.Shipping.Cost)
@Html.ValidationMessageFor(i => i.Shipping.Cost)
</p>
// so on
</fieldset>
<p>
<input type="submit" value="Save"/>
</p>
}
And when I fill the form and click "safe" button the NullReferenceException occures in the ProductRepository class in UpdateProduct() method:
public class ProductRepository : IProductRepository
{
private WebStoreDataContext _dataContext;
public ProductRepository(WebStoreDataContext dataContext)
{
_dataContext = dataContext;
}
public Product GetProduct(int productId)
{
return _dataContext.Products.SingleOrDefault(p => p.ProductId == productId);
}
public void UpdateProduct(Product p)
{
var dbProduct = GetProduct(p.ProductId);
dbProduct.Name = p.Name; // here the exception occures
dbProduct.Description = p.Description;
dbProduct.Price = p.Price;
dbProduct.Category = p.Category;
dbProduct.SubCategory = p.SubCategory;
_dataContext.SubmitChanges();
}
Seems like I can't use this assignment:
Product p = model.Product;
I also tried: (in view and then assign it to Product in Edit(Post) method)
TempData["product"] = @Model.Product;
And also: (in view)
@Html.Hidden("product", @Model.Product)
And pass it as parameters to Edit(Post) method:
[HttpGet]
public ViewResult Edit(Product p, Shipping s)
I think the problem is associated with model.
Any help would be great, Sorry for so much code)
Upvotes: 1
Views: 1995
Reputation: 11188
You need to add hidden ProductId input inside of the form in your View:
@using (Html.BeginForm())
{
@Html.HiddenFor(i => i.Product.ProductId)
...
}
The reason you need to have this line is that when you submit your form model binder looks at every input (including hidden inputs) and binds them to the properties of your Item model
that you pass on [HttpPost]
action. Before, when you didn't have this line, only the following properties were populated:
Your model didn't have information for the value of Item.Product.ProductId. This property is int
, which means that it was turning to be equal 0 when form was submitted. Inside your _productRepository.UpdateProduct(p);
method you are trying to get a product by Id and obviously it cannot find a product with id = 0, which is why this call was returning null
resulting in a null reference exception on the next line.
Upvotes: 2