Automapper mapping issue - asp.net-mvc

I need to map a model to a viewmodel using AutoMapper.
Model:
[Table("News")]
public class News
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public DateTime DatePostedOn { get; set; }
public int Position { get; set; }
public Category Category { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
}
[Table("Pictures")]
public class Picture
{
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Filename { get; set; }
public int Type { get; set; }
public virtual ICollection<News> News { get; set; }
}
Viewmodel:
public class HomeViewModels
{
public IList<HomeMainNews> MainNews { get; private set; }
}
public class HomeMainNews
{
public int Id { get; set; }
public string Title { get; set; }
public string Date { get; set; }
public string PictureURL { get; set; }
}
Mapping:
Mapper.CreateMap<News, HomeMainNews>();
How can I map a News that have a set of Pictures, to a viewmodel with only one picture according to a certain condition "Type = 2"
Current solution:
vm.MainNews = db.News
.Select(n => new HomeMainNews {
Id = n.Id,
Date = n.DatePostedOn.ToString(),
Title = n.Title,
PictureURL = n.Pictures.Where(p => p.Type == 1).Select(p => p.Filename).FirstOrDefault().ToString()
}).ToList();
Automapper solution:
vm.MainNews = db.News.Project().To<HomeMainNews>().ToList();

Try this
Mapper.CreateMap<News, HomeMainNews>()
.ForMember(mainNew => mainNew.Date, opt => opt.MapFrom(news => news.DatePostedOn))
.ForMember(mainNew => mainNew.PictureURL, opt => opt.MapFrom(news => news.Pictures.First(pic => pic.Type == 2).Filename));

Related

AutoMapper Many to Many relationship

I'm not sure where I'm going wrong here. I want to map my classes so that there aren't extra levels in the returned values.
Models (DTOs):
public class FilmViewModel
{
public FilmViewModel() { }
public int Id { get; set; }
[Required(ErrorMessage = "Naziv filma je obavezno polje.")]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$", ErrorMessage = "Godina mora biti u YYYY formatu.")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public int Trajanje { get; set; }
public bool IsActive { get; set; }
public List<Licnost> Licnosti { get; set; }
}
public class LicnostViewModel
{
public LicnostViewModel() { }
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<Film> Filmovi { get; set; }
}
Entities:
public class Film
{
[Key]
public int Id { get; set; }
[Required]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public bool IsActive { get; set; }
public int Trajanje { get; set; }
public List<FilmLicnost> Licnosti { get; set; }
}
public class Licnost
{
[Key]
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<FilmLicnost> Filmovi { get; set; }
}
public class FilmLicnost
{
[Key]
public int Id { get; set; }
[ForeignKey(nameof(Licnost))]
public int LicnostId { get; set; }
public Licnost Licnost { get; set; }
[ForeignKey(nameof(Film))]
public int FilmId { get; set; }
public Film Film { get; set; }
}
Basically Swagger already shows me what I'm returning, but I want to avoid unnecessary nesting. It's marked in the image:
I want to say that I've been looking all over SO, AutoMapper documentation etc. No answer/example finds me the solution I need. I'm either missing a Model(DTO) somewhere or there is something major wrong with my logic.
Some example links that I tried are this and this
Also here are some links I tried to get information from: link1, link2
This is what I've tried so far:
CreateMap<FilmLicnost, LicnostViewModel>()
.ForMember(dest => dest.Filmovi, dest => dest.MapFrom(x => x.Film))
.AfterMap((source, destination) =>
{
if (destination?.Filmovi == null) return;
foreach (var temp in destination.Filmovi)
{
temp.Id = source.Film.Id;
temp.IsActive = source.Film.IsActive;
temp.Jezik = source.Film.Jezik;
temp.Naziv = source.Film.Naziv;
temp.Opis = source.Film.Opis;
temp.Godina = source.Film.Godina;
temp.Trajanje = source.Film.Trajanje;
temp.UrlFotografije = source.Film.UrlFotografije;
}
});
CreateMap<FilmLicnost, FilmViewModel>()
.ForMember(dest => dest.Licnosti, dest => dest.MapFrom(x => x.Licnost))
.AfterMap((source, destination) =>
{
if (destination?.Licnosti == null) return;
foreach (var temp in destination?.Licnosti)
{
temp.Id = source.Licnost.Id;
temp.ImePrezime = source.Licnost.ImePrezime;
temp.IsGlumac = source.Licnost.IsGlumac;
temp.IsRedatelj = source.Licnost.IsRedatelj;
}
});
Also this:
CreateMap<FilmLicnost, Film>()
.ForMember(dest => dest.Licnosti, dest => dest.Ignore());
CreateMap<FilmLicnost, Licnost>()
.ForMember(dest => dest.Filmovi, dest => dest.Ignore());
Note I have already defined the mapping for Entities:
CreateMap<Film, FilmViewModel>();
CreateMap<FilmViewModel, Film>();
CreateMap<Licnost, LicnostViewModel>();
CreateMap<LicnostViewModel, Licnost>();

ASP.NET Display more than one entry/row

