Nested foreach loop in ASP.NET MVC - asp.net-mvc

I have problem with my nested foreach. As you see in the screenshot, it just returns all data in every dt.
I know how to solve my problem with a partial view. But I just want to know is there solution with foreach or some other loop.
public class VM
{
public IEnumerable<x> Upi { get; set; }
public IEnumerable<y> Adre { get; set; }
}
View
#foreach (var item in Model.Upi)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Surname)
</td>
<td>
#foreach (var smece in Model.Adre)
{
<div>
<pre>
#Html.DisplayFor(modelItem => smece.Ul)
#Html.DisplayFor(modelItem => smece.Ku), #Html.DisplayFor(modelItem => smece.Gr)
</pre>
</div>
}
</td>

Sorry guys I am stupid. It was simple. I just had to put one if.
if (smece.AU_ID == item.AU_ID) before pre and it works. TY all. Now only problem is, is there maybe other way where it doesnt need to iterate whole foreach and just go to direct AU_ID.

Related

Can't figure out razor syntax for my strongly typed view

I have a strongly typed view where I am trying to display a model when an id is passed to my Controller action method.
I am trying to construct a link to each of this models as well.
For the purpose before the beginning of my foreach I have an i=0, and then I am trying to increase it by 1 using i++. The problem is that the the i++ part doesn't work -- I have always zero as an id in my link. Why?
Can someone help with this?
#{
var i = 0;
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id = i })
i++;
</td>
</tr>
}
}
Razor does its best to distinguish code from markup/html/text, which isn't easy in general. And in this case, i++ is considered text.
The reason is that there are tags following the foreach { part, causing the reading mode to switch to markup/html/text. In that mode only #..., #{... or } are recognized as code, and everything else is treated as markup/html/text.
If this happens, just put #{ ... } around your statements, like this:
<td>
#Html.ActionLink("Details", "Details", new { id = i })
#{
i++;
}
</td>

display complex object properties in view asp.net

If I have two models
class Person {
public string Name {get;set;}
public DateOfBirth DOB {get;set;}
}
class DateOfBirth {
public int Year {get;set;}
public int Month {get;set;}
public int Day {get;set;}
}
and a view that tries to display this information
#model Person
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB.Year)
</td>
</tr>
What is the correct way of getting the values/information from the complex object "DateOfBirth"?
I'm currently trying this and the Year value is not being displayed, but the Name is being displayed because its just a string.
Thanks guys!
I think you're letting things get overly complicated with DisplayFor. You probably mean to do something like this:
#model IEnumerable<Person>
#foreach (var person in Model) {
<tr>
<td>
#person.Name
</td>
<td>
#person.DOB.Year
</td>
</tr>
When you start building a larger product, editor and display templates will allow you to get a lot of code reuse when you need to display basic information from your view models. But for now, that may be just a little more advanced than you need.

Passing entire Model from a View back to the Controller

I got a list of:
public class Items
{
public String Nro_Item { get; set; }
public Sucursal Sucursal { get; set; }
public Areas Area { get; set; }
public Sectores Sector { get; set; }
public bool ID_Estado { get; set; }
}
I'm passing it to this view:
#using ClientDependency.Core.Mvc
#model IEnumerable<TrackingOperaciones.Controllers.Items>
#{
ViewBag.Title = "Ver Items";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br/>
#using (Html.BeginForm("CargarRecibidos", "Recepcion", FormMethod.Post))
{
<table class="table table-striped table-bordered table-condensed">
<tr>
<th>
Numero
</th>
<th>
Sucursal
</th>
<th>
Area
</th>
<th>
Sector
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.ID_Estado)
</td>
</tr>
}
</table>
<p>
<input class="btn" name="Guardar" type="submit" value="Guardar"/> |
#Html.ActionLink("Volver al listado de RecepciĆ³n", "Index")
</p>
}
Until there everything is fine: Now the problem is getting back the entire model with the checked values in a controller for processing it like this one:
[HttpPost]
public ActionResult CargarRecibidos(IEnumerable<Items> items)
{
if (ModelState.IsValid)
{
//do something here
}
return RedirectToAction("Index");
}
}
But i'm falling miserably because "items" came back empty in the postback
i'm guess something is wrong with the form
#using (Html.BeginForm("CargarRecibidos", "Recepcion"))
{
<input class="btn" name="Guardar" type="submit" value="Guardar"/>
}
please help me!
Use IEnumerable
Then the controller input parameter will be List
Perhaps also consider using AJAX POST with JSON objects in place of a form submit (more modern/elegant) but submits are fine too.
Part of the problem is it won't post the entire model since only the checkbox is a form value. I think you need to add an additional hidden value in your form to track the item number and then handle the checkbox values specially in the controller. The item number is appended to "checkbox" in the posted values to keep them distinct.
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
#Html.Hidden("Nro_Item", item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBox("checkbox" + item.Nro_Item, item.ID_Estado)
</td>
</tr>
In the controller only bind to the number item so it can be used to process the checkboxes:
[HttpPost]
public ActionResult CargarRecibidos(List<string> nro_item)
{
foreach (string item in nro_item)
{
var checkbox=Request.Form["checkbox" + item];
if (checkbox != "false") // if not false then true,false is returned
{
// Do the action for true...
}
else
{
// Do the action for false
}
}
return View();
}

