MVC 5 Code First scaffolding with simple relationship - c#

I'm doing some experimental programming to get caught up with ASP MVC.
I created a project for buildings containing rooms. A very simple one to many relationship. I am trying to get scaffolding to work, and from older MVC examples it looks like this should just work. However, the BuildingId field in Rooms isn't mapping to the Building model - no select list in the view.
My models are:
namespace BuildingManagement.Models
{
public class Building
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Address { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
[Display(Name = "Phone")]
[DataType(DataType.PhoneNumber)]
[Required]
public string PhoneMain { get; set; }
[Display(Name = "Contact")]
[Required]
public string ContactName { get; set; }
public string Description { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
}
}
and
namespace BuildingManagement.Models
{
public class Room
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Type { get; set; }
public int BuildingId { get; set; }
}
}
I generated the controller with views using Entity Framework, it created the forms but not with the expected Building select list in the Room edit view. It displays an integer input field instead.
What am I missing?

You should change this:
public class Room
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Type { get; set; }
public int BuildingId { get; set; }
}
to
public class Room
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Type { get; set; }
[ForeignKey("ContainingBuilding")]
public int BuildingId { get; set; }
public virtual Building ContainingBuilding{ get; set;}
}
This way the scaffolding will generate a select list for the building.

public List<SelectListItem> CountryListItems {get; set;}
public int CountryId {get; set;}
sample model above
Model.CountryListItems= new List<SelectListItem>();
CountryListItems.Add(new SelectListItem
{
Text = "Albania",
Value = "1"
});
CountryListItems.Add(new SelectListItem
{
Text = "Bangladesh",
Value = "2",
Selected = true
});
CountryListItems.Add(new SelectListItem
{
Text = "Canada",
Value = "3"
});
The sample code above can be used in controller or other generator model class.
#Html.DropDownListFor(model => model.CountryId, model.CountryListItems, "-- Select Status --")
sample view block above.

Related

Asp.net core mvc ViewModel with 2 Models

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

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>
}

Save complexa data using entity framework

Hi every one I want to save complex data using Entity Framework and C#. I have 2 classes Product and Order defined as follows
Product Class
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Quantity { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
Order Class
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<Product> ProductDetails { get; set; }
}
And I want to save data Order details and my piece of code is as follows.
public Order Add(Order odrerDetails)
{
using (var context = new EcommerceDBContext())
{
var MyOrder_Id = Helper.Random(7); //Generate random orderID from my class
foreach (var detail in odrerDetails.ProductDetails)
{
odrerDetails.Order_Id = MyOrder_Id;
odrerDetails.Quantity = Convert.ToInt32(detail.Quantity);
odrerDetails.Amount = Convert.ToDouble(detail.Price);
//Other Details
context.objOrderListing.Add(odrerDetails);
}
context.SaveChanges();
return odrerDetails;
}
}
This gives me perfect data but when it comes to context.SaveChanges(); it return's me error.
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types.
To me you domain model seems all wrong. The order should just be used for grouping, its a typical e-commerce scenario.
When you get a receipt of your purchases, you get one receipt with every Item and price listed next to it. Its considered as one order of multiple things, not multiple orders of multiple things.
Reading your last comment, you cant have multiple orders with the same order id. Try to understand the domain first before trying to solve it with code. Also,you have no notion of a Customer with an Order.
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<OrderLineItem> Items { get; set; }
}
public class OrderLineItem
{
[Key]
public long ID { get; set; }
public long Order_Id { get; set; }
public long Product_Id {get; set;}
public int Quantity {get; set;}
}

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)
});

MVC3 EF Code First "Foreign Key" Data

I'm coming from webforms, and I'm trying to replicate a simple data model in MVC. I'm a .NET and C# novice, so excuse me if this is a really simple question. I have "Letters" that each have one category and multiple recipients. EF seems to create my data model correctly on the SQL backend, but I cant access the category in the view. Here is my model:
namespace FFLettersMVC.Models
{
public class Letter
{
public int id {get; set;}
public DateTime dateCreated { get; set; }
public string letterTitle { get; set; }
public DateTime dateMailed { get; set; }
public string createdBy { get; set; }
public string Type { get; set; }
public int CategoryID { get; set; }
public Category Category { get; set; }
public virtual ICollection<Recipient> Recipient { get; set; }
}
public class Category
{
public int id { get; set; }
public string name { get; set; }
}
public class Recipient
{
public int id { get; set; }
public int letterID { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public string ssnTin { get; set; }
public string email { get; set; }
public Letter Letter { get; set; }
}
}
Controller Code for Details Page:
//
// GET: /Letter/Details/5
public ViewResult Details(int id)
{
Letter letter = db.Letters.Find(id);
return View(letter);
}
View Code Attempting to access comments property:
<div class="display-label">Category</div>
<div class="display-field">
#Html.DisplayFor(model => model.Category.name)
</div>
You need to make it virtual, as you did the Recipient.
public virtual Category Category { get; set; }
Marking the property as 'virtual' notifies EF to override the property when creating its proxies.

Categories

Resources