I'm quite new to ASP.NET MVC. I am creating a holiday tracking app, and I'm attempting to create a details page for each Employee. I want this page to display a table showing a table of all the holiday request that employee has taken. I've gotten it to work but it only shows only one row.
Here's my models
public partial class Employee
{
public int EmployeeID { get; set; }
public string FullName { get; set; }
public string EmailID { get; set; }
public string Password { get; set; }
public System.DateTime StartDate { get; set; }
public int RoleID { get; set; }
public int ShiftID { get; set; }
public int AreaID { get; set; }
public int DisciplineID { get; set; }
public int SiteID { get; set; }
public int ALCategory { get; set; }
public Nullable<int> HoursTaken { get; set; }
public Nullable<int> AwardedLeave { get; set; }
public Nullable<int> TotalHoursThisYear { get; set; }
public int HoursCarriedForward { get; set; }
public Nullable<int> EntitlementRemainingThisYear { get; set; }
public string Comments { get; set;}
}
Employee Model:
public class EmployeeViewModel
{
public Employee Employee { get; set; }
public HolidayRequestForm HolidayRequestForm { get; set; }
}
Holiday Request Form Model:
public partial class HolidayRequestForm
{
public int RequestID { get; set; }
public int EmployeeID { get; set; }
public System.DateTime StartDate { get; set; }
public System.DateTime FinishDate { get; set; }
public int HoursTaken { get; set; }
public string Comments { get; set; }
public int YearCreated { get; set; }
public int MonthCreated { get; set; }
public Nullable<int> DayCreated { get; set; }
public Nullable<int> YearOfHoliday { get; set; }
public virtual Employee Employee { get; set; }
}
Controller Action:
public ActionResult Details(int? id)
{
Employee employee = db.Employees.FirstOrDefault(emp => emp.EmployeeID == id);
HolidayRequestForm holidayRequestForm db.HolidayRequestForms.FirstOrDefault(emp => emp.EmployeeID == id);
EmployeeViewModel employeeViewModel = new EmployeeViewModel()
{
Employee = employee,
HolidayRequestForm = holidayRequestForm,
};
return View(employeeViewModel);
}
My View is then just a HTML table to display the data from the database.
So the question is how do I display more than one row or entry?? Is it that I'm using FirstorDefault?
You must change Employee Model and declare a list for the Holiday :
Employee Model:
public class EmployeeViewModel
{
public Employee Employee { get; set; }
public List<HolidayRequestForm> HolidayRequestForm { get; set; }
}
Controller Action:
public ActionResult Details(int? id)
{
Employee employee = db.Employees.FirstOrDefault(emp => emp.EmployeeID == id);
List<HolidayRequestForm> holidayRequestForm = db.HolidayRequestForms.Where(emp => emp.EmployeeID == id).ToList();
EmployeeViewModel employeeViewModel = new EmployeeViewModel()
{
Employee = employee,
HolidayRequestForm = holidayRequestForm,
};
return View(employeeViewModel);
}

Xamarin.ios - Using NBuilder to build mocks throws TypeCreationException

I'm using the NBuilder library to build mock http responses, everything works fine in Android, but in iOS each time that I want to build a model class this exception is fired.
"FizzWare.NBuilder.TypeCreationException" and It says that my X model class doesn't have a parametless constructor, which actually has!. For example this model class:
public class Actor
{
public Actor() {
}
[JsonProperty("authorities")]
public List<Authority> Authorities { get; set; }
[JsonProperty("imageDerivatives")]
public ImageDerivatives ImageDerivatives { get; set; }
[JsonProperty("profileFileId")]
public PictureFile ProfilePicture { get; set; }
[JsonProperty("role")]
public Role Role { get; set; }
[JsonProperty("roleId")]
public int RoleId { get; set; }
[JsonProperty("status")]
public bool Status { get; set; }
[JsonProperty("updatedAt")]
public DateTime UpdatedAt { get; set; }
[JsonProperty("username")]
public string Username { get; set; }
[JsonProperty("createdAt")]
public DateTime CreatedAt { get; set; }
[JsonProperty("departmentId")]
public int DepartmentId { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("firstName")]
public string FirstName { get; set; }
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("isAppAdmin")]
public bool IsAppAdmin { get; set; }
[JsonProperty("lastName")]
public string LastName { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
}
And this is how I build the mock response:
private Actor GetRandomActor()
{
return Builder<Actor>.CreateNew()
.With(a => a.FirstName = GetRandomFirstName())
.With(a => a.LastName = GetRandomLastName())
.With(a => a.ProfilePicture = GetRandomPictureFile())
.With(a => a.Email = GetRandomEmail())
.With(a => a.Username = GetRandomUserName())
.Build();
}
Try adding the Preserve attribute to your constructor so it does not get removed by the Linker:
[Preserve]
public Actor() {}
(Or add it at the class level [Preserve (AllMembers = true)])

MVC models converting error

