asp.net mvc viewdata display in a viewpage - c#

I sent a viewdata to a view page like this.
public ActionResult SelectRes(int id)
{
var ResList = resrepository.GetAll();
ViewData["ResList"] = new SelectList(ResList, "ResId", "Res_KORNM");
return View(svcresrelationRepository.GetAll());
}
#foreach (var item in ViewData["ResList"] as List<ITSDapper.Dapper.Resource>)
{
<tr>
<td style="text-align:center;">
#Html.DisplayFor(a=> item.Res_KORNM)
</td>
</tr>
}
And I tried to display the viewdata in a view page but it's not worked.
(Object reference not set to an instance of an object)
How display the viewdata in foreach statement?

You would typically use a SelectList for data that is to be selected by a user.
If this is the intention you can just use an Html.DropDownList:
#Html.DropDownList("SelectedId",
(IEnumerable<SelectListItem>)ViewData["ResList"])
If you are simply needing to view the data, I would change your server-side code to use something other than a SelectList.
This could be done as follows:
Controller
public ActionResult SelectRes(int id)
{
var ResList = resrepository.GetAll();
ViewData["ResList"] = ResList;
return View(svcresrelationRepository.GetAll());
}
View
#foreach (var item in ViewData["ResList"] as List<ITSDapper.Dapper.Resource>)
{
<tr>
<td style="text-align:center;">
#Html.DisplayFor(a=> item.Res_KORNM)
</td>
</tr>
}

You are converting reference to wrong type, you are creating SelectList instance while in View you are convering it to IList<T>, you should convert it to SelectList:
#foreach (var item in ViewData["ResList"] as SelectList)
{
<tr>
<td style="text-align:center;">
#Html.DisplayFor(a=> item.Text) // note this as well
</td>
</tr>
}

Related

Sort DateTime object in DD/MM/YYYY format in .cshtml file

I currently have a for-loop in my .cshtml file which iterates through items inside a ViewBag. I want to sort these objects based on a DateTime property called orderDate in the Order.cs file. The for loop in the .cshtml file looks like the following:
<table id="order-history-table" class="table table-hover">
<thead>
<tr>
<th>
Order Number
</th>
<th>
Order Date
</th>
<th>
Order Total
</th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.list)
{
<tr>
<td>
<a class="orderNumber" data-toggle="modal" data-target="#modal-container" href="#Url.Action("orderDetails", "Orders", new { orderNumber = item.order.OrderNumber })">#item.order.OrderNumber</a>
<br />
#Html.ActionLink("Re-Order", "ReOrder", new { orderNumber = #item.order.OrderNumber }, new { onclick = "return confirm('Are you sure you wish to re-order?');" })
</td>
<td>#item.order.OrderDate.ToString("dd/MM/yyyy")</td>
<td style="text-align: center">$#(Math.Round(item.order.OrderTotal, 2))</td>
</tr>
}
</tbody>
I want this table to be sorted so that the most recent orders are shown at the top of the table. Since the data is being pulled from a database, and the tables values are generated dynamically, where do I perform this sorting? is it done through jQuery? How do I do this?
Thank you in advance
You can use LINQ OrderBy to do that.
So in your action method where you set the ViewBag.list, You can use OrderByDescending method on the collection.
var yourOrderList=new List<Order>();
// to do : Load Order items to yourOrderList
yourOrderList=yourOrderList.OrderByDescending(f=>f.OrderDate).ToList();
ViewBAg.list=yourOrderList;
I also recommend using a view model to pass data from your action method to view.
var yourOrderList=new List<Order>();
// to do : Add orders to yourOrderList
yourOrderList=yourOrderList.OrderByDescending(f=>f.OrderDate).ToList();
return View(yourOrderList);
And in your view
#model List<Order>
<h3>Orders</h3>
#foreach(var o in Model)
{
<p>#o.OrderDate.ToString()</p>
}
Since your view is strongly typed, you can do the same ordering in your razor view also as needed.
#model List<Order>
<h3>Orders</h3>
#foreach(var o in Model.OrderByDescending(g=>g.OrderDate))
{
<p>#o.OrderDate.ToString()</p>
}

how I can have a controller, which can pass (return) some model to _Layout.cshtml. view

I have a file index.cshtml which is auto generated by EF (code first). Following code is working fine in that file
#model IEnumerable<dyescan.Models.MyMainMenuItem>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ItemText)
</td>
<td>
#Html.DisplayFor(modelItem => item.LinkAction)
</td>
<td>
#Html.DisplayFor(modelItem => item.LinkController)
</td>
</tr>
}
But When I copy pasted the code in _layout.cshtml, I am unable to use this Model there.
Object reference not set to an instance of an object
I get above error in this line #foreach(var item in Model). Following is my code in _Layout.cshtml
#model IEnumerable<dyescan.Models.MyMainMenuItem>
#foreach(var item in Model)
{
<li>#Html.ActionLink(item.ItemText,item.LinkAction,item.LinkController)</li>
}
Update
So I tried to follow th comments this way. I made a Controller Shared (folder name) and in that controller I made an action _Layout (file name of the view). now it returns dbContex.MyMainMenuItems.. to the view
But still unable to make a controller for _Layout.. to pass it a model for my menuitems
When you use model in cshtml view, your Action method return model like :-
public ActionResult Index()
{
var items = themes.Select(o => new SelectListItem {Text = o, Value = o, Selected = o == theme});
return View(items);
}
When Action method return model it is bind to view. so in above code items will be bind to index.cshtml.
If you try to access this model in _Layout.cshtml it will give error.

Passing different types to view

