MVC: Displaying table data not working as expected - asp.net-mvc

I have this table in database:
I'm trying to display the the values (ModuleID and DateEntered) in the browser as table.
I'm using viewbag to pass the value to my view, which is not quite the right way as I get just one row right now. What I'm doing right now is
public ActionResult Index()
{
var modules = (from entries in _db.Modules
orderby entries.DateEntered
select entries);
ViewBag.entries = modules.ToList();
return View();
}
How can I get all rows from the table in above picture and pass it to view?
In my view I currently have:
#using BootstrapSupport
#model Sorama.DataModel.SIS.ModuleStock.Module
#{
ViewBag.Title = "Index";
Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
}
<table class="table table-striped">
<caption></caption>
<thead>
<tr>
<th>
Module ID
</th>
<th>
Date Entered
</th>
</tr>
</thead>
<tr>
#foreach (var entry in ViewBag.entries)
{
<td>#entry.ModuleId</td>
<td>#entry.DateEntered</td>
}
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
Action
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>#Html.ActionLink("Details", "Details")</li>
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Admin"))
{
<li class="divider"></li>
<li>#Html.ActionLink("Edit", "Edit")</li>
<li>#Html.ActionLink("Delete", "Delete")</li>
}
</ul>
</div>
</td>
</tr>
</table>
This shows the values of entire row and not just (ModuleID and DateEntered)
This is what I get in browser.
To sum up, I want to get all the rows from table but only specific columns.
Which is not happening at current situation.
Suggestions?

You misreading your results. There are 3 records with 2 fields each displayed in one row. You have single <tr> in your view and you insert values from ViewBag in <td> tags. You should put new <tr> for each of your record in ViewBag.
It should look more like this:
#foreach (var entry in ViewBag.entries)
{
<tr>
<td>#entry.ModuleId</td>
<td>#entry.DateEntered</td>
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
Action<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>#Html.ActionLink("Details", "Details")</li>
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Admin"))
{
<li class="divider"></li>
<li>#Html.ActionLink("Edit", "Edit")</li>
<li>#Html.ActionLink("Delete", "Delete")</li>
}
</ul>
</div>
</td>
</tr>
}

Try this
public ActionResult Index()
{
ABCList abc=new ABCList();
var modules = (from entries in _db.Modules
orderby entries.DateEntered
select new ABC {
id=entries.id,
ModuleTypeId=entries.ModuleTypeId,
ModuleId=entries.ModuleId,
DataEntered=entries.DataEntered
});
abc.settings = modules.ToList();
return View();
}
public class ABC
{
public long Id{ get; set; }
public long ModuleTypeId{ get; set; }
public string ModuleId{get;set;}
public DateTime DataEntered{ get; set; }
}
public class ABCList{
public List<ABC> Settings { get; set; }
}
View
#model ABCList
#foreach (var entry in Model.Settings)
{
<tr>
<td>#entry.ModuleId</td>
<td>#entry.DateEntered</td>
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
Action<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>#Html.ActionLink("Details", "Details")</li>
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Admin"))
{
<li class="divider"></li>
<li>#Html.ActionLink("Edit", "Edit")</li>
<li>#Html.ActionLink("Delete", "Delete")</li>
}
</ul>
</div>
</td>
</tr>
}

Related

How to pass data from Controller to _Layout.cshtml

I show list of city in _Layout. I use a ViewBag for pass data to this,
#{
var cities = (List<CustomCityViewModel>)ViewBag.Cities;
}
<ul class="list-items">
#foreach (var city in cities)
{
<li>
<span>
#if (city.Id == null)
{
<a href="#Url.Action("Search","Home")">
#city.Name
</a>
}
else
{
<a class="city-search-item" data-name="#city.Name" data-id="#city.Id">
#city.Name
<i class="fa fa-angle-left"></i>
</a>
}
</span>
</li>
}
</ul>
I should set viewbag value in every action.
How can I send data so that it is not assigned inside each action?
//create a base Model class
public class BaseModel
{
public BaseModel(){
//here init base data to get in _layout
//sete data to cities
}
public IList<City> cites{set;get;}
}
// all other Model extend from BaseModel
// in your _Layout use BaseModel
#model BaseModel
#{
var cities =Model;
}
<ul class="list-items">
#foreach (var city in cities)
{
<li>
<span>
#if (city.Id == null)
{
<a href="#Url.Action("Search","Home")">
#city.Name
</a>
}
else
{
<a class="city-search-item" data-name="#city.Name" data-id="#city.Id">
#city.Name
<i class="fa fa-angle-left"></i>
</a>
}
</span>
</li>
}
</ul>

Models not collecting values from View to HttpPost Controller Method