How to set a Viewmodel from several Models?

I would like to retrieve several items in one cell of a table in my view. I have several models, Product, Pack(as category), Order and OrderDetail. I think to achieve what I want, I should create a view model with data from my Models, but I don't really know how to do this and wich data i should bind.
This my view
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.OrderId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Username)
</td>
<td>
#Html.DisplayFor(modelItem => item.ClientID)
</td>
<td>
#Html.DisplayFor(modelItem => item.SiteNumber)
</td>
<td>
#if (item.Pack == null)
{
<ul>
#foreach (var tmp in item.????) //PRODUCT
{
<li>Html.DisplayFor(modelItem => tmp.Name) </li>
}
</ul>
}
else
{
<ul>
#foreach (var tmp in item.????) //PACK
{
<li>Html.DisplayFor(modelItem => tmp.Name) </li>
}
</ul>
}
</td>
<td>
#{
if (item.Pack == null)
{
<ul>
#foreach (var tmp in item.????) // PRODUCT
{
<li>Html.DisplayFor(modelItem => tmp.UnitPrice)
</li>
}
</ul>
}
else
{
<ul>
#foreach (var tmp in item.????) //PACK
{
<li>
#Html.DisplayFor(modelItem => tmp.UnitPricePack)
</li>
}
</ul>
}
}
</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.Total)
</td>
<td>
#Html.DisplayFor(modelItem => item.OrderDate)
</td>
</tr>
I would like my table looks like that at the end :
My question again, How can I create a ViewModel to retrieves data in my view and for it match with my #foreach condition inside ma table... I don't know if I am clear enough... This post follow this one . Actually, what i've done returns me error on error, I don't really know how to set up my viewmodel, which data I need to bind and how. Thanks for your help, your advices, I take all
You don't necessarily need a new ViewModel, Order has all you need. Your model will be a list of orders.
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.OrderId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Username)
</td>
<td>
#Html.DisplayFor(modelItem => item.ClientID)
</td>
<td>
#Html.DisplayFor(modelItem => item.SiteNumber)
</td>
<td>
<ul>
#foreach (var o in item.OrderDetails)
{
if (o.Pack == null)
{
<li>#Html.DisplayFor(modelItem => o.Product.Name) </li> //PRODUCT
}
else
{
<li>#Html.DisplayFor(modelItem => o.Pack.Name) </li> // PACK
}
}
</ul>
</td>
<td>
<ul>
#foreach (var o in item.OrderDetails)
{
if (o.Pack == null)
{
<li>#Html.DisplayFor(modelItem => o.UnitPrice) </li> //PRODUCT
}
else
{
<li>#Html.DisplayFor(modelItem => o.UnitPricePack) </li> //PACK
}
}
</ul>
</td>
<td>
<ul>
#foreach (var o in item.OrderDetails)
{
<li>#Html.DisplayFor(modelItem => o.Quantity)</li>
}
</ul>
</td>
<td>
#Html.DisplayFor(modelItem => item.Total)
</td>
<td>
#Html.DisplayFor(modelItem => item.OrderDate)
</td>
</tr>
}
Update according to your update:
You are still trying to pass collection of orderdetails instead of orders
instead of this:
var user = from m in db.OrderDetails
select m;
Have this ( assuming you have Orders table):
public ActionResult Index(string searchSite, string searchString)
{
var user = from m in db.Orders
select m;
if (!String.IsNullOrEmpty(searchString))
{
user = user.Where(s => s.ClientID.Contains(searchString));
}
if (!String.IsNullOrEmpty(searchSite))
{
user = user.Where(c => c.SiteNumber.Contains(searchSite));
}
return View(user);
}
i would suggest use of `AutoMapper', you can try
public class A{
public string FirstName{get;set;}
}
public class B{
public string LastName{get;set;}
}
now create a view mode
public class VModel{
public string FirstName{get;set;}
public string LastName{get;set;}
}
and where you want them to converge use auto mapper like
Mapper.CreateMap<A,VModel>();
Mapper.CreateMap<B,VModel>();
var ObjectOfClassA= new A{FirstName="John"};
var ObjectOfClassB= new A{LastName="Smith"};
VModel _model = Mapper.Map<A,VModel>(ObjectOfClassA);
_model = Mapper.Map<B,VModel>(ObjectOfClassB);
access it like
_model.FirstName;//should give you john
_model.LastName;//should give you smith

MVC 3 - Passing list of check boxes to and from a controller

I have a list of information sources in a database that I need to pass to a view in MVC. I need an end user to be able to tick the sources of information that apply to their course.
I am able to successfully pass the view a list of information sources alongside check boxes using the following code.
public ViewResult CreateUpdateInfoSource(int ProgrammeId)
{
List<ProgInfoSourceModel> viewmodel = new List<ProgInfoSourceModel>();
List<ProgInfoSourceDTO> myProgInfoDTOList = progInfoSourceService.AllInfoSources();
if (myProgInfoDTOList.Count != 0)
{
foreach (var x in myProgInfoDTOList)
{
ProgInfoSourceModel insert = new ProgInfoSourceModel();
insert.Selected = false;
insert.ProgrammeId = ProgrammeId;
insert.InfoSourceId = x.InfoSourceId;
insert.InfoSource = x.InfoSource;
insert.InfoReference = x.InfoReference;
insert.Rank = x.Rank;
viewmodel.Add(insert);
}
}
return View(viewmodel);
}
I am able to unpack this in the view just fine, however I am having real difficulty passing a the list back to my controller. I need to be able to loop through the list in my controller and see which ones do or don't apply so I can update the database.
My model looks like this:
namespace ProgrammeSpec.MVC.Models
{
public class ProgInfoSourceModel
{
[DisplayName("Selected")]
public bool Selected { get; set; }
[DisplayName("Programme Id")]
public int ProgrammeId { get; set; }
[DisplayName("Info Source Id")]
public int InfoSourceId { get; set; }
[DisplayName("Info Source")]
public String InfoSource { get; set; }
[DisplayName("Reference")]
public String InfoReference { get; set; }
[DisplayName("Rank")]
public int? Rank { get; set; }
}
}
My View looks like this:
<html>
<head>
<title>CreateUpdateInfoSource</title>
</head>
<body>
#using (Html.BeginForm())
{
<table>
<tr>
<th>
Selected
</th>
<th>
ProgrammeId
</th>
<th>
InfoSourceId
</th>
<th>
InfoSource
</th>
<th>
InfoReference
</th>
<th>
Rank
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.CheckBoxFor(modelItem => item.Selected)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProgrammeId)
</td>
<td>
#Html.DisplayFor(modelItem => item.InfoSourceId)
</td>
<td>
#Html.DisplayFor(modelItem => item.InfoSource)
</td>
<td>
#Html.DisplayFor(modelItem => item.InfoReference)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rank)
</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>
}
</table>
<input type="submit" value="Update" />
}
</body>
</html>
and the controller that the view gets passed to looks like this: (snippet)
[HttpPost]
public ActionResult CreateUpdateInfoSource(List<ProgInfoSourceModel> viewmodel)
{
if (ModelState.IsValid)
{
try
{
The problem is the viewmodel is null. I understand this is probably because I've unpacked the list in the view so it is no longer a list but how can I access the values of the check boxes then?
The added complication is that the number of info sources will vary so I can't use a static form or list and give each one an Id...
This must be a fairly common problem with a simple solution, but I'm an MVC novice and I don't know how to get round this.
Try using an editor template (Here's another SO that answers that question How to create custom editor/display templates in ASP.NET MVC 3?), for your ProgInfoSourceModel and then simply use Html.EditorFor(m => m.Model) on the View.
When you use the foreach loop, each checkbox is getting the same input name - and so is not actually submitting the correct data back.
If you go the editor template route, and making MVC do the hard work of iterating through the IEnumerable - it will create inputs with names like 'item[0].Selected' - which the model binder then correctly deserialized back into a list.
Phil Haack also blogged a fantastic walkthrough of exactly this scenario way back in 2008: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Resources