When I am sending information to the Database in MVC and I am redirecting the page and calling the view which prints out the newly stored data, I get a NullReferenceException error:
"Object reference not set to an instance of an object."
Apparently, my Model is null:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustomerID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
This is my Controller:
public ActionResult Index()
{
var customer = db.Customer.ToList();
return View();
}
Which gets called by:
[HttpPost]
public ActionResult Create(CustomerModel customer)
{
db.Customer.Add(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
I don't understand why it's null....
public ActionResult Index()
{
var customer = db.Customer.ToList();
return View(customer);
}
You are never passing the customer object to the view.
Edit: Also not wrapping your db.SaveChanges(); in a try/catch can be dangerous when an exception occurs.
Related
I get this error:
The call is ambiguous between the following methods or properties:
DisplayNameFor<IEnumerable<Category>,string>(HtmlHelper<IEnumerable<Category>>, System.Linq.Expressions.Expression<System.Func<IEnumerable,string>>)
and
DisplayNameFor<Category,string>(HtmlHelper<IEnumerable>, System.Linq.Expressions.Expression<System.Func<Category,string>>)
My model is
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
My Context Model is
public class CategoryContext : DbContext
{
public DbSet<Category> category { get; set; }
}
My Controller is :
public ActionResult GetCategory()
{
using (CategoryContext cc = new CategoryContext())
{
var cat = cc.category.ToList();
return View();
}
}
My View is :
#model IEnumerable<CRUD_Manav_EF.Models.Category>
<h1>Get Category</h1>
<table>
<tr>
<th>#Html.DisplayNameFor(model => model.CategoryName)</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayNameFor(modelItem => item.CategoryName) // I get error here
</td>
<td>
#Html.ActionLink("Edit", "Update", new { id = item.CategoryId })
#Html.ActionLink("Details", "Details", new { id = item.CategoryId })
#Html.ActionLink("Delete", "Delete", new { id = item.CategoryId })
</td>
</tr>
}
</table>
This error is displaying because you have used
#Html.DisplayNameFor(model => model.CategoryName) in table foreach loop and call would ambiguous between those method mentioned above. Since there is no benefit of using Display name again and again while iterating. if you will see the whole description of #Html.DisplayNameFor() you will get that the first parameter accept only model(lambda expression) and not IEnumerable of model. This is also shown in your compiler error.
see in example screenshot (this is dummy project)
Use #html.DisplayFor(..) instead in your foreach loop.
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CategoryName)
</td>
<td>
#Html.ActionLink("Edit", "Update", new { id = item.CategoryId })
#Html.ActionLink("Details", "Details", new { id = item.CategoryId })
#Html.ActionLink("Delete", "Delete", new { id = item.CategoryId })
</td>
</tr>
}
This htmlhelper method will take IEnumerable of your model. And your issue will be resolved(you can check it yourself).
I've created a DB application in MVC 4 using EntityFramework. It works okay, however I couldn't find the way of highlighting new added item to my table(html). Is it possible to highlight new rows in DB applications in MVC? Like in C#:
DataGrid.SelectedItem
Any advice or help would be very clarifying. How to highlight a row in MVC?
How are you rendering the table?
One option is to use TempData. Store the identifier of the added item in TempData and check for the identifier when rendering the table.
ItemController:
// POST: /Item/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="Id,Name")] Item item)
{
if (ModelState.IsValid)
{
db.Items.Add(item);
db.SaveChanges();
TempData["AddedItemId"] = item.Id;
return RedirectToAction("Index");
}
return View(item);
}
Item view:
<!-- Views\Item\Index.cshtml -->
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
var className = "";
if (TempData["AddedItemId"] != null && (int)TempData["AddedItemId"] == item.Id)
{
className = "alert-info";
}
<tr class="#className">
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
i am new in mvc. i have got a code where view is returning with model. what does it mean.
if i return view with model then model data can be access from view.
public ActionResult GetView(int id)
{
switch (id)
{
case 1:
return View("View1", model1);
break;
case 2:
return View("View2", model2);
break;
default:
return View("Default", modelDefault);
}
}
i need to see a small complete example where view will be return with model and view will be populated with model data. can anyone redirect me to a good example on this topic. thanks
Here you have a sample
CONTROLLER
public ActionResult Index()
{
// return a list of movies to view
return View(db.Movies.ToList());
}
VIEW
//declare expected type of model, if view returns something else, it will fail
#model IEnumerable<MvcMovie.Models.Movie>
//use model sent from controller
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<th>
#Html.DisplayFor(modelItem => item.Rating)
</th>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", { id=item.ID })
</td>
</tr>
}
More information on Accessing Your Model's Data from a Controller
I changed my index view so that each row is wrapped in a form:
Index.cshtml
#model IEnumerable<LevEl.Models.Page>
#foreach (var item in Model)
{
using (Html.BeginForm("Edit", "Pages", item, FormMethod.Post, new { id = "itemForm_" + item.PageId }))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
...
... more fields
...
<td>
#Html.CheckBoxFor(modelItem => item.IsPublished, new { onClick = "$(itemForm_" + item.PageId + ").submit();" })
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PageId }) | #Html.ActionLink("Details", "Details", new { id = item.PageId }) | #Html.ActionLink("Delete", "Delete", new { id = item.PageId })
</td>
</tr>
}
}
Here's my controller:
PagesController.cs
public ActionResult Index()
{
return View(db.Pages.Include(p => p.Language).ToList());
}
[HttpPost]
public ActionResult Edit(Page page)
{
var method = Request.HttpMethod;
if (ModelState.IsValid)
{
if (page.PageContents.GroupBy(pc => pc.Language).Any(g => g.Count() > 1))
return HttpNotFound("A page cannot have two translations in the same language.");
db.Entry(page).State = EntityState.Modified;
db.SaveChanges();
ClearMenuKeys();
return RedirectToAction("Index");
}
return View(page);
}
When I switch the value in the check box and the controller is reached, page is null.
How can I pass the entire page object upon postback?
It seems to me like your HTML do not store values of the Page. #Html.DisplayFor only displays data you have to set #Html.HiddenFor for that field too.
EDIT:
#Html.DisplayFor(modelItem => item.Title)
#Html.HiddenFor(modelItem => item.Title)
I am using ado.net entity model from an existing database.
I am using two tables products and categories.
I have a product controller:
public ActionResult Products()
{
using (var db = new StoreMvcEntities())
{
ViewData["categories"] = db.Categories.ToList();
return View(db.Products.ToList());
}
}
and a view:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => item.category.categoryname)
</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
Here is the problem: in the controller, if I remove the ViewData["categories"] = db.Categories.ToList(); the product category name is empty in the view. I'm not using the ViewData["categories"] in the view, and to get to product category name, I have to invoke
db.Categories and affect the result to any viewdata.
Can anybody explain to me how this is working?
My guess is that you're running into a side effect of Model Binding. Does the Products class have a property for the Category class?