I am currently trying to pass a list of models from my view to my controller. Currently, I am able to grab each model from the view and place them inside of a list and pass the list within the HttpPost controller ActionResult method. However when doing this, none of the models have their data within them as all of the models have their property values set to either 0 or null.
My code is as follows:
View:
#using (Html.BeginForm("SaveCarouselImageData", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="card shadow">
<div class="card-header border-0">
<div class="row align-items-center">
<div class="col">
<h3 class="mb-0">Homepage Carousel</h3>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table align-items-center table-flush">
<thead class="thead-light">
<tr>
<th></th>
<th scope="col">Image</th>
<th scope="col">Order Num</th>
<th></th>
</tr>
</thead>
<tbody id="carousel-content">
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<th><input type="number" value="#Model[i].getId()" name="id" hidden readonly /></th>
<th scope="row">
<img src="#Url.Content(Model[i].getImgLoc())" name="imgLoc" class="carousel-img-thumbnail" alt="Image" />
</th>
<td>
#Html.TextBoxFor(model => model[i].orderNum, Model[i].getOrderNum().ToString(), new { type = "number", name = "orderNum" })
</td>
<td>
<a class="btn btn-danger btn-lg btn-block openDeleteModal" data-toggle="modal" href="#deleteImageModal" data-id="#Model[i].getId()">
DELETE
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="row form-button-group">
<div class="col-md-6 col-sm-12 form-button-padding">
<button type="button" class="btn btn-success btn-lg btn-block" data-toggle="modal" data-target="#addImageModal">
+ Add New Image
</button>
</div>
<div class="col-md-6 col-sm-12 form-button-padding">
<button type="submit" class="btn btn-primary btn-lg btn-block">
Save Changes
</button>
</div>
</div>
}
Controller:
// POST: Saves Carousel Image Data
[HttpPost]
public ActionResult SaveCarouselImageData(List<CarouselModel> images)
{
if (!checkLoginCredentials())
{
return RedirectToAction("Login", "Home");
}
else
{
List<CarouselModel> updatedModels = new List<CarouselModel>();
foreach (CarouselModel img in images)
{
CarouselModel dbModal = siteServices.getCarouselImageById(img.getId());
dbModal.setOrderNum(img.getOrderNum());
}
int result = siteServices.updateCarouselTable(updatedModels);
return RedirectToAction("HomepageCarousel", "Admin");
}
}
Model:
public class CarouselModel
{
[Display(Name="id")]
private int id;
[Display(Name = "imgLoc")]
private string imgLoc;
[Display(Name = "orderNum")]
public int orderNum;
public int getId()
{
return this.id;
}
public string getImgLoc()
{
return this.imgLoc;
}
public int getOrderNum()
{
return this.orderNum;
}
public void setId(int id)
{
this.id = id;
}
public void setImgLoc(string imgLoc)
{
this.imgLoc = imgLoc;
}
public void setOrderNum(int orderNum)
{
this.orderNum = orderNum;
}
}
Again, the models themselves are currently getting passed from the View and into the List for the SaveCarouselImageData method, but all of their property values are null or 0.
Please assist.
all of their property values are null or 0.
I think that's because your CarouselModel's properties lack get;set; which the ASP.NET MVC Binding makes use of by default.
During POST, the binder will try to bind the form values to that of your model, but since it lacks accessors, it can't set any of the values that comes from the form.
Besides that, they're both specified to be Private which can only be accessed within the class, you should use Public if you want them to be set externally.
The easiest solution is to make them Public and add the accessors get;set;:
[Display(Name="id")]
public int id {get;set;}
[Display(Name = "imgLoc")]
public string imgLoc {get;set;}
[Display(Name = "orderNum")]
public int orderNum {get;set;}
If you still want ID and ImgLoc to remain Private then, you could do something like this;
private int _id {get;set;}
private string _imgLoc {get;set;}
[Display(Name = "orderNum")]
public int orderNum;
[Display(Name="id")]
public int id{
get{
return this._id;
}
set{
this._id = value;
}
}
[Display(Name = "imgLoc")]
public string imgLoc{
get{
return this._imgLoc;
}
set{
this._id = value;
}
}
Then change your HTML input fields to use the public properties.

Everything displays correctly except for the list of products of a category

