Asp.net core mvc ViewModel with 2 Models - c#

I'm building a feature with a jquery datatable, the idea is to have a list of stores in the parent row, and then when expanding the parent to list all the licensed terminals in child rows that are linked to the store parent row by a StoreLicenseId column. The issue I am having is that I have a ViewModel with two models, one for the list of stores and one for the licensed terminals. I'm busy building the method into my controller, my problem is in the second part of the method where I new up "StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()", all the references to tl.terminalId and tl.Terminalname. I get this error "StoreListViewModel does not contain a definition for TerminalID and no accessible extension method". I can see why this is happening, so my question really is, how do I include this "second" TerminalListViewModel into my method to form part of the query ?
ViewModel
public partial class StoreListViewModel
{
public List<TerminalListViewModel> StoreLicenseDetails { get; set; } = null!;
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
[DisplayName("Store Name")]
public string StoreName { get; set; } = null!;
[DisplayName("App One Licenses")]
public int QtyAppOneLicenses { get; set; }
[DisplayName("App Two Licenses")]
public int QtyAppTwoLicenses { get; set; }
[DisplayName("Date Licensed")]
public DateTime DateLicensed { get; set; }
[DisplayName("Licensed Days")]
public int LicenseDays { get; set; }
[DisplayName("Is License Active")]
public bool LicenseIsActive { get; set; }
}
public partial class TerminalListViewModel
{
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
public Guid TerminalId { get; set; }
public string TerminalName { get; set; } = null!;
public string LicenseType { get; set; } = null!;
public int TerminalLicenseDays { get; set; }
public DateTime DateLicensed { get; set; }
public bool LicenseIsActive { get; set; }
public bool IsDecommissioned { get; set; }
public DateTime LastLicenseCheck { get; set; }
}
Controller Method
//sl = StoreList
//tl = TerminalList
public IEnumerable<StoreListViewModel> GetStoreList()
{
return GetStoreList().GroupBy(sl => new { sl.StoreLicenseId, sl.StoreName, sl.QtyAppOneLicenses,
sl.QtyAppTwoLicenses, sl.DateLicensed, sl.LicenseDays,
sl.LicenseIsActive })
.Select(sl => new StoreListViewModel()
{
StoreName = sl.Key.StoreName,
QtyAppOneLicenses = sl.Key.QtyAppOneLicenses,
QtyAppTwoLicenses = sl.Key.QtyAppTwoLicenses,
DateLicensed = sl.Key.DateLicensed,
LicenseDays = sl.Key.LicenseDays,
LicenseIsActive = sl.Key.LicenseIsActive,
StoreLicenseId = sl.FirstOrDefault().StoreLicenseId,
StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()
{
StoreLicenseId = tl.StoreLicenseId,
TerminalId = tl.TerminalId,
TerminalName = tl.TerminalName,
}).ToList()
}).ToList();
}

