I am trying to get started learning MVC. I built the MVC Music Store project that I found on the Microsoft site. http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-1.
I got it working pretty well but I ran into trouble when I tried to modified it. I want to put the data in a separate project. I used Linq to Entities for the data access.
Here is my class to access the data
public class clsUtilities
{
Utilities.MVCMusicStoreEntities db = new Utilities.MVCMusicStoreEntities();
public object GetAlbums(string GenreName)
{
var query = from tags in db.vieAlbumArtists
where tags.GenreName.Equals(GenreName)
select tags;
return query;
}
}
In my Controller my code is
public ActionResult Browse2(string genre)
{
// retrieve Genre and its associated albums from the database
var genreModel = mcloUtilities.GetAlbums(genre);
return View(genreModel);
}
I generate a cshtml file in my view
#model Utilities.vieAlbumArtist
#{
ViewBag.Title = "Browse2";
}
This all compiles ok but when I run it I get:
The model item passed into the dictionary is of type System.Data.Objects.ObjectQuery'1[Utilities.vieAlbumArtist], but this dictionary requires a model item of type Utilities.vieAlbumArtist.
Change
#model Utilities.vieAlbumArtist
to
#model IEnumerable<Utilities.vieAlbumArtist>
You are returning a list of vieAlbumArtist, not just a single instance.
You might also want to change
public object GetAlbums(string GenreName)
to
public IEnumerable<Utilities.vieAlbumArtist> GetAlbums(string GenreName)
Passing objects around is not the best idea.
This is your problem:
public object GetAlbums(string GenreName)
You're returning the data as an object. But the view expects to receive an item of type Utilities.vieAlbumArtist. Either change the GetAlbums() method to return the appropriate type, or make sure you cast it in the controller to the type the view is expecting.
I was able to solve this with the help of the hints you guys gave me.
From clsUtilies
public class clsUtilities
{
Utilities.MVCMusicStoreEntities db = new Utilities.MVCMusicStoreEntities();
public IEnumerable<Utilities.vieAlbumArtist> GetAlbums(string GenreName)
{
IEnumerable<vieAlbumArtist> query = from tags in db.vieAlbumArtists
where tags.GenreName.Equals(GenreName)
select tags;
foreach (var n in query)
{
}
return query;
}
From Controller
public ActionResult Browse2(string genre)
{
// retrieve Genre and its associated albums from the database
var genreModel = mcloUtilities.GetAlbums(genre);
return View(genreModel );
}
From Views
#model IEnumerable< Utilities.vieAlbumArtist>
#{
ViewBag.Title = "Browse Albums";
}
#foreach(var album in Model)
{
<ul>
<a href="#Url.Action("Details", new { id=album.AlbumId})">
<img alt="#album.Title" src="#album.AlbumArtUrl" />
<span>#album.Title ( #album.Name ) </span> </a>
</ul>
}
}
To display a list of albums try this:
<ul>
#foreach(var item in vieAlbumArtist)
{
<li>item.Name</li> //Not sure if you actually have a name property
}
</ul>
Related
Whenever i m passing data from Controller to View this error is showing
Server Error in '/' Application.
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType1`6[System.String,System.String,System.Nullable`1[System.DateTime],System.Nullable`1[System.DateTime],System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IList`1[CaliberCoaching.Models.CareerInformation]'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType1`6[System.String,System.String,System.Nullable`1[System.DateTime],System.Nullable`1[System.DateTime],System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IList`1[CaliberCoaching.Models.CareerInformation]'.
This is My Controller Code
public ActionResult JobList()
{
CaliberCoachingContext objCaliberCoachingContext = new CaliberCoachingContext();
var lstCareerInformation = (from job in objCaliberCoachingContext.CareerInformations
select new { job.NameOfPost, job.PostName, job.StartDate, job.LastDate, job.Eligibility, job.NoOfVacancies }).ToList();
return View(lstCareerInformation);
}
and here is my view
#model IEnumerable<CaliberCoaching.Models.CareerInformation>
#{
ViewBag.Title = "JobList";
Layout = "~/Views/Shared/_CommonLayout.cshtml";
}
#foreach (var item in Model)
{
<div class="single-item-wrapper">
<div class="courses-content-wrapper">
<h3 class="title-default-left-bold">#item.NameOfPost</h3>
</div>
</div>
}
Please Give me the solution for this Problem.
The exception is self explanatory! Your razor view is strongly typed to a collection of CareerInformation objects, but from your action method, you are passing a different type to the view!
In your action method, the variable lstCareerInformation is not a collection of CareerInformation objects, but a collection of anonymous objects. This is happening because your LINQ expression is doing a projection to an annonymous object.
select new { job.NameOfPost, job.PostName, job.StartDate,
job.LastDate, job.Eligibility, job.NoOfVacancies }
select new will create an anonymous object
To fix the error, you should return a collection of CareerInformation objects. Just remove the projection part from your LINQ expression.
public ActionResult JobList()
{
var db = new CaliberCoachingContext();
var careerInformationList = db.CareerInformations.ToList();
return View(careerInformationList);
}
EDIT : As per the comment
i have used anonymous object because i wants to select particular
columns instead of all the columns from CareerInformation properties.
Then you should be using a view model. Create a viewmodel class with properties needed in your view.
public class JobVm
{
public string PostName { set;get;}
public Eligibility { set;get;}
public DateTime StartDate { set;get;}
// Add other properties needed by the view
}
Now in your action method, project create view model objects from your entity object collection using the Select method.
public ActionResult JobList()
{
var db = new CaliberCoachingContext();
var careerInformationList = db.CareerInformations
.Select(a=> new JobVm { PostName = a.PostName,
StartDate = a.StartDate,
Eligibility = a.Eligibility })
.ToList();
return View(careerInformationList);
}
Here careerInformationList is a list of JobVm objects and that is what we are passing to the View. So make sure your view is strongly typed to a collection of the JobVm objects.
#model List<JobVm>
<h2>Jobs</h2>
#foreach(var job in Model)
{
<div>#job.PostName</div>
<p>#job.Eligibility</p>
}
I am currently developing an asp.NET MVC web application as a front end to a database. I have a MySQL database, one of the tables is contact information for employees. I have added a column of 'isOnSite' of datatype TINYINT(1).
I have updated the data model in my application, and added a checkbox control for this in one of my view. This works fine, I edit a contact, check the box to say that they are currently contracted to this particular site, and a '1' is populated in the 'isOnSite' column for that particular record, great!
One of the views is a Dashboard. In this view (using a partial view) I would like to generate a list of the contacts in the table that have the value of 'isOnSite = true'
I am struggling to do this. I should mention that I am pretty new to all of this.
Any help would be greatly appreciated.
Thank you in advance!
-- EDIT --
With the help of #Bunnynut and also my Father-in-Law We managed to solve this,
in large part to the code examples by #Bunnynut.
CONTROLLER ACTION
public ViewResult Index()
{
var tblcontacts = from m in db.tblcontacts.Where(x => x.isOnSite)
select m;
return View(tblcontacts.OrderBy(x => x.LastName).ToList());
}
PARTIAL VIEW
#model IEnumerable<ResourceBase.Models.tblcontact>
#{
ViewBag.Title = "OnSite";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>OnSite</h2>
<div class="container-fluid-viewport jumbotron col-xs-offset-4">
#foreach (var x in Model)
{
#x.FullName <br />
}
</div>
And the Main view just renders the partial view.
Thanks again for your help #Bunnynut
To begin with the Index View uses a model of type ResourceBase.Models.tlbcontact which is it seems a single tblcontcat.
But you are try to pass a List to your partial view so that is not possible.
You Index View should consume a model of which it pass parts of it to your partial views.
IndexViewModel:
public class IndexViewModel
{
public string Title { get; set; }
public List<ResourceBase.Models.tblcontact> Employees { get; set; }
}
Index Action:
public ActionResult Index()
{
var model =
new IndexViewModel
{
Title = "PeopleBase Dashboard",
Employees = GetEmployees()
};
return View(model);
}
Index View:
#model IndexViewModel
<div class="container-fluid-viewport col-md-offset-3 col-md-9">
<h2>#Model.Title</h2>
<div class="partialViewWrapper jumbotron">#{Html.RenderPartial("_peopleBaseDashView", Model.Employees.Where(x => x.isOnSite).ToList());}
</div>
</div>
Your partial View looks ok to me
Use the following SELECT statement
SELECT * FROM yourTable WHERE isOnSite = 1
to fill a property of your ViewModel, which you can then display in your view.
You can easily pass the list of employees directly to your partial view as long as you tell your partial view the model passed is of that type.
So in the master view containing the code that call the partial view you can do this:
#{Html.RenderPartial("NAME_PARTIAL_VIEW", employees.Where(x => x.isOnSite).ToList());}
And in you partial view:
#model List<Employee>
#foreach(var employee in Model)
{
#employee.Name
}
This is how I have made a previous post as you can see here.
must retrieve the list from the database
I have tried to make my foreach which have been previously described. but it causes problems for not running my foreach in through while making the mistake on it.
Index.cshtml
#foreach (var u in Model)
{
<div class="col-md-6 col-sm-6">
<div class="plan">
<h3>#u.Name<span>$#u.Price</span></h3>
<p>#u.Text</p>
</div>
</div>
}
and undervisningController.cs
// GET: Undervisning
public ActionResult Index()
{
DatabaseClasseDataContext db = new DatabaseClasseDataContext();
var model = db.Packages.ToList();
return View(model);
}
And the top on index.cshtml have i:
#model MentorOrdblind_MVC.Models.Undervisning.Undervisning
Model Undervisning.cs
public class Undervisning
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Hours { get; set; }
public string Text { get; set; }
}
You are passing your view a List<T> but your model is not a type of IEnumerable. So your view is only expecting a single object of the type Undervisning and not a collection.
Use this:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>
Change your model delcaration to:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>
At this moment your model is a single class, not a list of objects
Always keep in mind what is being passed from controller action to view. If you pass only model from the action then use the model reference in the respective view of the action. If you pass List then use IEnumerable model reference in the view.
If you pass list from action then in the view use:
#model IEnumerable<your model> in the top as reference
If you pass model without a list then use:
#model your model
In your case you are passing list so use IEnumerable of your desired model class.
Thanks
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.
I am new to mvc and cannot figure out how to pass a single column of data to the view.
I have connected my db with ado.net entity model to models.
Then in my controller I have :
public class HomeController : Controller
{
shdesignEntities2 _db;
public ActionResult Index()
{
_db = new shdesignEntities2();
ViewData.Model = _db.tblKategoris.ToList();
return View();
}
}
In the view :
#foreach(var m in ViewData.Model)
{
<p>Kategori Ad :</p><p> #m.kategori_ad </p>
}
When I do like this , I pass the whole table data to the view where I only need a single column of information.
How can I only pass data from the column kategori_ad ?
Use Select:
ViewData.Model = _db.tblKategoris.Select(x => x.kategori_ad).ToList();
You can use LINQ to find the object that you want and then pass it to the view, do something like this:
public ActionResult Index()
{
_db = new shdesignEntities2();
ViewData.Model = _db.tblKategoris.Select(x => x.kategori_ad).ToList();
return View();
}
That way ViewData.Model only has the object that matches the linq query.
Here you can find more about Linq to retrieve data from a collection in C#: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
In Controller
ViewData["Rows"] = (from c in _db.tblKategoris
select c.kategori_ad).ToList();
View
#foreach(var m in (List<string>)ViewData["Rows"])
{
<p>Kategori Ad :</p><p> #m </p>
}
You may look at ViewModels. Also by this way you can use smaller part of data exposed.
For example
public class KategoriViewModel
{
public IEnumerable<Kategori> Kategoriler { get; set; }
}
Then you should add a controller action like
public ActionResult Something()
{
var model = new KategoriViewModel;
model.Kategoriler = your query..;
return View(model);
}
In view
#model KategoriViewModel
#foreach(var m in ViewData.Model)
{
<p>Kategori Ad :</p><p> #m.kategori_ad </p>
}