I'm creating ViewModels in my MVC application. We are using automapper for domain model to view model conversion. My question is I keep getting a circular reference error when doing ajax stuff in MVC (seems like it's the JavaScriptSerializer that's causing problems), so instead of getting back a list of Projects, I just need the count (because that's all my view model needs). Here is a sample of the hierarchy. Thanks in advance for any advice!
public class ProjectViewModel
{
public int ProjectID { get; set; }
[Required]
[UIHint("Project Name")]
public string Name { get; set; }
public ICollection<ProjectGroupViewModel> ProjectGroups { get; set; }
}
public class ProjectGroupViewModel
{
public int ProjectGroupID { get; set; }
[Required]
public string Name { get; set; }
//THIS is what I Want to have as int ProjectCount
public ICollection<ProjectViewModel> Projects { get; set; }
}
public class ProjectGroupViewModel
{
public int ProjectGroupID { get; set; }
[Required]
public string Name { get; set; }
//THIS is what I Want to have as int ProjectCount
public int ProjectsCount { get; set; }
}
AutoMapper.Mapper.CreateMap<ProjectGroup, ProjectGroupViewModel>()
.ForMember(x => x.ProjectsCount, o => o.MapFrom(x => x.Projects.Count()))
Related
I have looking on SO but I didn't find a solution and I'm totally lost the correct way to fix this.
What's happening?
I'm getting error CS0411 in a view: the type arguments for method cannot be inferred from the usage mvc
I'm using a Tuple in that view to use 2 models.
var model = new Tuple<IList<TimeTableInsertModel>, List<Ticket>>(ttc.getTimeTableDetails(id), ticket);
#model Tuple<IList<TimeTableInsertModel>, List<Ticket>>
And I want to use the field TicketQuantity.
#Html.HiddenFor(item.TicketQuantity)
But that's give the error. I can use the property in the view without any #Html functions.
The views:
public class TimeTableInsertModel
{
[Key]
public int TimeTableId { get; set; }
public int MovieId { get; set; }
public int RoomId { get; set; }
public int SeatsAvaible { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public virtual Movie Movie { get; set; }
public virtual ICollection<Reservation> Reservations { get; set; }
public virtual Room Room { get; set; }
public int TicketQuantity { get; set; }
}
public partial class Ticket
{
public Ticket()
{
ReservationTickets = new HashSet<ReservationTicket>();
}
public int TicketId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public virtual ICollection<ReservationTicket> ReservationTickets { get; set; }
}
I'm assuming for the moment you're looping through an IEnumerable like this:
#foreach (var item in Model.Item1)
{
...
Html.HiddenFor(item.TicketQuantity);
...
}
The HiddenFor method takes a delegate as an argument, so instead of this:
#Html.HiddenFor(item.TicketQuantity)
you need to do something like this:
#Html.HiddenFor( m = > item.TicketQuantity)
I have a model that looks like this
public abstract class Item
{
public int ItemId { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public DateTime PurchaseDate { get; set; }
public ICollection<String> Pictures { get; set; }
public Int32 MinimumPrice { get; set; }
public DateTime Deadline { get; set; }
public Boolean VisibleBids { get; set; }
public Boolean Handled { get; set; }
public DateTime PlacementDate { get; set; }
public ApplicationUser User { get; set; }
}
In my controller I do
db.Items.ToList()
This leaves the Pictures field for all fetched objects null because its how the entity framework works. What is a good solution to fetch them in one query?
I hope you already done with Navigation properties between your tables, Now you just need to make your collection virtual and use the concept of eager loading when you need data from both the tables
public virtual ICollection<String> Pictures { get; set; }
and use include in linq like
db.Items.Include("Pictures").ToList()
So here by making virtual navigation you are saying that only take the data of related entity when you needed and whenever you need the data use the Include for eager loading.
For setting navigation properties please have a look on the code.
Suppose the scenario where we have a Post and on this we have multiple comments like
class Posts
{
public int PostsId { get; set; }
public string PostsDescription { get; set; }
public virtual ICollection<Comments> Comments { get; set; }
}
class Comments
{
public int CommentsId { get; set; }
public string CommentsDescription { get; set; }
public int PostsId { get; set; }
public virtual Posts Posts { get; set; }
}
I have a model and i want to put an extra field which can be populated form the same model. IE: Categories and and sub-categories.
In my example, visitor can add an filetype but if file type is under an another file type, he can choose,
But i cant work it out. Below you can see my model.
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
public virtual HrFileType HrFileType2 { get; set; }
}
You just need to add a ForeignKeyAttribute like below:
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
[ForeignKey("HrFileTypeId")]
public virtual HrFileType HrFileType2 { get; set; }
}
You can also use fluent API to achieve this:
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
public virtual HrFileType HrFileType2 { get; set; }
}
public class YourDbContext : DbContext
{
public DbSet<HrFileType> HrFileTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//
modelBuilder.Entity<HrFileType>()
.HasOptional(c => c.HrFileType2)
.WithMany()
.HasForeignKey(c => c.HrFileTypeId);
}
}
Have you tried listing the other file types?
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public List<HrFileType> RelatedTypes { get; set; }
}
then using Entity Frameworks fluent API in the DbContext, try explicitly declaring a many to many map.
modelbuilder.Entity<HrFileType>().HasMany(x => x.RelatedTypes).WithMany();
I'd be very interested to see if this works. It's the only logical solution I can think of without having some kind of parent class.
I have the following entity model:
public class Project
{
[Key]
public int ProjectID { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string Category { get; set; }
public string Client { get; set; }
public int Year { get; set; }
// more attributes here...
}
I would like to prepare a view model (specific for my view). Here is the view model:
public class ProjectListViewModel
{
public IEnumerable<ProjectInfos> ProjectList { get; set; }
public PagingInfo Paging { get; set; }
public class ProjectInfos
{
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string Category { get; set; }
public string Client { get; set; }
public int Year { get; set; }
}
public class PagingInfo
{
public int TotalItems { get; set; }
public int ItemsPerPage { get; set; }
public int CurrentPage { get; set; }
public int TotalPages { get; set; }
}
}
In my controller, I would like to prepare the view model by filling it with 2 different objects:
List of projects
Paging information
Here is my controller:
public ViewResult List(string category, int page = 1)
{
IEnumerable<Project> projectList = m_Business.GetProjects(category, page, 10);
PagingInfo pagingInfo = m_Business.GetPagingInfo(category, page, 10);
// Here I need to map !!
ProjectListViewModel viewModel = .....
return View(viewModel);
}
So how can I proceed in my controller? I know we can use automapper to map from one object to another but here I need to map from two objects into a single one.
Thanks.
You can extend AutoMapper to map multiple objects.
Here is a blog which provides some sample cope.
Then you can use code like this:
var personViewModel = EntityMapper.Map<PersonViewModel>(person, address, comment);
I am using EF4 CTP5. Here are my POCOs:
public class Address
{
public int Id { get; set; }
public string Name { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public List<Address> Addresses { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public decimal Total { get; set; }
public Address ShippingAddress { get; set; }
public Address BillingAddress { get; set; }
}
Is there a way to get Address to be a ComplexType for the Order class? After playing around with this, I'm guessing not, but maybe there's a way I haven't seen.
EDIT: In response to Shawn below, I gave it my best shot:
//modelBuilder.Entity<Order>().Ignore(o => o.BillingAddress);
//modelBuilder.Entity<Order>().Ignore(o => o.ShippingAddress);
modelBuilder.Entity<Order>()
.Property(o => o.BillingAddress.City).HasColumnName("BillingCity");
Fails at runtime with error "The configured property 'BillingAddress' is not a declared property on the entity 'Order'." Trying to use Ignore() doesn't work. Next, the Hanselman article is CTP4, but the CTP5 equivalent is:
modelBuilder.Entity<Order>().Map(mapconfig =>
{
mapconfig.Properties(o => new {
o.Id
, o.Total
, o.BillingAddress.City
});
mapconfig.ToTable("Orders");
});
Fails with error "Property 'BillingAddress.City' of type 'Order' cannot be included in its mapping."
I give up. Maybe the final release will have something like this. Or maybe I need to switch to NHibernate =)
All you need to do is to place ComplexTypeAttribute on Address class:
[ComplexType]
public class Address
{
public int Id { get; set; }
public string Name { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
Alternatively, you can achieve this by fluent API:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ComplexType<Address>();
}
But you cannot have Address type as to be both an Entity and a Complex Type, it's one way or another.
Take a look at this blog post where I discuss this at length:
Associations in EF Code First CTP5: Part 1 – Complex Types
If you want Address to be in the same table as Order, you're going to have to tell EF that in the DbContext OnModelCreating override.
Take a look here: http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspx