Hey, I am new to asp and I would like to ask you for some help. I built store with MvcMusicStore tutorial help. Now I want to add a View to manage orders which will display just OrderID (in Index View), then more info in Details View. Info will come from table which looks like this:
When I list OrderID, its multiplying because each product creates new record with the same OrderID in the table. Is there any way to display each Id just once?
Then I tried to display more info in Detaild View but I failed again. I used this code in Controller:
public ActionResult Details(int id)
{
var orderdetail = storeDB.OrderDetails.Single(a => a.Order.OrderId == id);
return View(orderdetail);
}
but obviously it wont work because only one element can be displayed. I also tried with foreach loop in Details.aspx but I was getting some IEnumerables-related error. Any advice is welcome, sorry for newbie question and bad English. Thank you.
Edit: Here is Controller's code for Index View (Product in my table equals Album in tutorial):
public ActionResult Index()
{
var manageorders = storeDB.OrderDetails
.Include("Product").Include("Order")
.ToList();
return View(manageorders);
}
And Details View code:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MasterPage.Master" Inherits="System.Web.Mvc.ViewPage<ss.Models.OrderDetail>" %>
Index
<div id="style3">manage orders</div>
<div id="style1">
<table>
<tr>
<th></th>
<th>
user
</th>
<th>
data
</th>
<th>
product
</th>
<th>
quantity
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { id=item.Order.OrderId }) %> |
<%: Html.ActionLink("Details", "Delete", new { id=item.Order.OrderId })%>
</td>
<td>
<%: item.Order.Username %>
</td>
<td>
<%: item.Order.OrderDate %>
</td>
<td>
<%: item.Quantity %>
</td>
<td>
<%: item.Quantity %>
</td>
</tr>
<% } %>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
And error I am recieving:
Compiler Error Message: CS1579: foreach statement cannot operate on variables of type 'ss.Models.OrderDetail' because 'ss.Models.OrderDetail' does not contain a public definition for 'GetEnumerator'
Single() will throw an exception if there's more than 1 element in the sequence, so the error here is because each Order can have many OrderDetails (this is your IEnumerable-ish error). If you wanted to select the first match, when there could be many, use the First() method, which won't throw if there's more than one.
It depends really what your controller is working with - Orders or OrderDetails. This would be the difference between Orders/Details/1 and OrderDetails/Details/1, where the first would be focussing on the whole order and all of its details, and the second would be looking at one specific line.
If you wanted to work with the order - which it looks like you're going for - then you'd need a reference of some kind from the Order to its collection of OrderDetails. If you're using something like Entity Framework like in the MusicStore tutorial, then you'll get this collection as part of your entity model. You would pass the Order to the view, and could then access the OrderDetails collection in a for each or similar loop e.g.
public ActionResult details(int id)
{
Order viewModel = storeDb.Orders.Single(o => o.Id = id);
return View(viewModel);
}
This wouldn't throw if Id is the unique per order, because there is only a single match (not many). Your view could then have something like:
<ul>
<% foreach (OrderDetails od in Model.OrderDetails) { %>
<li><%: od.UnitPrice %> (Or whatever information you wanted to show) </li>
<% } %>
</ul>
I'm assuming you would be using a strongly typed view of type Order, otherwise you'd have to work with ViewData, but it looks from your question like you're happy enough with those concepts already.
Edit - adding more...
1.The typing of your page is causing you some problems, make sure you are clear in your own mind exactly what your Model is. If you are passing in a list - like you would in an Index action - you need a page that inherits ViewPage> (you can see this in the <%# Page %> declaration at the top of the page). If you're going to write code like "for each... in model", that would imply that your model must contain more than one thing. This is where your "GetEnumerator" error message is from.
Your view as posted inherits ViewPage, i.e. the model is a single object, not a collection of objects, and so "for each ... in model" has no sensible meaning. The type of your View should be the same as the type being passed down by your controller. Your Index method passes a List, and List is an example of an IEnumerable. Your details however passes a single YourModelClass.
2.The error message "Compiler Error Message: CS1061: 'ss.Models.OrderDetail' does not contain a definition for 'OrderDetails'" - check your model, if there are relationships (foreign keys etc) between your tables, they should be joined on the model diagram, and you'd normally have navigation properties as well. The fact that you're getting this message means that something in that isn't there.
3.I'd suggest it might be worth checking out some of the videos, as the explanations are quite handy. Try some of the videos at http://www.asp.net/mvc/fundamentals . I Joe Stagner's "For the rest of us" series are very good, and as a starting point Stephen Walther's "Creating a Movie DB Application" would help, as it shows this kind of thing.
Related
I have an existing web application built using ASP.NET WebForms and I am converting it to MVC 4.0. I have an administrative page that allows user to do CRUD operations on same page for employee such as edit address or add multiple addresses at same time by dynamically adding usercontrols. I have implemented ListView for displaying, editing and saving on same page. Now if I want to achieve same thing i.e. display/Edit/Save on the same view in MVC could someone suggest good practices for such scenario. (p.s. I have partial views ready for such CRUD operations)
Any help will be greatly appreciated.
Yes there are many way you can achieve this in MVC. Just like ListView,there are many third party controls which acts as ListView in MVC. But if you don not want to use those third party controls,then you can go with Table,Tr and Td. For that purpose, lets take an example. Your model is returning the list of data so that you need to display that list on the View. So get that list and use foreach loop and just use Table,TH,TR and TD. You can use #Html.ActionLink for Edit,Delete,etc. Hope this will help you.
I have implemented the similar thing in the MVC:
View:
// Creating html Table from data present in model
<table class="content-wrapper">
<tr>
<th>
#Html.DisplayName("Name")
</th>
<th>
#Html.DisplayName("ID")
</th>
<th>
#Html.DisplayName("Designation")
</th>
<th>
</th>
</tr>
#foreach (var item in Model.lstEmployees)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.id)
</td>
<td>
#Html.DisplayFor(modelItem => item.designation)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.id })
#Html.ActionLink("Delete", "Delete", new { id = item.id })
</td>
</tr>
}
Controller:
public ActionResult Delete(Data model)
{
//Code for delete
return View("Index", data);
}
[HttpGet]
public ActionResult Edit(Int32 Id)
{
//code for binding the existing records
return View(_data);
}
[HttpPost]
public ActionResult Edit(string sampleDropdown, Data model)
{
//code for saving the updated data
return RedirectToAction("Index", "Home");
}
As I wanted to use the same view to show/edit/save, I found a solution to implement AJAX and render partial views for CRUD operations. This can be achieved in many ways but I selected two options:
Using #Ajax.BeginForm and jquery.unobtrusive-ajax.min and just fetching partialview.
Using jQuery AJAX to acheive this.
Here is a link I found in Stackoverflow very helpful:
Using Ajax.BeginForm with ASP.NET MVC 3 Razor
(Thanks all for your effort)
i want to make a form using below code i developed Model for View :
Please read the following blog post to better understand how the model binding works for collections and how your input fields should be named: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
OK, now let's get rid of this foreach loop and use editor templates, shall we?
<table style="width:65%; vertical-align:top" id="sample">
<%= Html.EditorFor(x => x.Properties) %>
</table>
and now define an editor template that will automatically be rendered for each element of the properties collection (~/Views/Shared/EditorTemplates/PropertyModel.ascx):
<%# Control
Language="C#"
AutoEventWireup="true"
Inherits="System.Web.Mvc.ViewUserControl<PropertyModel>"
%>
<tr>
<td>
<%= Html.LabelFor(x => x.ParameterName) %>
</td>
<td>:</td>
<td>
<%= Html.TextBoxFor(x => x.ParameterName) %>
</td>
</tr>
As far as those radio buttons are concerned, there's something wrong in your design about them. They are not part of the collection model but part of the main view model and yet you are putting them inside the foreach loop that is rendered for each element of the collection property. You might need to rethink what you are trying to do here.
I'm new to MVC.
In the tutorials I've gone through they say it is good practise to have your entities object disposed of after it is passed to the view. Like so...
using(MyProjectEntities db = new MyProjectEntities)
{
return View(db.PersonAddresses.ToList());
}
However I don't want to just display the IDs of the Person and the Address records that are linked in the PersonAddress table. I want the whole shebang and I get an error when I do the following in my view.
<% foreach (var item in Model) { %>
<tr>
<td>
<%: item.Person.LastName + ", " + item.Person.FirstName %>
</td>
<td>
<%: item.Address.AddressLine1+ "<br />" + item.Address.AddressLine2 %>
</td>
<td>
<%: item.Room.RoomName %>
</td>
<td>
<%: String.Format("{0:g}", item.Date) %>
</td>
</tr>
<% } %>
However if do
MyProjectEntities db = new MyProjectEntities;
return View(db.PersonAddresses.ToList());
My view works fine.
Is there a better way of passing those values to the view where I can dispose of the Entities object properly?
One way is to "eager" load the data by adding .Include in your LINQ query, this pre-loads the specified data so it is ready to go.
It's better not to access your data layer directly from your controllers. I would create a separate business logic layer or service layer, and call that from the controllers, instead of calling the data access layer from your controllers. So your data access layer is not directly accessed by your user interface layer. This issue would then be moot.
I'm a complete C# AND MVC noob, so this one's been a bitter struggle for me.
I've done a horrible but ultimately successful job of building a website for work to display the results of the impending primary/local elections.
What I need in the final view of my site is to display all the results of races in the same category. For example, there are three city commission positions open, and I need results for all three races on one page. I can display all the results I want, filtered by category, and in the pretty css table, what I can't seem to figure out is how I split that table up with sub headings for each of the individual races.
The data is direct Linq to SQL and comes out of a single view on the server (repositories are a thing that will have to happen in my next project unless they are essential to this function).
I'm not quite sure if this is what you are after, do let me know and I'll try to help.
This won't work directly for you, but hopefully might point you in the right way. I'm currently using a custom view model to hold this data, which I'm actually thinking of moving away from as my system is getting very complicated, but it might help you.
I can explain what that means if you need me to, (I was a noob just a year ago!)
I have assumed that you want races grouped by category.
<% foreach (var group in Model.GroupBy(item => item.categoryId)) Gives you the inital sort
{ %>
<% foreach (var item in group.Take(1))
{ //Category %>
<%=Html.Encode(item.CategoryName) %>
<% } %>
<% foreach (var item in group)
{ //Indervidual races%>
<%=Html.Encode(item.raceResult) %>
<% } %>
<% foreach (var item in group.Take(1))
{ %>
<!-- Area which happens after each category grouping -->
<% } %>
<% } %>
THANK YOU!! That was precisely the information I was looking for. Model.groupby was the break through for me.
Here's the code I used in the final FWIW:
<%
foreach (var group in Model.GroupBy(item => item.contestNumber))
{
foreach (var item in group.Take(1))
{
%>
<table width="600">
<tr>
<th>
<%: item.txtContest %>
</th>
<th width="40"></th>
</tr>
<%
foreach (var result in group)
{
%>
<tr>
<td>
<%: result.Candidate %>
</td>
<td>
<%: result.voteTotal %>
</td>
</tr>
<%
}
%>
</table>
<br />
<br />
<br />
<%
}
}
%>
We have a small Asp.Net MVC project which displays a report of several tens or hundreds of rows of data. Each row is represented by an object on the view models.
Currently we are showing the rows like this:
<table>
<tr style="text-align:center">
<th>Name</th>
<th>Item count</th>
<th>Stat 1</th>
<th>Stat 2</th>
<th>Etc</th>
</tr>
<% var alternating = false;
foreach(RowItem rowItem in Model.RowItems)
{ %>
<%= Html.BeginRow(alternating) %>
<%= Html.ShowRow(rowItem) %>
<% alternating = !alternating; %>
<%= Html.EndRow() %>
<% } %>
</table>
Where BeginRow, EndRow and ShowRow are helper extension methods that I wrote. ShowRow is something like
public static string ShowRow(this HtmlHelper html, RowItem rowItem)
{
return "<tr><td>.... </tr>";
}
But I could also replace Html.ShowRow(rowItem) with another partial view, i.e. Html.RenderPartial("RowControl", rowItem);
The question is, what are the advantages and drawbacks of these two approaches? All I can think of is that the partial view is more "designable" - easier to work with when the amrkup is complex, and by team members who specialise in "design" and "client development", i.e. html, css and javascript not c#. The HTML helper method is a just assembling a string containing the required html, which appeals to an old-school coder.
Which one, if any, has noticeable performance implications over hundreds of items? Are there maintenability impacts for either of them? All other things being equal, which would you choose to use?
We are on Asp.Net MVC 1.0 and Visual Studio 2008, but will probably upgrade some time in the next few months.
I'm not sure how well known this is (I just found out by playing around myself), but you can actually use anonymous methods to define chunks of your page content, so that is an alternative to defining a separate partial view. I find this especially useful when just have a small chunk of HTML/server code that I want to reuse, or if I don't want to define a complex Model/ViewData contract between a partial view and the calling view.
Below is an example of some code embedded in a view:
// define example data
IEnumerable<MyDataItem> data = new MyDataItem[] {
new MyDataItem { Id = 1, Value = "ABC" },
new MyDataItem { Id = 1, Value = "BCD" },
new MyDataItem { Id = 1, Value = "CDE" },
new MyDataItem { Id = 1, Value = "DEF" },
};
// an anonymous method to define reused HTML/server code
Action<MyDataItem> displayData = delegate(MyDataItem item)
{
%><span class="my-data-class" title="This is my data!"><%= item.Value %></span><%
};
%><div><%
// use the displayData delegate to render a table
%><table><%
foreach (MyDataItem item in data)
{
%><tr><td><% displayData(item); %></td></tr><%
}
%></table><%
// use the displayData delegate to render a set of divs
foreach (MyDataItem item in data)
{
%><div><% displayData(item);%></div><%
}
%></div><%
The above example renders the following HTML (formatted for clarity):
<div>
<table>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
ABC</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
BCD</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
CDE</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
DEF</span>
</td>
</tr>
</table>
<div>
<span class="my-data-class" title="This is my data!">ABC</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">BCD</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">CDE</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">DEF</span>
</div>
</div>
When creating views for MVC projects, I generally try to keep all of the same element generation in the same view. So for your case, since you are creating a table, I would make sure that all table tags are created inside the same view. This helps ensure that you are creating well formed HTML and makes tracking down validation issues much easier.
I don't really like what is going on here so much for a couple of reasons. The show row extension is likely taking some kind of custom HtmlTableRow object as its input, which likely has a collection of HtmlTableCell objects in it, each of which has stylistic properties set on it. Since these HtmlTableRows are created in your controller, it tightly couples your presentation to your controller which defeats the separation of concerns principle of MVC.
Next, if you replace ShowRow with a render partial, it will not follow the guideline I suggest in the first paragraph by rendering tags for the same element in different views. Occasionally you can get away with rendering your elements in different functions, but if you do so, the objects they return should implement the disposable pattern and only be implemented with using statements.
If I were going to modify this so that designers could have more control over the design, I would render the table all in one partial view, and I would give every cell a descriptive class name. I would also take the entire table and put it in a partial view, even if it were the only thing on this page.