C# MVC foreach loop in view with model and viewbag - c#

Controller:
public ActionResult SelectPlaats()
{
var one = repository.GetAllReserveringen.Where(x => x.StartDatum >= x.StartDatum
&& x.StartDatum <= x.EindDatum).Select(p => p.Plaats);
var two = repository.GetAllPlekken.Select(p => p.Plaatsnummer);
ViewBag.vrijeplekken = two.Except(one).ToList();
return View(repository.GetAllPlekken);
}
View:
#using Camping.Domain.Entities
#model IEnumerable<Plek>
#{
ViewBag.Title = "Beschikbare campingplekken";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="panel panel-default">
<div class="panel-heading">
<h3>Overzicht van alle klanten</h3>
</div>
<div class="panel-body">
<table class="table table-striped table-condensed table-bordered">
<tr>
<th>Plaatsnummer</th>
<th>Veldnaam</th>
<th>Type</th>
<th>Vierkante meter</th>
<th>Amp</th>
<th>Wifi</th>
<th>Water</th>
<th>Riool</th>
<th>CAI</th>
<th>PPN</th>
<th>Seizoenplek</th>
<th class="text-center">Reserveren</th>
</tr>
#foreach (var item in Model.Where(x => x.Plaatsnummer == ViewBag.vrijeplekken))
{
<tr>
<td>#item.Plaatsnummer</td>
<td>#item.Veldnaam</td>
<td>#item.Type</td>
<td>#item.Vierkantemeter</td>
<td>#item.Amp</td>
<td>#item.Wifi</td>
<td>#item.Water</td>
<td>#item.Riool</td>
<td>#item.CAI</td>
<td>#item.PPN</td>
<td>#item.Seizoenplek</td>
<td class="text-center">
#using (Html.BeginForm("SelectPlek", "Reservering"))
{
#Html.Hidden("Id", item.Plaatsnummer)
<input type="submit"
class="btn btn-default btn-xs"
value="Reserveren" />
}
</td>
</tr>
}
</table>
</div>
</div>
So we have the Model with all the campingsides + details my camping application has. But I only want to display in this view the free campingspots.
I extracted all the free campingsides from my database and put them in my Viewbag.vrijeplekken which holds a list of the sidenumbers (Plaatsnummer).
I can't figure out how to get a table with only the free campingsidenumbers but with the details all the campingsides have.
I hope anyone can help me out. Thanks in advance!