I am making a webpage using ASP.NET Core MVC. It's an online store. The issue I have is that everything displays correctly except for the list of products of a category.
Category and Product have a one-to-many relationship in the SQLite database I am working with. When I list the category, id, name, description.., works superb, but the products in that category don't show.
This is the code where I have the issue. #Model.Products is the correct call, but I tried everything, from transforming it ToList(), ToString(), or searching for the products using a foreach loop:
#model Packt.Shared.Category
#{
ViewData["Title"] = "Category Details - " + Model.CategoryName;
}
<h2>Category Details</h2>
<hr/>
<div class=dl-horizontal>
<dt>Category ID</dt>
<dd>#Model.CategoryID</dd>
<dt>Category NAme</dt>
<dd>#Model.CategoryName</dd>
<dt>Category description</dt>
<dd>#Model.Description</dd>
<dt>List of products of the category</dt>
<dd>#Model.Products</dd> <!-Here it doesnt show a thing, not even with ToString() nor ToList(), also tried with Async->>
</div>
The button that launchs the code is the View button in the Index.cshtml razor page. How do I call the list of Products in the Category (1-to-many relationship)?:
#model NorthwindMvc.Models.HomeIndexViewModel
#{
ViewData["Title"] = "Radical Change";
string currentItem = "";
}
<div id="categories" class="carousel slide" data-ride="carousel"
data-interval="3000" data-keyboard="true">
<ol class="carousel-indicators">
#for (int c = 0; c < Model.Categories.Count; c++)
{
if (c == 0)
{
currentItem = "active";
}
else
{
currentItem = "";
}
<li data-target="#categories" data-slide-to="#c"
class="#currentItem"></li>
}
</ol>
<div class="carousel-inner">
#for (int c = 0; c < Model.Categories.Count; c++)
{
if (c == 0)
{
currentItem = "active";
}
else
{
currentItem = "";
}
<div class="carousel-item #currentItem">
<img class="d-block w-100"
src="~/images/category#(Model.Categories[c].CategoryID).jpeg"
alt="#Model.Categories[c].CategoryName" />
<div class="carousel-caption d-none d-md-block">
<h2>#Model.Categories[c].CategoryName</h2>
<h3>#Model.Categories[c].Description</h3>
<p>
<a class="btn btn-primary"
href="/Home/CategoryDetail/#Model.Categories[c].CategoryID">View</a>
</p>
</div>
</div>
}
</div>
<a class="carousel-control-prev" href="#categories"
role="button" data-slide="prev">
<span class="carousel-control-prev-icon"
aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#categories"
role="button" data-slide="next">
<span class="carousel-control-next-icon"
aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="row">
<div class="col-md-12">
<h1>Radical Change - Hairdresser</h1>
<p class="lead">
We've had #Model.VisitorCount visitors this month.
</p>
<form asp-action="ProductsThatCostMoreThan" method="get">
<input name="price" placeholder="Enter product price" />
<input type="submit" value="Submit" />
</form>
<form asp-action="Customers" method="get">
<input name="country" placeholder="Select a country" />
<input type="submit" value="Submit" />
</form>
<h2>Productos</h2>
<div id="newspaper">
<ul>
#foreach (var item in #Model.Products)
{
<li>
<a asp-controller="Home"
asp-action="ProductDetail"
asp-route-id="#item.ProductID">
#item.ProductName costs
#item.UnitPrice.Value.ToString("C")
</a>
</li>
}
</ul>
</div>
</div>
</div>
First of all, you could not use #Model.Products to show all products' info on view.Then, your action code should use Include method to retrieve the navigation properties' value.
Finally,refer to my simple demo shown below.
1.Assume that you have below models:
public class Category
{
[Key]
public long CategoryID{ get; set; }
public string CategoryName{ get; set; }
public string Description{ get; set; }
public virtual ICollection<Product> Products{ get; set; }
}
public class Product
{
[Key]
public long ProductID{ get; set; }
public string ProductName{ get; set; }
public long CategoryId{ get; set; }
public virtual Category Category{ get; set; }
}
2.For the Home/CategoryDetail, you need to use Include method to retrieve data:
public async Task<IActionResult> CategoryDetail(long? id)
{
if (id == null)
{
return NotFound();
}
var category = await _context.Category
.Include(s=>s.Products)
.FirstOrDefaultAsync(m => m.CategoryID == id);
if (category == null)
{
return NotFound();
}
return View(category);
}
3.To show Products info on Category/CategoryDetail razor view, you need to use #foreach:
#foreach(var item in Model.Products)
{
<h3>#item.ProductName</h3>
}

ASP.NET MVC CheckBox List sending always null