How to set to a different model?
List<ORDER_DETAILSMetadata> result = db.ORDER_DETAILS.Where(p => p.Order_Number == id).ToList();
Error 6 Cannot implicitly convert type 'System.Collections.Generic.List<Mvc5.Models.ORDER_DETAILS>' to 'System.Collections.Generic.List<Mvc5.Models.ORDER_DETAILSMetadata>'
ORDER_DETAILSMetadata
MetadataType(typeof(ORDER_DETAILSMetadata))]
public partial class ORDER_DETAILS
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class ORDER_DETAILSMetadata
{
public int Order_Details_ID { get; set; }
public Nullable<int> Order_Number { get; set; }
public Nullable<short> Sequence_Number { get; set; }
public string Item_Num { get; set; }
public Nullable<short> Order_Quantity { get; set; }
public Nullable<short> Ship_Quantity { get; set; }
}
ORDER_DETAILS.cs
public partial class ORDER_DETAILS
{
public int Order_Details_ID { get; set; }
public Nullable<int> Order_Number { get; set; }
public Nullable<short> Sequence_Number { get; set; }
public string Item_Num { get; set; }
public Nullable<short> Order_Quantity { get; set; }
public Nullable<short> Ship_Quantity { get; set; }
}
As far as i have understood, you can do something like this:
List<ORDER_DETAILSMetadata> result = db.ORDER_DETAILS.
Where(p => p.Order_Number == id).
Select(x => new ORDER_DETAILSMetadata
{
Order_Details_ID = x.Order_Details_ID,
Order_Number = x.Order_Number,
Sequence_Number = x.Sequence_Number,
Item_Num = x.Item_Num,
Order_Quantity = x.Order_Quantity,
Ship_Quantity = x.Ship_Quantity
}).ToList();
If you just want to convert one type of model to other type, you can do something like:
List<target> targetList = new List<target>(originalList.Cast<target>());
You can check the details about Cast() and OfType() here. Go for the first approach when you have different count and types of fields.

ASP.NET MVC finding pending fees

I'm learning ASP.NET MVC 4 with Entity Framework (Database First) and ran into a problem that I'm not able to solve.
I have following tables:
Student: To store students information
Course: To store courses running in an institute
StudentCourse: To store which student selected what course
Fees: To store submitted fees by a student corresponding to StudentCourse
Now, I wan't to show course name, course fees, total fees submitted & the pending fees of students
I'm using Entity Framework in the project and trying to execute a query like this:
var feeslist = entities.Fees
.Where(m => m.StudentCourse.status=="pending")
.GroupBy(m => m.StudentCourse.id)
.Select(m => new { StudentCourseId = m.Key, SumOfFees = m.Sum(v => v.fees) });
I want to get Course object instead of StudentCourseId so that i can display the course, its course fees and total fees submitted by student.
In case, I'm listing all of the four class contents:
Student
public partial class Student
{
public Student()
{
this.Leaves = new HashSet<Leave>();
this.StudentCourses = new HashSet<StudentCourse>();
}
public int id { get; set; }
public string first_name { get; set; }
public string middle_name { get; set; }
public string last_name { get; set; }
public string password { get; set; }
public string email { get; set; }
public string gender { get; set; }
public string facebook { get; set; }
public string contact_number { get; set; }
public string address { get; set; }
public string admin { get; set; }
public string college { get; set; }
public string status { get; set; }
public System.DateTime createdat { get; set; }
public System.DateTime updatedat { get; set; }
public string descripton { get; set; }
public virtual ICollection<Leave> Leaves { get; set; }
public virtual ICollection<StudentCourse> StudentCourses { get; set; }
}
Course
public partial class Course
{
public Course()
{
this.CourseContents = new HashSet<CourseContent>();
this.StudentCourses = new HashSet<StudentCourse>();
}
public int id { get; set; }
public string course_name { get; set; }
public int course_fees { get; set; }
public int duration { get; set; }
public string admin { get; set; }
public string status { get; set; }
public System.DateTime createdat { get; set; }
public System.DateTime updatedat { get; set; }
public virtual ICollection<CourseContent> CourseContents { get; set; }
public virtual ICollection<StudentCourse> StudentCourses { get; set; }
}
StudentCourse
public partial class StudentCourse
{
public StudentCourse()
{
this.Fees1 = new HashSet<Fee>();
this.Issues = new HashSet<Issue>();
}
public int id { get; set; }
public int student_id { get; set; }
public int course_id { get; set; }
public int fees { get; set; }
public System.DateTime join_date { get; set; }
public string admin { get; set; }
public System.DateTime createdat { get; set; }
public System.DateTime updatedat { get; set; }
public string status { get; set; }
public virtual Course Course { get; set; }
public virtual ICollection<Fee> Fees1 { get; set; }
public virtual ICollection<Issue> Issues { get; set; }
public virtual Student Student { get; set; }
}
Fee
public partial class Fee
{
public int id { get; set; }
public int student_course_id { get; set; }
public int fees { get; set; }
public string admin { get; set; }
public System.DateTime createdat { get; set; }
public System.DateTime updatedat { get; set; }
public virtual StudentCourse StudentCourse { get; set; }
}
var feeslist = entities.Fees
.Where(m => m.StudentCourse.status=="pending")
.GroupBy(m => m.StudentCourse.Course)
.Select(m => new { Course = m.Key, SumOfFees = m.Sum(v => v.fees) });

Resources