Your View should only concern itself with presenting the data it receives in the (View)model.
It is up to the controller to select which data to display.
As Derek suggests:
public Actionresult SelectPlaats()
{
var one = repository.GetAllReserveringen.Where(x => x.StartDatum >= x.StartDatum && x.StartDatum <= x.EindDatum).Select(p => p.Plaats).ToList();
return View(repository.GetAllPlekken.Where(p => !one.Contains(p.plaatsnummer)).ToList());
}
or
public Actionresult SelectPlaats()
{
var one = repository.GetAllReserveringen.Where(x => x.StartDatum >= x.StartDatum && x.StartDatum <= x.EindDatum);
return View(repository.GetAllPlekken.Except(one).ToList());
}
And in your View:
#foreach (var item in Model)
{
....

Related

How to retrieve values from #Html.DisplayTextFor when #Html.CheckBox is checked?

I have made the following form but have some difficulties with retrieving values. The problem that I cannot seem to overcome is checking whether the #Html.CheckBox("check", new {#type="checkbox", #id="CheckBox"}) is checked or not and according to that save the #Html.DisplayTextFor(m => m.DLLsFull[i][0]) in a List. I was wondering if someone could guide me unto the right path / help me out to find out how I can do this.
Munch appreciated!
<div class="text-center">
<h1 class="display-6">Testsets per DLL</h1>
#using (Html.BeginForm("TestsetsPerDLL", "GenerateOverview", FormMethod.Post, new {#class = "d-flex flex-column"}))
{
<h1 class="w-50 text-start align-self-sm-center fw-lighter fs-5">Vul de output type in:</h1>
<table class="w-50 align-self-sm-center">
<tr>
<td>#Html.HiddenFor(m => m.Overview)</td>
#if (#ViewBag.OutputTypes == null || #ViewBag.OutputTypes.Count == 0)
{
<td>#Html.TextBoxFor(m => m.Output, new { #class = ""})</td>
}
else
{
<td>#Html.DropDownListFor(m => m.Output, new SelectList(#ViewBag.OutputTypes), "Selecteer een type", new {#class = " w-100"})</td>
}
</tr>
</table>
<partial name="_pager" model="Pager"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<table class="table table-striped">
#if (Model.DLLsFull is not null)
{
<tr>
<th>DLL</th>
<th>Titel</th>
<th>Beschrijving</th>
<th>Geselecteerd</th>
</tr>
#for (int i = 0; i < Model.DLLsFull.Count; i++)
{
<tr>
<td class="m-t-1 text-start">#Html.DisplayTextFor(m => m.DLLsFull[i][0])</td>
<td class="m-t-1 text-start">#Html.DisplayTextFor(m => m.DLLsFull[i][1])</td>
<td class="m-t-1 text-start">#Html.DisplayTextFor(m => m.DLLsFull[i][2])</td>
<td class="m-t-1 text-center">#Html.CheckBox("check", new {#type="checkbox", #id="CheckBox"})</td>
</tr>
}
}
</table>
<input class="btn btn-outline-primary" type="submit" value="Genereer" />
}
</div>````

Problem with foreach loop ASP.Net core MVC

Previous post
It is with reference to the previous post above.
Is there something wrong with the foreach loop or Action ManageCategories?
The page loads normally, but after removing the category, it cannot pass through the foreach loop
View:
#model collector_forum.Models.Category.CategoryIndexModel
#{
ViewData["Title"] = "Categories";
}
<div class="container body-content">
<div class="row sectionHeader">
<div class="sectionHeading">Browse Categories</div>
<div class="sectionDescription">
<p>Welcome to <strong>Collectors Forum community</strong>. Posts are categorized by their theme</p>
<p>
Please read the Forum Guidelines before creating a new post.
#if (Context.User.Identity.IsAuthenticated)
{
<span>
You must be a
<a asp-area="Identity" asp-page="/Account/Register">registered member</a>
to create a new post
</span>
}
</p>
</div>
</div>
<div class="row" id="categoryIndexContent">
<table class="table table-hover" id="categoryIndexTable">
<tbody>
#foreach (var category in Model.CategoryList)
{
<tr>
<td>
#*<div class="forumLogo" style="background-image: url(#category.ImageUrl);"></div>*#
<div class="categoryData">
<div class="categoryTitle">
<a asp-controller="Forum" asp-action="Topic" asp-route-id="#category.Id">#category.Name</a>
</div>
<div class="categorySubTitle">
#if (category.HasRecentPost)
{
<div class="hasRecentPost">Hot</div>
}
</div>
</div>
</td>
<td>
<div class="categoryPostCount">
#category.NumberOfPosts Posts
</div>
<div class="categoryMemberCount">
#category.NumberOfUsers Users
</div>
</td>
<td>
<div class="categoryDescription">
#category.Description
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
This is the error
And here code of my Delete Action:
public IActionResult Delete(int id)
{
var category = _categoryService.GetById(id);
if (category == null)
{
ViewBag.ErrorMessage = $"Category with ID = {id} cannot be found";
return View("NotFound");
}
else
{
var result = _categoryService.Delete(id);
if (result.IsCompletedSuccessfully)
{
return RedirectToAction("ManageCategories");
}
return View("ManageCategories");
}
}
What went wrong?
ManageCategories Action:
public IActionResult ManageCategories()
{
var categories = _categoryService.GetAll()
.Select(category => new CategoryListingModel
{
Id = category.Id,
Name = category.Title,
Description = category.Description
});
var model = new CategoryIndexModel
{
CategoryList = categories
};
return View(model);
}
After debugging method Delete seems doesn't work = > image
Delete Action
public async Task Delete(int id)
{
var category = GetById(id);
_context.Remove(category);
await _context.SaveChangesAsync();
}
You may change
return View("ManageCategories");
to
return RedirectToAction("ManageCategories");

Displaying Data from different tables in View

Just wanted to ask if there's something I missed here.
I have two tables that I joined together in my controller
using .NET MVC btw
anyway, here's my controller:
namespace Review.Controllers
{
public class ReviewController : Controller
{
ReviewContext db = new ReviewContext();
ReviewItemsContext db2 = new ReviewItemsContext();
MainDataModel db3 = new MainDataModel();
List<UAR_Review> uar_review = new List<UAR_Review>();
List<UAR_ReviewItems> uar_reviewitems = new List<UAR_ReviewItems>();
public ActionResult Index(int? page) {
ViewBag.AccList = (from r in db2.UAR_ReviewItems
select r.Account).Distinct();
/*var entities = from s in db2.UAR_ReviewItems
orderby s.Account
select s;*/
var entities = from s in uar_review
join st in uar_reviewitems on s.ID equals st.ReviewID into st2
from st in st2.DefaultIfEmpty()
select new MainDataModel { UAR_Review = s, UAR_ReviewItems = st };
int pageSize = 15;
int pageNumber = (page ?? 1);
return View(entities.ToPagedList(pageNumber, pageSize));
}
}
}
and here's my view:
#model PagedList.IPagedList<Review.Models.MainDataModel>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Review", FormMethod.Get))
{
<h2>Index</h2>
#section NavBar{
<h3>Period: 2 of 2018</h3>
#Html.DropDownList("userAccount", new SelectList(ViewBag.AccList), "Select Account to Filter")
<input type="submit" value="Search" />
}
#section MiddleSection{
<table class="table">
<tr>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Name")</span>
</th>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Role")</span>
</th>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Action")</span>
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
<span class="font-gotham-narrow">#item.UAR_Review.DisplayName</span>
</td>
<td>
<span class="font-gotham-narrow">#item.UAR_ReviewItems.Role</span>
</td>
<td>
#Html.HiddenFor(modelItem => item.UAR_ReviewItems.Response)
<span class="font-gotham-narrow">
#Html.RadioButton("Response", "Retain")#Html.Label("Retain") 
</span>
<span class="font-gotham-narrow">
#Html.RadioButton("Response", "Remove")#Html.Label("Remove")
</span>
</td>
</tr>
}
</table>
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
}
}
}
The problem is, when I run it there is nothing being displayed in the Site.here's the page.
I just wanted to ask if there's anything I missed.
Also, please disregard the dropdownlist on the left side, I've been planning to use it to sort the shown elements in the page by AccountType(This is stored in my UAR_ReviewItems table). For now, I'm just trying to figure out what's wrong here and why there are no elements being displayed.
Your screen grab does say the PageCount is 0.
Your Model in empty. Check your queries.