Based on the error,I suppose your GetStoreList() method returns List<OrderListViewModel> ,but your OrderListViewModel doesn't contains properties of TerminalListViewModel,So you got the error
GetStoreList() method should return List<SourceModel>( Source is the model which contains all the properties of StoreListViewModel and TerminalListViewModel)
For example,the link your provided:Multiple child rows in datatable, data from sql server in asp.net core
public class OrderList
{
//source of properties of OrderListViewModel(parent rows)
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
//source of properties of OrderListDetailViewModel(child rows)
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
public class OrderListViewModel
{
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
public List<OrderListDetailViewModel> OrderListDetails { get; set; }
}
public class OrderListDetailViewModel
{
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
Orderlist contains all columns OrderListViewModel and OrderListDetailViewModel needs.
When it comes to your case,you should
create 3 models (source,parentrow,childrows)
model for parentrows contains the properties
StoreLicenseId,StoreName, QtyAppOneLicenses,QtyAppTwoLicenses, DateLicensed, LicenseDays,LicenseIsActive
and model for childrows contains the other properties of source model
If you still have questions,please show the data you pulled form db,and I'll write a demo for you

Related

Issue in mapping Automapper configuration

I have the following POCO classes:
public class Employees
{
public int EmployeeId
{
get;
set;
}
public int EmpImageId
{
get;
set;
}
public string EmployeePhotoUrl
{
get;
set;
}
public string EmpAddress
{
get;
set;
}
}
public class Images
{
public int ImageId
{
get;
set;
}
public string ImageUrl
{
get;
set;
}
public string ImgCode
{
get;
set;
}
}
public class EmployeeDTO
{
public int EmployeeId
{
get;
set;
}
public int EmpImageId
{
get;
set;
}
public string EmployeePhotoUrl
{
get;
set;
}
public string EmpAddress
{
get;
set;
}
}
While getting the list of Employees present in the system, for each Employee, the photourl (EmployeePhotoUrl) is fetched from the Images table using the EmpImageId property.
// Get the list of Employees
var employees = await _dbContext.Employees
.Select(ef => new EmployeeDTO
{
EmployeeId= ef.EmployeeId,
EmployeePhotoUrl = images.FirstOrDefault(im => im.ImageId.Equals(ef.EmpImageId)).EmployeePhotoUrl,
EmpAddress = ef.EmpAddress
}).Skip((pageNo - 1) * 100).Take(pageSize).ToListAsync();
I want to leverage Automapper in this case. The issue I see here is the assignment of EmployeePhotoUrl, since this property is fetched from another entity: Images
Can anyone help me to know how to leverage Automapper in this case.

How to CreatMap List of Object with appling conditions Automapper

I have Domain object ProductType. It contains parentproducttypeId column. If product type is a subset of another producttype that parentproducttypeId to set to that producttypeId.(ex: T-Shirt is a subset of Casual wears)
public class ProductType : IEntityBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int PerentProductTypeId { get; set; }
public int Active { get; set; }
public DateTime UpdatedOnUTC { get; set; }
}
In API view model I have two classes
public class ParentProductTypeModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<ChildProductTypeModel> ChildProductTypeList { get; set; }
public ParentProductTypeModel()
{
ChildProductTypeList = new List<ChildProductTypeModel>();
}
}
public class ChildProductTypeModel
{
public int Id { get; set; }
public string Name { get; set; }
}
I need to Map returned List of Product Type to this ParentProductTypeModel List with setting all subset lists according to there parentproducttypeId. If parentproducttypeId equals to 0 it is parentproduct.

Create relations and swap id to name in view EF ASP.NET MVC