I want to create a table with items and checkboxes to select these items. I am including these checkboxes in a list but this list is always returning null. Thank you very much for your help.
Controller:
public ActionResult Index()
{
var expenseTypesView = new ViewExpenseTypesAndSelection
{
ExpensesTypes = _context.ExpenseType.ToList(),
};
return View(expenseTypesView);
}
[HttpPost]
public ActionResult SelectExpensesTypes( ViewExpenseTypesAndSelection SelectedExpenses)
{
var entry = new userSpecificExpenses();
var i = 0;
foreach (var item in SelectedExpenses.SelectedExpenses)
{
if(item)
{
entry.expenseTypeId = i;
entry.UtilisateurId= User.Identity.GetUserId();
_context.UserspecificExpenses.Add(entry);
_context.SaveChanges();
}
i++;
}
return View();
}
View:
#model MBT.ViewModels.ViewExpenseTypesAndSelection
....
#using (Html.BeginForm("SelectExpensesTypes", "ExpenseTypes"))
{
<table class="table table-bordered table-hover">
<thead>
<tr>
<th class="text-center">Expense</th>
<th class="text-center">Include</th>
</tr>
</thead>
<tbody>
#{
for (int i = 0; i < Model.ExpensesTypes.Count; i++)
{
<tr>
<td>
<div class="checkbox">
#Model.ExpensesTypes[i].Type
</div>
</td>
<td>
<div class="checkbox">
#Html.CheckBoxFor(m => m.SelectedExpenses[i])
</div>
</td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-primary">Submit</button>
}
You sending ViewExpenseTypesAndSelection almost null just with ExpensesTypes and then post it back to your post method. It means you send null and receive null.
So what is wrong with that?

MVC : Routing route value acting strange?

I have a viewmodel which looks like
public class BusinessUnitDetail
{
public Guid Id { get; set; }
public string Name { get; set; }
public LicensesDetails LicensesDetails { get; set; }
public RepresentativeDetails RepresentativeDetails { get; set; }
}
public class LicensesDetails
{
public string BusinessUnitName { get; set; }
public List<LicensesVM> Licenses { get; set; }
}
public class RepresentativeDetails
{
public string BusinessUnitName { get; set; }
public List<RepresentativeVM> Representatives { get; set; }
}
Currently my view contains two tables which shows List of Representative and List of Licenses.
Here is the view, quite long but anyways
#{
ViewBag.Title = "BusinessUnitDetails";
Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
int snor = 1;
int snol = 1;
}
<fieldset>
<legend>#Model.Name <small>Representatives</small></legend>
</fieldset>
<table class="table table-striped table-hover table-bordered">
<caption></caption>
<thead>
<tr>
<th>S.No</th>
<th>Name</th>
</tr>
</thead>
#foreach (var entry in Model.RepresentativeDetails.Representatives)
{
<tr>
#*#Html.HiddenFor(m=>entry.BusinessUnitId)*#
<td>#(snor++)</td>
<td>#entry.UserName</td>
<td>
<div class="btn-group" >
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
Action<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>#Html.ActionLink("Details", "RepresentativeDetails",routeValues:new{entry.BusinessUnitId})</li>
</ul>
</div>
</td>
</tr>
}
</table>
<fieldset>
<legend>#Model.Name <small>Licenses</small></legend>
</fieldset>
<table class="table table-striped table-hover table-bordered">
<caption></caption>
<thead>
<tr>
<th>S.No</th>
<th>Kind</th>
</tr>
</thead>
#foreach (var entry in Model.LicensesDetails.Licenses)
{
<tr>
#* #Html.HiddenFor(m=>entry.BusinessUnitId)*#
<td>#(snol++)</td>
<td>#entry.LicenseName</td>
<td>
<div class="btn-group" >
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
Action<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>#Html.ActionLink("Details", "LicenseDetails",routeValues:new{entry.BusinessUnitId})</li>
</ul>
</div>
</td>
</tr>
}
</table>
When i click the Details action of some row in License table, I expected it to redirect me to LicenseDetails action method as stated in Html.ActionLink, but it doesn't.
The route when i click the details action is
Customer/businessunit/LicenseDetails?BusinessUnitId=25c70a1d-0ed5-406f-8cae-1c6c1bf7d0da
I don't know how the LicenseDetails?BusinessUnitId= part is being generated, and why the action doesn't forward to the LicenseDetails method in controller.
What can I do so that, when i click the details action in second table, I get forwarded to proper controller action which proper Guid id
Any idea?
Edit 1: License Detail Action Methode
public ActionResult LicenseDetails(Guid licenseId)
{
var licenseDetails = _businessUnitRepository.GetLicenseDetail(licenseId);
return View(licenseDetails);
}
Your ActionLink seems fit to some routes. Type it more strongly with controllername:
#Html.ActionLink("Details", "LicenseDetails", "Home", new { licenseId = entry.BusinessUnitId }, null)
Try with this syntax:
#Html.ActionLink("Details", "LicenseDetails", new { licenseId = entry.BusinessUnitId })

Resources