Select rows and pass data(ID) to next view, MVC5 C#

I have been trying to select multiple rows from my table of data(Generated using EF) and then pass all selected rows to the next view to perform some action. On passing the data to the next view i am getting the following error :
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Temporary local of type 'int[]'> was null.
Any help on how to solve this will be appreciated.
Below is my code:
View:
<div class="row">
<div class="col-md-12">
<!-- Advanced Tables -->
<div class="panel panel-default">
<div class="panel-heading">
#using (Html.BeginForm()) {
<form action="#" method="post">
<label>Search by Company Name:</label> #Html.TextBox("SearchString")
<input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;">
<label>Search by Card Number:</label> #Html.TextBox("searchCard")
<input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;">
Export to Excel
</form>
}
</div>
<div class="panel-body">
Add Gift Card
Get Card Balance
Load Cards
<br />
<br />
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th>Card ID</th>
<th>Company</th>
<th>Card Number</th>
<th>Card Number 2</th>
<th>Date Created</th>
<th>Card Status</th>
<th>Discount Level ID</th>
<th>Loyalty Level ID</th>
<th>Gift Card Enabled</th>
<th>Loyalty Enabled</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td><input type="checkbox" name="ids" value="#item.CardID" /></td>
<td>#item.CardID</td>
<td>#item.Customer.CustomerCompanyName</td>
<td>#item.CardNumber</td>
<td>#item.CardNumber2</td>
<td>#item.CardDate</td>
<td>#item.CardStatus</td>
<td>#item.DiscountLevelID</td>
<td>#item.LoyaltyLevelID</td>
<td>#item.GiftCardEnabled</td>
<td>#item.LoyaltyEnabled</td>
<td>
<i class="fa fa-edit "></i> Edit <br />
</td>
</tr>
}
</tbody>
</table>
Page #(Model.PageCount
< Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount #Html.PagedListPager(Model, page=> Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
</div>
</div>
</div>
<!--End Advanced Tables -->
</div>
</div>
Controller:
public ActionResult PostCards(int[]ids)
{
var myObject = new Card();
foreach(var id in ids)
{
myObject = db.Cards.Single(o => o.CardID == id);
return RedirectToAction("LoadCards", myObject);
}
return View();
}
public ActionResult LoadCards()
{
return View();
}
I need the selected data to be passed to the LoadCards view.
Let us first look at the NullReference you are getting. The problem here is that no correct index is created to bind the checkboxes to an array. Use a for loop instead of foreach. In MVC/Razor, how do I get the values of multiple checkboxes and pass them all to the controller?
To get the desired behaviour:
change the foreach to a for loop so the correct indices for sending the data will be created.
add a checkbox in each row that lets the user select the rows to submit.
your action should recieve a collection of models for each row. This model always transports the CardId and tells us whether it was selected.
public class SelectedCardModel {
public int CardId { get; set; }
public bool IsSelected {get; set;}
}
In the view:
#using (Html.BeginForm("PostCards", "CustomerView", FormMethod.Post) {
// <table> etc ...
<tbody>
#for (var i = 0; i < Model.Count; i++) {
#{ var item = Model.ElementAt(i); }
<tr>
<td>
#Html.Hidden("CardId[" + i + "]")
#Html.CheckBox("IsSelected[" + i + "]")
</td>
// display other properties of item ...
<td>#item.CardID</td>
// ...
</tr>
}
</tbody>
</table>
<button type="submit">Load Cards</button>
}
Action:
[HttpPost]
public ActionResult PostCards(SelectedCardModel[] selectedCards) {
foreach(var card in selectedCards) {
if (card.IsSelected) {
var selectedId = card.CardId;
// ...
}
}
}