I have two models:
public class Project
{
public int ProjectID { get; set; }
public string Name { get; set; }
public string ShortDesc { get; set; }
public string LongDesc { get; set; }
public int Status { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string Image { get; set; }
public List<Note> Notes { get; }
}
and:
public class Note
{
public int NoteID { get; set; }
public int ProjectID { get; set; }
public string Name { get; set; }
public string Content { get; set; }
public int Status { get; set; }
public DateTime Timestamp { get; set; }
public string Tags { get; set; }
}
My goal is to be able to easily relate Note and Project objects in view.
To store ProjectID in Note object I do:
// GET: Notes/Create
public ActionResult Create() {
ViewBag.Projects = db.Projects.ToList();
return View();
}
And later in Create view:
#Html.DropDownListFor(model => model.ProjectID, new SelectList(ViewBag.Projects, "ProjectID", "Name"))
Which allows me to pick related project by it's name.
How to correctly swap ProjectID with Project.Name on Index page (where all my notes are shown)?
Also I would like to see related Notes column in Project Index (where all my Projects are listed). Is it possible with use of Notes List from ProjectModel?
You can add a Project property to your Note class.
public class Note
{
public int NoteID { get; set; }
public int ProjectID { get; set; }
public string Name { get; set; }
public string Content { get; set; }
public int Status { get; set; }
public DateTime Timestamp { get; set; }
public string Tags { get; set; }
public virtual Project Project {set;get;}
}
And now you can access this project property in your view
#model List<Note>
#foreach(var item in Model)
{
<p>#item.Name</p>
<p>#item.Project.Name</p>
}

c# lambda query to load item in a related table

Lambda Query
I am working with with EF6 MVC5 and set up my listing model to include a virtual ICollection of images. I want to query the listings and include an image with each listing title in my view. I am having trouble writing the lambda query in the controller to send to my view.
Listing Class
public class Listing
{
public int Id { get; set; }
public ApplicationUser User;
[Required]
public string UserId { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; }public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string Phone { get; set; }
public string LocationAddress1 { get; set; }
public string LocationAddress2 { get; set; }
public string LocationCity { get; set; }
public string LocationState { get; set; }
public string LocationZip { get; set; }
public string LocationCountry { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
[DataType(DataType.MultilineText)]
public string Comments { get; set; }
public bool isLEO { get; set; }
public bool isProperty { get; set; }
public string Keywords { get; set; }
public bool isNoShowAddress { get; set; }
public bool isActive { get; set; }
public bool isApproved { get; set; }
public virtual ICollection<Image> Images { get; set; }
public virtual ICollection<Review> Reviews { get; set; }
Image Class
public class Image
{
public int Id { get; set; }
public Listing Listing { get; set; }
public int ListingId { get; set; }
public string ImagePath { get; set; }
public bool isPrimary { get; set; }
public DateTime DateAdded { get; set; }
public bool isHidden { get; set; }
}
When you have nested objects I believe you do something like this:
var listings = dbcontext.Listings.Include("Images").Where(...)
Where include tells EF to fetch nested objects.
It could also be something like this:
var listings = dbcontext.Listings.Include(c=>c.Images).Where(...)
You have to project your query to another type specifically designed for use inside Views (this is often referred to as ViewModel) or you can just project it into an anonymous type, the approach is similar.
The following code assumes you will use an anonymous type:
var listings = dbContext.Listings.Select(l => new {
Id = l.Id,
User = l.User,
//add every property you need to show inside your View
Image = l.Images.FirstOrDefault(i => i.isPrimary)
});

Accessing properties from multiple classes

I am creating a web application and I have two classes:
public class MOrderMain
{
public int ID { get; set; }
public int CompanyID { get; set; }
public string CompanyName { get; set; }
public DateTime OrderDate { get; set; }
public string BillingName { get; set; }
public string BillingAddress { get; set; }
public string DeliveryName { get; set; }
public string DeliveryAddress { get; set; }
}
public class MOrder
{
public int ID { get; set; }
public int OrhID { get; set; }
public int ProID { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public double Rate { get; set; }
public double Amount { get; set; }
public int DeliveredQty { get; set; }
}
I would like to retrieve details from both classes. For example, I want to get
ID and Billing Name from class MorderMain and all the properties from class MOrder. How can I do this?
I am getting the values by database. I have the query but how will I assign the data and how will I retrieve from both?
var mylist = new List<MOrder>();
_con = _db.GetConnection();
if (_con.State.Equals(ConnectionState.Closed))
{
_con.Open();
}
_cmd = new SqlCommand("Get_All_Order_Details", _con)
{ CommandType = CommandType.StoredProcedure };
_dr = _cmd.ExecuteReader();
while (_dr.Read())
{
mylist.Add(new MOrder
{
ID = Convert.ToInt32(_dr["ordID"]),
OrhID = Convert.ToInt32(_dr["orhID"]),
ProID = Convert.ToInt32(_dr["proID"]),
Name = _dr["pName"].ToString(),
Quantity = Convert.ToInt32(_dr["ordQty"]),
Rate = Convert.ToDouble(_dr["ordRate"]),
Amount = Convert.ToDouble(_dr["ordAmount"]),
DeliveredQty = Convert.ToInt32(_dr["ordQtyDelivered"])
});
}
return mylist;
Since you are retrieving data from both tables in your database but want to combine them in your application, the solution would be to create a single class that contains the data you return from your stored procedure:
public class MAllOrderDetails
{
public int ID { get; set; }
public string BillingName { get; set; }
// include the other billing details you want here
public int OrhID { get; set; }
public int ProID { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public double Rate { get; set; }
public double Amount { get; set; }
public int DeliveredQty { get; set; }
}
Then, your query changes to filling in a List<MAllOrderDetails>.
This leaves your application with only dealing with a collection of a single class with all the data nicely contained in single objects.
var mylist = new List<MAllOrderDetails>();
//...
while (_dr.Read())
{
mylist.Add(new MAllOrderDetails
{
ID = Convert.ToInt32(_dr["ordID"]),
BillingName = _dr["BillingName"].ToString(),
// etc.
OrhID = Convert.ToInt32(_dr["orhID"]),
ProID = Convert.ToInt32(_dr["proID"]),
Name = _dr["pName"].ToString(),
Quantity = Convert.ToInt32(_dr["ordQty"]),
Rate = Convert.ToDouble(_dr["ordRate"]),
Amount = Convert.ToDouble(_dr["ordAmount"]),
DeliveredQty = Convert.ToInt32(_dr["ordQtyDelivered"])
});
}
Update
You could probably get away with this as the closest solution to not creating an additional classes:
class MAllOrderDetails
{
public MOrder Order { get; set; }
public MOrderMain OrderMain { get; set; }
}
I feel, though, that from a maintainability standpoint, this will cause you more headaches than just creating additional classes.

Categories

Resources