I have a method in controler in which I pass to view objects with different type like:
case ItemType.Magnets:
{
return View(dbHelper.Magnets.Details(id));
}
case ItemType.Maps:
{
return View(dbHelper.Maps.Details(id));
}
How can I write a view for this?
You need to creates different views for different item. Here is solution
case ItemType.Magnets:
{
return View("MagnetsView",dbHelper.Magnets.Details(id));
}
case ItemType.Maps:
{
return View("Maps",dbHelper.Maps.Details(id));
}
If you want to display Magnets item you need to create Magnet view. Same for Maps.
You might want to create two different views, each called unique and each accepting its own viewmodel.
You will also want to specify view's name in the controller class:
return View("ViewName_1", dbHelper.Maps.Details(id));
or
return View("ViewName_2", dbHelper.Magnets.Details(id));
#AlexDefine unless you want to create a universal view for all types of properties inside, which is not that easy.
Part of it I have here:
#model object
<table>
#{
var properties = from prop in ViewData.ModelMetadata.Properties
let propInfo = prop.ContainerType.GetProperty(prop.PropertyName)
where !ViewData.TemplateInfo.Visited(prop)
select prop;
}
#foreach (var prop in properties)
{
<tr>
<td>
<div style="float: right;">
#prop.GetDisplayName()
</div>
</td>
<td>
<div class="editor-field">
#Html.Editor(prop.PropertyName, new { ContainerModel = Model })
</div>
</td>
</tr>
}
</table>
More or less, it makes a table of any kind of model. But you should upgrade it for your needs by self.

Dynamically load data with #Ajax.ActionLink using Skip() and Take()

I am new to ASP.NET MVC, so please help me to solve this, at a first glance, simple issue.
I have a table of students on my View and a Load More link below it. By clicking on this link I need to load more students records with AJAX.
So this is my View (omitted unnecessary data)
<table id="studentTable">
<thead>
...
</thead>
<tbody>
#Html.Partial("_StudentDetailsList", Model)
</tbody>
</table>
#Ajax.ActionLink("Load More", "LoadMoreStudents", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "studentTable"
})
_StudentDetailsList partial view to display students
#model IEnumerable<MvcApplication1.Models.Student>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
</tr>
}
action
public ActionResult LoadMoreStudents(int skip = 0)
{
return PartialView("_StudentDetailsList", studentRepository.Get(orderBy: s => s.OrderBy(st => st.FirstName).OrderBy(st => st.LastName)).Skip(skip).Take(10));
}
So as you can see, I want to load next 10 students every time, but I have to know how much are already loaded. So the question is: from where should I get this skip parameter which I want to pass to the Action from the View. How can I count on the View how many partial views are already loaded and how many students each partial has? Or is it a bad practice to pass this parameter to action, maybe I should handle it somewhere else (e.g. some service)? Please advice the right way to do this. Thanks.
P.S. Please feel free to edit the caption as I can't come up with appropriate one.
The easiest method would be to create a ViewModel that contains these variables for you.
ViewModel
public class YourViewModel(){
public int skip {get;set;}
public IEnumerable<StudentDetails> StudentDetailList {get;set;}
}
The Controller/Action Method
public ActionResult LoadMoreStudents(int skip = 0)
{
return PartialView("_StudentDetailsList", new YourViewModel{
StudentDetailList = studentRepository.Get(orderBy: s => s.OrderBy(st => st.FirstName).OrderBy(st => st.LastName)).Skip(skip).Take(10),
skip = skip + 10});
}
The View
#Html.Partial("_StudentDetailsList", Model.StudentDetailList)
The Partial View
#model MvcApplication1.Models.YourViewModel
<table id="studentTable">
<thead>
...
</thead>
<tbody>
#foreach (var item in Model.StudentDetailList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
</tr>
}
</tbody>
</table>
#Ajax.ActionLink("Load More", "LoadMoreStudents", new {skip = Model.skip}, new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "studentTable"
})
Basically, you have to be able to dynamically update the Ajax.ActionLink with values coming back from the controller. Here, I have moved it into the PartialView (arguabley you could move the entire table including the fetch more link into the PartialView and have it be even cleaner).
You are on the way. You should replace the Ajax.ActionLink for a link with $.get, and retrieve the skip by counting the numbers of rows at the tbody that you already have:
First replace the ActionLink for:
Load More Students here!
Second, create this function to do the get:
$('mylink').click(function (e) {
e.preventDefault();
//Gets the number of rows that you alredy have loaded
var rowCount = $('studentTable').find('tbody > tr').length;
//The URL for the get, with the number of rows
var url = "http://www.myurl.com/controller/action?skip=" + rowCount;
$.get(url, function (data) {
//Append the content from the partial view to the tbody
$('studentTable').find('tbody').append(data);
});
});
I think that this is a good way as well!
Hopes this help you!

How can I arrange items in a table - MVC3 view (Index.cshtml)

I want to show the amount of different types of vitamins present in specific types of food samples, using ASP.NET MVC3. How can I display this in my View (Index.cshtml) ?
an example:
And these are my codes:
<table>
<tr>
<th></th>
#foreach (var m in Model)
{
foreach (var v in m.Vitamins)
{
<th>#v.Name</th>
}
}
</tr>
#foreach (var m in Model)
{
foreach (var f in m.Foods)
{
<tr>
<td>#f.Type</td>
</tr>
}
}
</table>
#*The amount of Vitamins in each food:
var a in m.AmountOfVitamins
#a.Amount
*#
If the Amount collection is ordered correctly (I'm guessing yes), then you could use simply:
foreach (var f in m.Foods)
{
<tr>
<td>#f.Type</td>
foreach (var a in m.AmountOfVitamins)
{
<td>a.Amount</td>
}
</tr>
}
If they're in some other random order, then you'd need a way to sort them according to the header columns A, B, C, D ...

Categories