Html.BeginForm() not passing the model

I have the following cshtml form:
model Scraper.Facade.PlayerRow
#using (Html.BeginForm("Calculate", "Home", FormMethod.Post))
{
<table class="table table-striped table-bordered table-condensed table-responsive table-hover">
#foreach (var player in Model.AttribsPlayerLine)
{
<thead>
<tr class="success">
#foreach (var attrib in player.AttribsPlayerList)
{
//#Html.DisplayNameFor(x => Model.tytul)
<th data-field="#attrib.attribName">#Html.DisplayFor(x => attrib.attribName) </th>
}
</tr>
<tr class="active">
#foreach (var attrib in player.AttribsPlayerList)
{
<td data-field="#attrib.attribValue">#Html.TextBoxFor(x => attrib.attribValue)</td>
}
</tr>
</thead>
}
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
which is displaying correctly and then I am trying to get the model in the following controller ActionResult
[HttpPost]
public ActionResult Calculate(PlayerRow model)
{
GenericHelper _genericHelper = new GenericHelper();
return View();
}
However the PlayerRow model is always null.
What am I doing wrong?
This is my model definition
public PlayerRow LoadHtmlDoc(string fileLocation)
{
List<Attrib> attribsHeaderList = new List<Attrib>();
var playerRow = new PlayerRow();
playerRow.AttribsPlayerLine = new List<AttribLine>();
var htmlDoc = new HtmlDocument { OptionFixNestedTags = true };
// There are various options, set as needed
// filePath is a path to a file containing the html
htmlDoc.Load(fileLocation);
}
public class PlayerRow
{
public List<AttribLine> AttribsPlayerLine;
}
UPDATE
Hi All, I changed a bit the logic of my application, basically having 2 lists which has the Header Attributes, and the Attributes for all the players, so only 2 classes now, and I changed the cshtml like this, which is working now :-
#using (Html.BeginForm("Calculate", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table class="table table-striped table-bordered table-condensed table-responsive table-hover">
<tr>
#for (int k = 0; k < Model.HeaderAttributes.Count; k++)
{
<td>
#Html.DisplayFor(x => x.HeaderAttributes[k].AttributeName)
#Html.HiddenFor(x => x.HeaderAttributes[k].AttributeName)
</td>
}
</tr>
#for (int i = 0; i < Model.PlayerList.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(x => x.PlayerList[i].PlayerName)
#Html.HiddenFor(x => x.PlayerList[i].PlayerName)
</td>
#for (int j = 0; j < Model.PlayerList[i].AttributesList.Count; j++)
{
<td>
#Html.DisplayFor(x => x.PlayerList[i].AttributesList[j].AttributeValue)
#Html.HiddenFor(x => x.PlayerList[i].AttributesList[j].AttributeValue)
</td>
}
</tr>
}
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
Now my problem is, who to award the Answer, since I can say that most of the Answers were really helpful to arrive to my solution
Here is a working example of what you're trying to do. This is about as a close as I can get you.
Let's start with the simplified models:
public class PlayerRow
{
public List<AttribLine> AttribsPlayerLine { get; set; }
}
public class AttribLine
{
public string attribName { get; set; }
public string attribValue { get; set; }
}
Note that it is IMPORTANT to include the { get; set; } on each model property so the model binder knows it's on the block for binding.
Next is a simplified view looking only at the form() section:
#using (Html.BeginForm("Calculate", "PlayerRow", FormMethod.Post))
{
<table>
#*/*Build out header*/*#
<tr>
#foreach (AttribLine a in Model.AttribsPlayerLine)
{
<th>#Html.Label("title", a.attribName)</th>
}
</tr>
#*/* Add row of our player attributes */*#
<tr>
#foreach (AttribLine a in Model.AttribsPlayerLine)
{
using (Html.BeginCollectionItem("AttribsPlayerLine"))
{
<td>
#Html.TextBox("attribValue", a.attribValue)
#Html.Hidden("attribName", a.attribName)
#*
/* Add any more [AttribLine] properties as hidden here */
*#
</td>
}
}
</tr>
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
Note that it is IMPORTANT here to make sure that even though a property is not editable by the user, it needs to be included as a hidden element inside our CollectionItem so the model binder can SET it on the [POST]
Hope this helps.
You are correctly passing the model to the view, but once it gets to the view, the model data will essentially be 'cleared' unless you either edit it or pass it on the next controller, in this situation "Calculate".
I'm not sure exactly what parts of the viewmodel you want passed to the controller, but you can always use this:
#Html.HiddenFor(model => model.DataYouWantPassedToController)
Now, you can always use these items also to pass data if you want to edit/change:
#Html.EditorFor(model => model.DataYouWantToEditAndPass)... and so on.
If you simple loop through data without changing or passing it, like you do in the #foreach, the data will be lost during your 'Post' method.
Try use a #Html.EditorForModel() like this:
#model Scraper.Facade.PlayerRow
#using (Html.BeginForm("Calculate", "Home", FormMethod.Post))
{
#Html.EditorForModel()
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
Create a file named PlayerRow.cshtml as PartialView on the folder Views/Shared/EditorTemplates and add the following code:
#model Scraper.Facade.PlayerRow
<table class="table table-striped table-bordered table-condensed table-responsive table-hover">
#foreach (var player in Model.AttribsPlayerLine)
{
<thead>
<tr class="success">
#foreach (var attrib in player.AttribsPlayerList)
{
//#Html.DisplayNameFor(x => Model.tytul)
<th data-field="#attrib.attribName">#Html.DisplayFor(x => attrib.attribName) </th>
}
</tr>
<tr class="active">
#foreach (var attrib in player.AttribsPlayerList)
{
<td data-field="#attrib.attribValue">#Html.TextBoxFor(x => attrib.attribValue)</td>
}
</tr>
</thead>
}
</table>
I think that this will help you.

Categories

Resources