Can't return a view with include() - asp.net-mvc

ASP.net MVC3 Razor EF
When I do this it works:
public ViewResult Index()
{
return View(db.Songs.Include("Artist").ToList());
}
But this doesn't:
public ViewResult Index()
{
return View(db.Artists.Include("Song").ToList());
}
I get this error:
A specified Include path is not valid. The EntityType 'MVCProject.Models.Artist' does not declare a navigation property with the name 'Song'.
Any idea why? if you need more info/code please mention which. but please let me know where something like that can happen, and how it can be solved. it's driving me crazy.
Thanks.
Artists Class:
public class Artist
{
public int ArtistID{ get; set; }
public string Name { get; set; }
public IQueryable<Song> Songs{ get; set; }
}

Replace public IQueryable<Song> Songs{ get; set; } with public virtual ICollection<Song> Songs{ get; set; }
public class Artist
{
public int ArtistID{ get; set; }
public string Name { get; set; }
public virtual ICollection<Song> Songs{ get; set; }
}
Then
return View(db.Artists.Include("Songs").ToList());

You probably have Songs (plural) as navigational property for Artist class. So, return View(db.Artists.Include("Songs").ToList()); should work. If ot - you need to show Model class for Artist

Related

Viewmodel set up Aspt.net MVC 6

