Problem:
I have List of Categories with SubCategories, so when i click on SubCategory item it redirect me to List of Entries. There along the list it has Create ActionLink. So the problem is passing the SubCategoryId when I click SubCategoryItem for the Create ActionLink. Without the CreateActionLink it lists the entries but with it, it gives an error in the index view:
Object reference not set to an instance of an object.
Line 6:
Line 7: <p>
Line 8: #Html.ActionLink("Create New", "Create", new { subCategoryId = #Model.SubCategoryId})
Line 9: </p>
Line 10:
I understand that i am passing null reference and the question is how to avoid that?
Here is my code:
Controller:
public class EntryController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult EntryList(int subCategoryId)
{
var entries = EntryDAL.GetEntries(subCategoryId);
return View("_EntryList",entries);
}
public ActionResult Create(int subCategoryId)
{
var model = new Entry();
model.SubCategoryId = subCategoryId;
return View(model);
}
[HttpPost]
public ActionResult Create(Entry entry)
{
try
{
if (ModelState.IsValid)
{
var add = EntryDAL.Add(entry);
return RedirectToAction("Index");
}
return View(entry);
}
catch (Exception)
{
return View();
}
}
}
IndexView:
#model PasswordCloud.Domain.Models.SubCategory
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create", new { subCategoryId = #Model.SubCategoryId })
</p>
#{Html.RenderPartial("_EntryList",Model.EntryList);}
PartialView:
#model IEnumerable<PasswordCloud.Domain.Models.Entry>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Username)
</th>
<th>
#Html.DisplayNameFor(model => model.Password)
</th>
<th>
#Html.DisplayNameFor(model => model.Url)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.SubCategoryId)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Username)
</td>
<td>
#Html.DisplayFor(modelItem => item.Password)
</td>
<td>
#Html.DisplayFor(modelItem => item.Url)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubCategoryId)
</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>
SubCategoryListItem View:
#model IEnumerable<PasswordCloud.Domain.Models.SubCategory>
#foreach (var item in Model) {
#Html.ActionLink(item.Name,"Index","Entry", new { subCategoryId = item.SubCategoryId }, null)
}
In your Index action you never create a model and pass it to the view. So when it gets to your line where you make the action link where you use new { subCategoryId = #Model.SubCategoryId} your model is null. Thus you get a null ref exception. To fix it you need to do something like this.
public ActionResult Index()
{
var model = ...
return View(model);
}
Related
I have two tables. One is Booking and other is Course. Course can have many Bookings.
I want to count number of Bookings for each Course and pass that to ViewBag. So I want to count how many users applied for each Course.
This line counts total number o Bookings but I cant figure out how to do that for each Course.
ViewBag.Counter = db.Bookings.Count();
This line gets all the courses to my Index page.
IEnumerable<Course> courses = cr.GetCourses();
return View(courses.ToList());
And this is controller that is doing the work. I tried with 2 foreach loops but cant get it to work.
public ActionResult Index()
{
Booking booking = new Booking();
Course course = new Course();
List<Course> listCourses = new List<Course>();
List<Booking> bookings = new List<Booking>();
foreach (var item in listCourses)
{
int id = course.CourseId;
foreach (var item1 in bookings)
{
ViewBag.Counter = db.Bookings.Where(x => x.CourseId == id).Count();
}
}
IEnumerable<Course> courses = cr.GetCourses();
return View(courses.ToList());
}
I expect to get a number of users that applied for each course that is listed on my index page. I got no exceptions or errors and nothing shows up in my view. When I use ViewBag.Counter = db.Bookings.Count(); I get a total number of users that applied for all avaliable courses. Model on the view is Course model which is in relation with Booking with one to many relation.
This is the View for my ActionResult.
#model IEnumerable<Entities.Course>
#{
ViewBag.Title = "AlgebraSchoolApp";
}
<h2>Dobrodošli!</h2>
<p>
Da bi se prijavili na neki od naših tečajeva kliknite na link prijave:
<button>
#Html.ActionLink("Prijava","Create","Booking")
</button>
</p>
<h2> Svi tečajevi</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.CourseName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayName("Broj polaznika")
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CourseName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#ViewBag.Counter
</td>
</tr>
}
</table>
<h2>Slobodni tečajevi</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.CourseName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Date)
</th>
</tr>
#foreach (var item in Model.Where(x => x.Full == false))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CourseName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
</tr>
}
</table>
The reason that ViewBag.Counter is showing the same result for all courses is because it is being overwritten each time with ViewBag.Counter = db.Bookings.Where(x => x.CourseId == id).Count();.
If i have understood your issue this can be fixed by creating a new view model to store the required information for a course and return this to your view. EG:
public class CourseViewModel
{
public string CourseName { get; set; }
public string Description { get; set; }
//etc
public int BookingCount { get; set; }
}
Controller:
public ActionResult Index()
{
var courses = cr.GetCourses();
var courseViewModels= new List<CourseViewModel>();
foreach (var course in courses )
{
var bookingCount = db.Bookings.Where(x => x.CourseId == course.CourseId).Count();
courseViewModels.Add(new CourseViewModel{
CourseName = course.CourseName, //Add all the vm properties
BookingCount = bookingCount
});
}
return View(courseViewModels);
}
In the view:
#model IEnumerable<CourseViewModel>
#/*...*/
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CourseName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.BookingCount )
</td>
</tr>
}
Trying to get this to work but keep getting null values from the Model.
Controller:
[HttpPost]
public ActionResult Index(OPISPriceReportOLY_Result model)
{
if (ModelState.IsValid)
{
int id = model.orpid;
using (var context = new IntranetCoreEntities())
{
var selected = context.OPISRetailPricings.Find(id);
selected.DMarkup = model.DMarkup;
selected.DSell = model.DSell;
selected.RMarkup = model.RMarkup;
selected.RSell = model.RSell;
context.SaveChanges();
}
}
return View("Index", model);
}
View:
#model IEnumerable<OPIS7.Models.OPISPriceReportOLY_Result>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("Index", "OPISPriceReportOLY_Result", FormMethod.Post))
{
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.cpid)
</th>
<th>
#Html.DisplayNameFor(model => model.Zone)
</th>
<th>
#Html.DisplayNameFor(model => model.ZoneDescription)
</th>
<th>
#Html.DisplayNameFor(model => model.Rack)
</th>
<th>
#Html.DisplayNameFor(model => model.ActualProduct)
</th>
<th>
#Html.DisplayNameFor(model => model.Cost)
</th>
<th>
#Html.DisplayNameFor(model => model.DMarkup)
</th>
<th>
#Html.DisplayNameFor(model => model.DSell)
</th>
<th>
#Html.DisplayNameFor(model => model.RMarkup)
</th>
<th>
#Html.DisplayNameFor(model => model.RSell)
</th>
<th>
#Html.DisplayNameFor(model => model.DateUpdated)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.cpid)
</td>
<td>
#Html.DisplayFor(modelItem => item.Zone)
</td>
<td>
#Html.DisplayFor(modelItem => item.ZoneDescription)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rack)
</td>
<td>
#Html.DisplayFor(modelItem => item.ActualProduct)
</td>
<td>
#Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
#Html.TextBoxFor(modelItem => item.DMarkup)
</td>
<td>
#Html.TextBoxFor(modelItem => item.DSell)
</td>
<td>
#Html.TextBoxFor(modelItem => item.RMarkup)
</td>
<td>
#Html.TextBoxFor(modelItem => item.RSell)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateUpdated)
</td>
<td>
<button type="submit">Update</button>
</td>
</tr>
}
</table>
}
Model:
namespace OPIS7.Models
{
using System;
using System.ComponentModel.DataAnnotations;
public partial class OPISPriceReportOLY_Result
{
[Key]
public int orpid { get; set; }
public int cpid { get; set; }
public string Zone { get; set; }
public string ZoneDescription { get; set; }
public string Rack { get; set; }
public string ActualProduct { get; set; }
public Nullable<double> Cost { get; set; }
public Nullable<double> DMarkup { get; set; }
public string DSell { get; set; }
public Nullable<double> RMarkup { get; set; }
public Nullable<double> RSell { get; set; }
public Nullable<System.DateTime> DateUpdated { get; set; }
}
}
According to documentation this is supposed to work without having to resort to AJAX or JS of any kind but I'm hitting a wall. Any ideas?
If you just want to take single OPISPriceReportOLY_Result in action method, you will need to move form tag inside for loop.
The clean approach is to create a Partial View. You can read more at Adam Freeman's book.
Index.cshtml
#model IEnumerable<OPISPriceReportOLY_Result>
<table class="table">
#foreach (var item in Model)
{
#Html.Partial("_Result", item)
}
</table>
_Result.cshtml
#model OPISPriceReportOLY_Result
#using (Html.BeginForm("Update", "Home", FormMethod.Post))
{
<tr>
<td>
#Html.DisplayFor(x => x.cpid)
#Html.HiddenFor(x => x.cpid)
</td>
<td>
#Html.DisplayFor(x => x.Zone)
#Html.HiddenFor(x => x.Zone)
</td>
<td>
#Html.DisplayFor(x => x.ZoneDescription)
#Html.HiddenFor(x => x.ZoneDescription)
</td>
<td>
#Html.DisplayFor(x => x.Rack)
#Html.HiddenFor(x => x.Rack)
</td>
<td>
#Html.DisplayFor(x => x.ActualProduct)
#Html.HiddenFor(x => x.ActualProduct)
</td>
<td>
#Html.DisplayFor(x => x.Cost)
#Html.HiddenFor(x => x.Cost)
</td>
<td>
#Html.TextBoxFor(x => x.DMarkup)
</td>
<td>
#Html.TextBoxFor(x => x.DSell)
</td>
<td>
#Html.TextBoxFor(x => x.RMarkup)
</td>
<td>
#Html.TextBoxFor(x => x.RSell)
</td>
<td>
#Html.DisplayFor(x => x.DateUpdated)
#Html.HiddenFor(x => x.DateUpdated)
</td>
<td>
<button type="submit">Update</button>
</td>
</tr>
}
Controllers
After updating in database, you cannot return View("Index", model);. Index view is expecting an enumerable. The best approach is to redirect to Index page again.
public class HomeController : Controller
{
public ActionResult Index()
{
List<OPISPriceReportOLY_Result> results = new List<OPISPriceReportOLY_Result>();
results.Add(new OPISPriceReportOLY_Result { cpid = 1 });
results.Add(new OPISPriceReportOLY_Result { cpid = 2 });
results.Add(new OPISPriceReportOLY_Result { cpid = 3 });
return View(results);
}
[HttpPost]
public ActionResult Update(OPISPriceReportOLY_Result model)
{
if (ModelState.IsValid)
{
int id = model.orpid;
using (var context = new IntranetCoreEntities())
{
var selected = context.OPISRetailPricings.Find(id);
selected.DMarkup = model.DMarkup;
selected.DSell = model.DSell;
selected.RMarkup = model.RMarkup;
selected.RSell = model.RSell;
context.SaveChanges();
}
}
return RedirectToAction("Index");
}
}
I'm trying to create a simple view (paging, sorting and filtering).
The method I have that does that looks something like this:
public IEnumerable<VehicleMakeEntity> GetMake(int index, int count,
Expression<Func<VehicleMakeEntity, int>> orderLambda)
{
var data = _makeRepository.SelectListMake(index, count, orderLambda).AsQueryable();
return data;
}
You see it call another method from a repository, which looks the same
private readonly IQueryable<VehicleMakeEntity> _source;
public MakeRepository(ProjectDbContext context)
{
this.context = context;
_source = this.context.VehicleMake;
}
public IEnumerable<VehicleMakeEntity> SelectListMake(int index, int count,
Expression<Func<VehicleMakeEntity, int>> orderLambda)
{
return _source.Skip(index * count).Take(count).OrderBy(orderLambda);
}
In my controller I call the method
public IActionResult Make()
{
var data = _vehicleService.GetMake(1, 10, (p => p.Id));
return View(data);
}
And it returns some data I do not know how to work with as seen here
I also generated a View based on that controller method, a basic List View which you can see here
#model IEnumerable<Data.Entities.VehicleMakeEntity>
#using NonFactors.Mvc.Grid;
#{
ViewData["Title"] = "Make View";
}
<h2>Make View</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Id)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Abrv)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Abrv)
</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>
}
</tbody>
But nothing is displaying on the site. Am I supposed to do something with the returned data? What am I doing wrong? I checked if the entities aren't getting the information from the database, they are.
Can you check with below code.
public IActionResult Make()
{
var data = _vehicleService.GetMake(1, 10, (p => p.Id)).ToList();
return View(data);
}
Also try to remove AsQueryable()
public IEnumerable<VehicleMakeEntity> GetMake(int index, int count, Expression<Func<VehicleMakeEntity, int>> orderLambda)
{
return _makeRepository.SelectListMake(index, count, orderLambda);
}
I want to select a line of references to get the list of athor reference associat ,
this is the code of my view :
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Réf_OE)
</th>
<th>
#Html.DisplayNameFor(model => model.GENER_MOTORS)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Réf_OE)
</td>
<td>
#Html.DisplayFor(modelItem => item.GENER_MOTORS)
</td>
<td>
#Html.ActionLink("Select", "Select", new { Réf = item.Réf_OE })
</tr>
}
This the code of my select method :
[HttpGet]
public ActionResult Select(string Réf)
{
if (Réf != null)
{
var autres_ref = db.Autre_Références.Where(c => c.Réf_id == Réf).ToList();
ViewBag.autres_ref = autres_ref;
return RedirectToAction("Index", "Référence_Consctructeur");
}
else
{
return RedirectToAction("Create", "Référence_Consctructeur");
}
return RedirectToAction("Index", "Référence_Construscteur");
}
and i put the cursor on select it shows :
http://localhost:56616/R%C3%A9f%C3%A9rence_Consctructeur/Select/7700308756
I didn't understand why the paramter passed to select is null
please help.
The parameter name you are passing in your ActionLink should match with the parameter name in your action:
#Html.ActionLink("Select", "Select", new { Réf= item.Réf_OE })
Or change the parameter name of your action:
public ActionResult Select(string id){...}
I have a table with data, how can I populate a form on the same page with the data when the edit button is clicked. Basically is should be the same as this example but without using knockoutjs
http://jsfiddle.net/jiggle/2cr2f/
#model IEnumerable<GenomindApp2.Areas.RulesEngine.ViewModels.GeneViewModel>
#{
ViewBag.Title = "Index2";
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.GeneValue)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneCode)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneName)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneComments)
</th>
<th>
#Html.DisplayNameFor(model => model.WildType)
</th>
<th>
#Html.DisplayNameFor(model => model.WildTypeAllele)
</th>
<th>
#Html.DisplayNameFor(model => model.AtRiskAllele)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.GeneCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.GeneName)
</td>
<td>
#Html.DisplayFor(modelItem => item.GeneComments)
</td>
<td>
#Html.DisplayFor(modelItem => item.WildType)
</td>
<td>
#Html.DisplayFor(modelItem => item.WildTypeAllele)
</td>
<td>
#Html.DisplayFor(modelItem => item.AtRiskAllele)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { }) |
#Html.ActionLink("Details", "Details", new { }) |
#Html.ActionLink("Delete", "Delete", new { })
</td>
</tr>
}
</table>
You should do it like that:
Model:
public class ModelB
{
public int Age { get; set; }
public string Name { get; set; }
}
Controller:
public ActionResult MyAction()
{
var model = new List<ModelB>
{
new ModelB{Age = 2, Name = "Bob"},
new ModelB{Age = 7, Name = "Sam"},
};
return View(model);
}
[HttpPost]
public ActionResult MyAction(List<ModelB> model)
{
//whatever
}
View:
#model List<TestWebApplication.Models.ModelB>
...
#using (Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
Age: #Html.EditorFor(modelItem => Model[i].Age);
Name: #Html.EditorFor(modelItem => Model[i].Name);
<br />
}
<input type="submit"/>
}
Please note that I used for instead of foreach. When you populate a form you shouldn't use foreach - it will not render well.