I am new to using the Entity Framework. I have added my Model, and I need to use two my models/tables in one View Page. So to do that I added this to my AccountViewModels.cs page:
public class category_menuitem
{
public Category Category { get; set; }
public MenuItem MenuItem { get; set; }
}
I am trying to use Values from those two Models/Tables.
My View Page:
using System.Data.SqlClient
#model IEnumerable<YourGoGetterV1.Models.category_menuitem>
#{
ViewBag.Title = "Show Menu" - ViewBag.restaurant_id;
}
<h2>ShowMenu</h2>
<div class="jumbotron">
#foreach (var item in Model)
{
<div><strong>#Html.DisplayFor(item1 => item.Category.Name)</strong>
<div>#Html.DisplayFor(item1 => item.Category.Description)</div>
#{
using (var context = new YourGoGetterContext())
{
SqlParameter sa = new SqlParameter("#p0", ViewBag.restaurant_id);
var menu_items = context.MenuItems.SqlQuery("Select * FROM MenuItems where restaurant_id = #p0", sa).ToList();
var test = "DID IT WORK??";
}
}
</div>
}
</div>
Controller:
public ActionResult ShowMenu(string id, int restaurant_id)
{
ViewBag.Id = id;
ViewBag.restaurant_id = restaurant_id;
return View(Models.category_menuitem.ToList((object(id)));
}
I want to cast the ID, so that it creates a different URL for something that passes in a different ID. But I'm having two problems.
1) I can't even put in the Models.Category_menuitem.ToList() because "No overload for method 'ToList' takes 1 arguments"
2)The Models.Category_menuitem does not contain a definition for ToList.
What do I do?
I think you should do it different. The model should contain the data you use in the view. So do your db requests in the model and give the model to the view to display the data in it. Don't do SQL requests in the view. You also should write classnames always in capital letters because of C# naming conventions.
If I understand it right you want to display a menubar or something like that with categories and each category has many menuitems?
Just create a model menuitems like this:
public class MenuItems {
public List<Category> Categories{get;set;}
}
and a model Category like this:
public class Category {
public string CategoryName {get;set;}
public List<MenuItem> MenuItems {get;set;}
}
Fill the models with data and give the MenuItems Model to the view. In the view you can do something like:
#foreach (var category in Model.Categories)
{
foreach (var menuItem in category.MenuItems)
{
}
}
I hope this helps ;)
To this part of your code:
var menu_items = context.MenuItems.SqlQuery("Select * FROM MenuItems where restaurant_id = #p0", sa).ToList();
I am not sure what you wanna do. You are querying the db for data which should be already in the model or am I wrong? But if you want to use EF you would write:
var items = context.Menuitems.Where(m => m.restaurant_id == id).ToList();
Related
I am very new to asp.net development. In my asp.net mvc project I have model "Employee" and I'm passing a list of "Employee" model to a RAZOR view and I'm trying to count different type of employees and show a summary.
my view is like this,
#{
int available = 0;
int onLeave = 0;
int away = 0;
int unAvailable = 0;
}
#foreach (var employee in Model){
<lable>#employee.Name</lable></br>
#if (#employee.Available){
#available=available+1;
}
#if (#employee.Unavailable){
#unAvailable=unAvailable;
}
#if (#employee.Away){
#away=away+1;
}
#if (#employee.Onleave){
#onLeave=onLeave+1;
}
}
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#available
<label>Unavailable:</label>#unAvailable
<label>Away:</label>#away
<label>On Leave:</label>#onLeave
</div>
but when I run the my project variables "available","unAvailable","away" and "onLeave" don't get updated.
I'm sure that list is not empty because employee names are displaying.
can some explain me what is happening here and correct way of doing this
You should be doing this outside the before passing to the view like I mentioned in my original comment. You can create a new object called a ViewModel to represent the data exactly like you want it on the page. So I created a simple example, I only used the 4 properties of Employee you are displaying in you CSHTML page. On your View where you said your MODEL is either a list, arrary or whatever of Employee change it to EmployeeViewModel. Then in your controller where you get your list of employees set them to the Employees property of the Employee ViewModel.
public class EmployeeViewModel
{
public IEnumerable<Employee> Employees { get; set; }
public int TotalAvailable { get { return Employees.Count(emp => emp.Available); } }
public int TotalUnavailable { get { return Employees.Count(emp => emp.Unavilable); } }
public int TotalAway { get { return Employees.Count(emp => emp.Away); } }
public int TotalOnLeave { get { return Employees.Count(emp => emp.OnLeave); } }
}
public class Employee
{
public bool Available { get; set; }
public bool Unavilable { get; set; }
public bool Away { get; set; }
public bool OnLeave { get; set; }
}
//In the controller do this.
public ActionResult Index() //use your controller Action Name here
{
var employeeViewModel = new EmployeeViewModel { Employees = /*Your list of empoyees you had as a Model before here*/}
return View(employeeViewModel)
}
Change your CSHTML code to something like this:
#foreach(var employee in Model.Employees)
{
<label> #employee.Name </label></br>
}
<div>
<!--additional summary is displayed here-->
<label> Available:</label> #Model.TotalAvailable
<label> Unavailable:</label> #Model.TotalUnavailable
<label> Away:</label> #Model.TotalAway
<label> On Leave:</label> #Model.TotalOnLeave
</div>
An easy and quick way is:
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#Model.Count(i => i.Available)<br>
<label>Unavailable:</label>do the same.
<label>Away:</label>do the same.
<label>On Leave:</label>do the same.
</div>
Make sure the model has already been "ToList()", or it might lead to mult-access of database.
Basically, I only use viewmodel when I need to pass more than 1 models to the view. Not worth in this case.
Make such calculations in View considered a BAD practice.
In your case better option will be create ViewModel with corresponding properties and then pass it to the model, previously calculating count for every type in controller using LINQ. Where you could reference your types like Model.available, Model.away and so on. Using ViewModel it is the best practice for MVC.
#Thorarins answer show you how to use LINQ in your code to calculate count for you types.
UPDATE:
You can use JS, but you should not, because it still not what supposed to happen in View. Work with data should not be handled in View. Don't be scared by ViewModels, they not that hard as it could seem. Please read this article which consider all ways to pass data to View, which has good example how create and pass ViewModel.
Mvc sample on how to do it:
you need a model class
public class EmployeeModel
{
public int Available {get; set;}
public int OnLeave {get; set;}
public int Away {get; set;}
public int UnAvailable {get; set;}
}
and a command:
public ActionResult Index()
{
var model = new EmployeeModel();
model.Available = employee.count(e=> e.available);
model.OnLeave = employee.count(e=> e.onLeave);
model.Away = employee.count(e=> e.away);
model.UnAvailable = employee.count(e=> e.unAvailable );
return View(model);
}
and a view
#model EmployeeModel
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#Model.Available
<label>Unavailable:</label>#Model.UnAvailable
<label>Away:</label>#Model.Away
<label>On Leave:</label>#Model.OnLeave
</div>
Here's the visual of what I'm trying to do.
So basically what happens here is that you choose a name from the select on the left and a team from the select on the right, then click Submit Assignment and it adds a record. (This information is for reference so you can understand the context. I don't need help with the database inserts or updates.)
This is going to be a PartialView with a ViewModel.
I need to know how to populate those two dropdowns with separate lists. I'm assuming those would be coming over in the ViewModel.
So in my main view, I have a call to the PartialView with RenderAction.
//The action //The controller
#{Html.RenderAction("TeamAssignment", "TeamAssignment");}
The controller that gets called
public class TeamAssignmentController : Controller
{
MyDatabaseEntities db = new MyDatabaseEntities();
[ChildActionOnly]
public ActionResult TeamAssignment()
{
//NEED A VIEW MODEL HERE TO PASS INTO THE PARTIALVIEW
return PartialView();
}
}
In the ViewModel I will need lists that populate the two drop downs.
The linq query on the left for Name would be this.
var nameList = (from p in db.Participant
where p.ParticipantType == "I"
select new {
p.ParticipantID,
p.IndividualName
}).ToList();
The linq query on the right for Team would be this.
var teamList = (from p in db.Participant
where p.ParticipantType == "T"
select new {
p.ParticipantID,
p.TeamName
}).ToList();
How can I pass that information into the PartialView and how do I populate the dropdowns with the ID for value and name for display text?
UPDATE
I belive this may be the ViewModel I need. Is this correct?
public class TeamAssignmentViewModel
{
//Need these ints for the updating and deleting
public int IndividualParticipantID { get; set; }
public int TeamParticipantID { get; set; }
public List<Participant> NameList { get; set; }
public List<Participant> TeamList { get; set; }
}
You need to create an instance of a viewmodel, populate it and pass it to your PartialView:
[ChildActionOnly]
public ActionResult TeamAssignment()
{
// Instantiate A VIEW MODEL HERE TO PASS INTO THE PARTIALVIEW
MyCustomModel model = new MyCustomModel();
model.nameList = (from p in db.Participant
where p.ParticipantType == "I"
select p).ToList();
model.teamList = (from p in db.Participant
where p.ParticipantType == "T"
select p).ToList();
return PartialView("TeamAssignment", model);
}
EDITED: removed use of dynamic class in linq statements
The markup for the Dropdowns might look something like:
#Html.DropDownListFor(model => model.IndividualParticipantID,
new SelectList(Model.NameList, "ParticipantID", "FirstName")
#Html.DropDownListFor(model => model.IndividualParticipantID,
new SelectList(Model.TeamList, "ParticipantID", "Team")
I'll start by admitting that I haven't read everything posted, but I can help with passing data to the PartialView to be used as a model.
In your View, you can build the partial like this:
#Html.Partial("_PartialViewName", currentItem,
new ViewDataDictionary {
{ "ExtraValue", Model.Count },
{ "SecondExtraValue", #ViewBag.ValueToPass });
Then in the PartialView, you can do this:
#model [Type of currentItem from above]
#{
// I'm using var here for shorthand, whereas I do strong typing and cast in my codebase.
var dataValue = ViewData["ExtraValue"];
var secondDataValue = ViewData["SecondExtraValue"];
}
Using this method you can pass in a model, as well as other values that may be needed for rendering.
Hope this helps. :)
I am in the habit of using nested loops in classic. Data from the first record set is passed to the second record set. How would I accomplish the same thing in MVC? As far as I can tell, I can only have one model passed to my view.
<%
rs.open "{Call usp_SalesOrder}",oConn
Do While (NOT rs.EOF)
%>
<div><% = rs("SalesOrderNumber")%></div>
<%
rs2.open "{Call usp_SalesOrderLines(" & rs("SOKey") & ")}",oConn
Do While (NOT rs.EOF)
%>
<div><% = rs2("SalesOrderLineNumber")%></div>
<%
rs2.MoveNext
Loop
rs2.close
%>
<%
rs.MoveNext
Loop
rs.close
%>
My suggestion would be to build a more robust model. It is true that you can only pass one model to your view, but your model can contain the results of multiple data sets, provided you have gathered those data sets in your controller and assigned them to the model.
I also suggest staying away from the ViewBag. It's an easy trap to fall into. Trust me when I say you'll regret it later.
For your example, maybe a model defined like this:
public class MyModel
{
public List<SalesOrder> SalesOrders = new List<SalesOrder>();
}
public class SalesOrder
{
public string SOKey = string.Empty;
public List<SalesOrderLine> SalesOrderLines = new List<SalesOrderLine>();
}
And the code to populate the sales orders in the controller:
public Action Index()
{
MyModel model = new MyModel();
model.SalesOrders.AddRange(CallUspSalesOrder());
foreach (SalesOrder salesOrder in model.SalesOrders)
{
salesOrder.SalesOrderLines.AddRange(CallUspSalesOrderLines(salesOrder.SOKey));
}
return View(model);
}
That way, you have access to all sales orders (and their sales order lines) within the view.
I would say that Nathan's post is a good start. Here is what I would do from beginning to end.
This is how I would do my model:
public class SalesOrderModel
{
public List<SalesOrderLines> SOLines = new List<SalesOrderLines>();
public List<SalesOrder> SOHeader = new List<SalesOrder>();
}
My Controller would then do this:
public ActionResult Index()
{
List<SalesOrder> SalesOrder = callSalesOrderUSP.ToList();
List<SalesOrderLines> SalesOrderLines = new List<SalesOrderLines>();
foreach (var thing in SalesOrder)
{
SalesOrderLines.AddRange(callSalesOrderLinesUSP(thing.SOKey).ToList());
}
SalesOrderModel salesOrderModel = new SalesOrderModel
{
SOHeader = SalesOrder,
SOLines = SalesOrderLines
};
return View(salesOrderModel);
}
Then in your view you can do this:
#foreach(var something in Model.SOHeader)
{
foreach (var thing in Model.SOLines.Where(i => i.SOKey == something.SOKey))
{
//display info here
}
}
You can use ViewBag to pass elements not relevant to your model. Also do not be afraid of creating your own ModelView objects that can work between your View and Controller. Your views should not be restricted to what your model has to offer.
Take a look at this for how you can implement a ViewModel in MVC.
And perhaps look at this to see how you can use ViewBag to pass values to your view, not relevant to your model.
HELP:
i would like to add a dropdownlist to my MVC3 application using code first and c#.
i have 2 table Student and University, i need to put a dynamic list of university in a Create view of Student.
how and where should be add methode to my controller.
some one help me please
thanks
I'm guessing you are getting down votes because you could have just googled this and easily found the answer. Anyways, here's a link to get you started.
http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists
The basic idea is you pass the drop down list as a property of the class that send to the view.
So something like this:
public Student
{
public List<University> Universities({//get list from database in getter
Then in the the view use something like
#Html.DropDownListFor(model => model.StudentsSchool, Model.Universities)
First create Entity class for your dropdown. It will return a list of value
public class KeyValueEntity
{
public string Description { get; set; }
public string Value { get; set; }
}
public class MyViewModel
{
public List<KeyValueEntity> Status { get; set; }
}
On your controller write the following code
[HttpGet]
public ActionResult Dropdown()
{
MyViewModel model = GetDefaultModel();
return View(model);
}
}
public MyViewModel GetDefaultModel()
{
var entity = new MyViewModel();
entity.Status = GetMyDropdownValues();
return entity;
}
private List<KeyValueEntity> GetMyDropdownValues()
{
return new List<KeyValueEntity>
{
new KeyValueEntity { Description = "Yes" , Value ="1" },
new KeyValueEntity { Description = "No" , Value ="0"}
};
}
Code for your cshtml page :
Now you need to bind your view with your model for this on top of your view you define your model class
#model MyViewModel
Following is the code for dropdown binding
#Html.LabelForModel("Status:")
#Html.DropDownListFor(m => m.Status, new SelectList(Model.Status, "Value", "Description"), "-- Please Select --")
I need to populate two listboxes with data from a database.
But I need to display two listboxes in one view, so I created a ListBoxModel class.
public class ListboxModel
{
public ListBox LB1 { get; set; }
public ListBox LB2 { get; set; }
}
And in my Controller:
public ActionResult IndexStudents(Docent docent, int lessonid, int classid)
{
var MyListBox = new ListboxModel
{
LB1 = new ListBox(docent.ReturnStudentsNormal(lessonid, classid),
LB2 = new ListBox(docent.ReturnStudentsNoClass(lessonid, classid)
};
return View(MyListBox);
}
But this code does not work, how can I bind the data to the listboxes?
So I'd like to use 2 models, one for each listbox... one with normal students and one with students who are not subscribed for lessons.
How could I do that?
And what code do I have to write in my view?
Something like:
<div class="editor-field">
<%: Html.ListBox("IndexStudentsNormal", Model.LB1) %>
<div class="editor-field">
<%: Html.ListBox("IndexStudentsNoClass", Model.LB2) %>
The listbox has to be a listbox with multiple colums so that it can contain the name, sirname, class, teacher of the student.
Student is an object, I'd like to display student.Name, student.Sirname, student.Class, and so on in that listbox.
So can I use an object in a ListBox, or do I have to convert everything to strings?
How can I do that?
Thanks in advance!
The model shouldn't contain a ListBox, it should just contain the lists of students. The trick is to keep the Model as simple as possible, it should really only be a bunch of property getters and setters. The view is responsible for binding a Model's properties to HTML elements.
Model:
public class StudentModel
{
public IList<string> NormalStudents {get;set;}
public IList<string> NoClassStudents {get;set;}
}
Controller:
public ActionResult IndexStudents(Docent docent, int lessonid, int classid)
{
var studentModel = new ListboxModel
{
NormalStudents = docent.ReturnStudentsNormal(lessonid, classid),
NoClassStudents = docent.ReturnStudentsNoClass(lessonid, classid)
};
return View(studentModel);
}
View:
<div class="editor-field">
<%: Html.ListBox("IndexStudentsNormal", Model.NormalStudents) %>
</div>
<div class="editor-field">
<%: Html.ListBox("IndexStudentsNoClass", Model.NoClassStudents) %>
</div>
Based on Jason's answer, the first line in your view should include:
<%# Inherits="System.Web.Mvc.ViewPage<StudentModel>" %>
This tells your view that "Model" is of type StudentModel. If there's other bits in this first line (Title, Language, MasterPageFile, etc), they're fine to stay there.
-- edit: add longish comments --
The thing to remember is that a SelectListItem has three required parts: Value, Text, and Selected. Value is the key, so something like StudentId or DocentId. Text is displayed in the list, so something like StudentName or DocentName. Selected indicates whether this item is selected in the list, typically false.
Right now it looks like you have methods that only return a list of the student names (Docent.ReturnStudentsNormal() and Docent.ReturnStudentsNoClass()). I would have these methods return a list of key-value pairs, key being StudentId and value being StudentName.
Then you can change your model class to be
public class StudentModel
{
List<SelectListItem> NormalStudents;
List<SelectListItem> StudentsNoClass;
}
and in your controller
public ActionResult IndexStudents(Docent docent, int lessonId, int classId)
{
var studentModel = new StudentModel();
var normalStudents = docent.ReturnStudentsNormal(lessonId, classId);
foreach (var student in normalStudents)
{
studentModel.NormalStudents.Add(new SelectListItem() {Value = student.Key, Text = student.Value});
}
var studentsNoClass = docent.ReturnStudentsNormal(lessonId, classId);
foreach (var student in studentsNoClass)
{
studentModel.StudentsNoClass.Add(new SelectListItem() {Value = student.Key, Text = student.Value});
}
return View(studentModel);
}
Now you'll be able to use these properties on your model directly for Html.ListBox().