I'm having trouble understanding how to implement a ViewModel in Asp.net MVC, I have the following tables:
Form
ID, Data
Report
ID, FormID, Owner, Category, Status, SubmissionDate
ReportValues
ID, ReportID, Title, Value
I'm looking for a way to display and edit Report and ReportValues in the one ViewModel where ReportValues.ReportID = Report.ID
ReportValues will have multiple entries that relate to a Report.
I have had a look at similiar questions on here and tried following a tutorial ( http://techfunda.com/howto/262/list-data-using-viewmodel ) and coming up empty handed.
If you need any more information let me know and thanks in advance for any replies!
Your View Model is nothing more than a class. You can solve this many ways, but here's an example.
Create your 3 classes like you normally would.
public class Form
{
public int Id { get; set; }
public string Data { get; set; }
}
public class ReportValues
{
public int Id { get; set; }
public int ReportId { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
public class Report
{
public int Id { get; set; }
public int FormId { get; set; }
public string Owner { get; set; }
public string Category { get; set; }
public string Status { get; set; }
public DateTime SubmissionDate { get; set; }
}
Then, create your ViewModel class to include the three above classes like this.
public class ReportViewModel
{
public Form Form { get; set; }
public ReportValues ReportValues { get; set; }
public Report Report { get; set; }
}
In your view you can access your three classes and their properties as you would in your controller. Model.Form.Id
Depending on your data types, ReportValues will likely be a property of Report, but that's entirely up to your data structure. You will need to populate the classes using whatever method you want (Entity Framework, ADO, etc.) before you can pass them to your view and use them.

MVC Include path not valid error

Controller
public ActionResult Index(int? id)
{
var userEmail = User.Identity.Name;
var model = db.Staffs.Where(i => i.Email == userEmail).Include("Histories").Include("CurrentApplications").FirstOrDefault();
return View(model);
}
I got the following error for the line var model = db.Staffs.Where(i => i.Email == userEmail).Include("Histories").Include("CurrentApplications").FirstOrDefault(); but i don't know why I got it.
Error
A specified Include path is not valid. The EntityType
'StaffPortalDBModel.Staff' does not declare a navigation property with
the name 'Histories'.
Staff class
public partial class Staff
{
public int StaffID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public Nullable<decimal> AllocatedLeave { get; set; }
public Nullable<int> BalanceLeave { get; set; }
public virtual IEnumerable<History> Histories { get; set; }
public virtual IEnumerable<CurrentApplication> CurrentApplications { get; set; }
}
I believe you may need to use ICollection and not IEnumerable when defining Navigation properties. This may be the issue.
I'd also recommend (assuming your version of Entity Framework is high enough that it is supported) to use strongly typed Includes so that if you change your property in Staff.cs you'll get a compile time error.
ie: .Include(s => s.Histories)

Join two model to present in a view in MVC

I want to join two below model class with entity framework in controller for present factor in accounting system in a view
<pre>
namespace AccountingSystem.Models
{
public class BuyFactor
{
public int BuyFactorId { get; set; }
public DateTime CreateDate { get; set; }
public string Seller { get; set; }
public string Creator { get; set; }
public decimal SumAllPrice { get; set; }
public ICollection<BuyFactorDetail> BuyFactorDetails { get; set; }
}
}
namespace AccountingSystem.Models
{
public class BuyFactorDetail
{
public int BuyFactorDetailId { get; set; }
public int Number { get; set; }
public string Description { get; set; }
public decimal SumPrice { get; set; }
public int BuyFactorId { get; set; }
public virtual BuyFactor BuyFactor { get; set; }
public virtual Commodity Commodity { get; set; }
}
}
</pre>
Create a new Model
public class JointModel
{
public BuyFactor BuyFactor {get; set;}
public BuyFactorDetail BuyFactorDetail {get; set;}
}
Just create another model then calls the other model in there
public class ParentModel
{
public BuyFactor BuyFactor {get; set;}
public BuyFactorDetail BuyFactorDetail {get; set;}
}
So when you will call it in view
#model IEnumerable<AccountingSystem.Models.ParentModel>
#Html.DisplayNameFor(model => model.BuyFactor.Creator)
Best way define Model as a Property in Main Model
For example
public class BuyFactor
{
public int BuyFactorId { get; set; }
public DateTime CreateDate { get; set; }
public string Seller { get; set; }
public string Creator { get; set; }
public decimal SumAllPrice { get; set; }
public ICollection<BuyFactorDetail> BuyFactorDetails { get; set; }
public BuyFactorDetail BuyFactorEntity {get;set;}
}
Assign value in BuyFactorEntity and use as Model.BuyFactorEntity.BuyFactorDetailId
Use a Linq join query like
var query = (from b in context.BuyFactors
join d in context.BuyFactorDetail
on
..
select new
{
BuyFactorId = b.BuyFactorId,
....
BuyFactorDetailId = d.BuyFactorDetailId,
...
..
}));
Your BuyFactor already contains the BuyFactorDetail collection. You sure the entities are 1:N relationship with each other?
You can use the BuyFactor as model and could use the BuyFactorDetails propertu of the BuyFactor entity.
Use ViewBag in controller to assign respective objects for both.
ViewBag.BuyFactor= BuyFactor;
ViewBab.BuyFactorDetail = BuyFactorDetail;
To use it in view you will have to typecast them back.

asp.net MVC 4 EntityType: EntitySet has no keys defined

I am a MVC newbie so go easy on me please.
I am getting two errors when I try to add a migration. They are as follows:
EntityType 'Icon' has no key defined. Define the key for this EntityType.
EntityType: EntitySet 'Icons' is based on type 'Icon' that has no keys defined.
I am including the Icon inside another model, like so:
public class Icon
{
public string IconName { get; set; }
public string IconColor { get; set; }
public int BackgroundXPos { get; set; }
public int BackgroundYPos { get; set; }
public string IconColorHover { get; set; }
public int BackgroundHoverXPos { get; set; }
public int BackgroundHoverYPos { get; set; }
}
public class GalleryThumbnail : CSSBoxModel
{
[DisplayName("Thumbnail Image Outline Color")]
public string ThumbnailImageOutlineColor { get; set; }
[DisplayName("Thumbnail Menu Font")]
public CSSFont ThumbnailMenuFont { get; set; }
[DisplayName("Thumbnail Icon Color")]
public Icon ThumbnailIconColor { get; set; }
}
How is this Address class below any different which is working:
public class Address
{
public String Adress1 { get; set; }
public String Adress2 { get; set; }
public String Adress3 { get; set; }
public String City { get; set; }
public String County { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Country { get; set; }
}
[Table("UserProfile")] //Could be PP empolyee, Subscriber or Subscriber's customer
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public bool? Gender { get; set; }
public Address Address { get; set; } //billing address
public Address ShipAddress { get; set; }
}
I did not add a key in either my Icon or Address class because I have no intention of storing specific data in my DB. They are merely to be used inside other classes. So wy is one neededing an ID and the other is not?
I have not created public DbSet Icons { get; set; } in my DB Context either.
Also can you tell me what it is called when you use a class inside another ( or instance of class inside a class as in these examples ) ?
Much appreciated!
Since the address entity has no key defined it the Entity Framework assumes it's a complex property, and your UserProfile table will be rendered with columns named Addres_Address1, Address_Address2, Address_Address3, Address_City, and so on...
Even though you haven't declared an EntitySetIcons DbSet on your context class, it's still being added implicitly because one of your other classes somewhere has an ICollection or IEnumerable property defined.
More info on Code Conventions here:
http://msdn.microsoft.com/en-us/data/jj679962.aspx
So, either decorate the collections as NotMapped like #Kamyar said or simply remove the references from any class already declared as a DbSet.
you can use [NotMapped] attribute in System.ComponentModel.DataAnnotations.Schema namespace in EntityFramework.dll:
using System.ComponentModel.DataAnnotations.Schema;
...
[NotMapped]
public Address Address { get; set; } //billing address
[NotMapped]
public Address ShipAddress { get; set; }
Regarding the naming, AFAIK these are called public properties as well.

How to correctly use a viewmodel

I am new to ASP.net MVC. I am trying to create a viewmodel to display a join of data. Here is some example code:
public class Person
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Relative> Relatives { get; set; }
}
public class Relative
{
[Key]
public int ID {get; set; }
public Person Person { get; set; }
public RelationType RelationType { get; set; }
}
public class RelationType
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
}
public class PersonViewModel
{
public string Name { get; set; }
public ICollection<string> RelativeNames { get; set; }
public ICollection<string> RelativeTypes { get; set; }
}
public class PersonContext : DbContext
{
public DbSet<PersonViewModel> people { get; set; }
}
When I try to create my controller through Visual Studio, I get the following error:
Unable to retrieve metadata for PersonViewModel. One or more validations errors were detected during generation:
EntityType 'PersonViewModel' has no key defined. Define the key for this EntityType.
The error is self explanatory. You need to add an Id field to the PersonViewModel which will have to be decorated with [Key] as you have rightly done in the classes above.
View Models are convenient classes for passing data between the controller and the view. The reason you are getting this exception is that because you are passing PersonViewModel class into your dbSet. You cannot do this unless PersonViewModel class has a corresponding table. In that case PersonViewModel should not be a view model but should be a entity,a model class to represent your table.
By Looking at your code I am guessing that you have tables for Person and Relative
in your database hence you shoud do the following
public class PersonContext : DbContext
{
public DbSet<Person> Person { get; set; }
public DbSet<Relative> Relative { get; set; }
}
and populate PersonViewModel through Person and Relative properties of your DbContext classes. This could be done inside the controller or in a repository class if you have one.

Resources