MVC3 EF Code First "Foreign Key" Data - c#

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.

Related

Club the UI model and DB model in C#

I'm having a client, and it sending the following Signature to the Library
Client UI Signature :
namespace Library.Model
{
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string streetName { get; set; }
public string City { get; set; }
public string State { get; set; }
}
}
Library DB Structure:
namespace Library.Data
{
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
public Address AddressInfo { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string streetName { get; set; }
public string City { get; set; }
public string State { get; set; }
}
}
Here I'm doing the mapping process from Client UI model to DB Structured model. How could I use the DB structured model as like Client model instead of the Client model.
Kindly assist me how efficiently we can share the DB Structured model in Client?
Note: But the Client the Signature should be
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string streetName { get; set; }
public string City { get; set; }
public string State { get; set; }
}
Kindly refer Update a class property based on another Property of a calss properties value in the Setter - I need the solution similar to this.
i think you can use PersonViewModel to make this and it will be like you mention
public class PersonViewModel
{
public int PersonId { get; set; }
public string Name { get; set; }
public string streetName { get; set; }
public string City { get; set; }
public string State { get; set; }
}
Make join and file this object
PersonViewModel persons = new PersonViewModel ();
I wish it will help 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>
}

Linq Include not working when item has multiple navigation properties of the same class

I am working on a project for school, and got a bit stuck on this.
A booking has 3 navigation properties, 1 customer and 2 airports.
To get the CustomerCode in one of the views for a booking, I can use (db.Bookings.Include(b => b.Customer)).
When I try to do the same for Origin and/or Destination (db.Bookings.Include(b => b.Origin)), nothing happens.
I can work around it by finding and setting both origin and destination by using a second query. (booking.Origin = db.Airports.Find(id))
But I would like to know why the Include isn't working, and if there is a more elegant way of loading the airports on a booking.
Booking class
public int BookingID { get; set; }
public int CustomerID { get; set; }
public int OriginID { get; set; }
public int DestinationID { get; set; }
public string Awb { get; set; }
public string ClientRef { get; set; }
public string Info { get; set; }
// Navigation
public virtual Airport Origin { get; set; }
public virtual Airport Destination { get; set; }
public virtual Customer Customer { get; set; }
Customer class
public int CustomerID { get; set; }
public string CustomerCode { get; set; }
public string CompanyName { get; set; }
public string VatNumber { get; set; }
Airport class
public int AirportID { get; set; }
public string AirportCode { get; set; }
Controller
public ActionResult Index()
{
var bookings = db.Bookings.Include(b => b.Origin).Include(b => b.Destination).Include(b => b.Customer);
return View(bookings.ToList());
}
Context
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
public class AppContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, please use data migrations.
// For more information refer to the documentation:
// http://msdn.microsoft.com/en-us/data/jj591621.aspx
public AppContext() : base("name=AppContext")
{
}
public System.Data.Entity.DbSet<Tester.Models.Country> Countries { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Airport> Airports { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Customer> Customers { get; set; }
public System.Data.Entity.DbSet<Tester.Models.Booking> Bookings { get; set; }
}
As suggested by Alexander Derck, use [ForeignKey] attribute.
Booking class
public int BookingID { get; set; }
public int CustomerID { get; set; }
[ForeignKey("Origin")]
public int OriginID { get; set; }
[ForeignKey("Destination")]
public int DestinationID { get; set; }
public string Awb { get; set; }
public string ClientRef { get; set; }
public string Info { get; set; }
// Navigation
public virtual Airport Origin { get; set; }
public virtual Airport Destination { get; set; }
public virtual Customer Customer { get; set; }
Origin is a Property. Is not possible use for include. Maybe you not like try like this:
Booking.Include(a=> a.Airport)

ASP.Net MVC 5 EF6 - Allow nullables on two properties but force at least one to be present

In simple relational terms, I want each entry of ContractDetails to be assigned to either a Site OR a Company, not both at the same time, and one of them must be selected or there is no link at all. I'm not quite sure how to represent this in entity framework. My Model at Present:
Company Model:
public class Company
{
public int ID { get; set; }
public string Company_Name { get; set; }
public string Company_Prefix { get; set; }
public virtual ICollection<Site> Sites { get; set; }
}
Contract Details Model:
public class ContractDetails
{
public int ContractDetailsID { get; set; }
public int ContractTypeID { get; set; }
public int ContractRenewalPeriodID { get; set; }
public int? CompanyID { get; set; }
public int? SiteID { get; set; }
[Required, StringLength(10)]
public string Reference { get; set; }
[Display(Name = "Contract Start Date"), DataType(DataType.Date)]
public DateTime? Contract_Start_Date { get; set; }
[Display(Name = "Contract End Date"), DataType(DataType.Date)]
public DateTime? Contract_End_Date { get; set; }
[Column(TypeName = "text")]
public string Notes { get; set; }
public string Direct_Debit_Reference { get; set; }
public virtual Company Company { get; set; }
public virtual Site Site { get; set; }
public virtual ContractType ContractType { get; set; }
public virtual ContractRenewalPeriod ContractRenewalPeriod { get; set; }
}
Site Model:
public class Site
{
public int ID { get; set; }
public string Site_Name { get; set; }
public string Site_TelephoneNumber { get; set; }
public string Site_City { get; set; }
public int CompanyID { get; set; }
public virtual Company Company { get; set; }
}
Just implement the IValidatableObject on ContractDetails class. On Validate method put the validation logic. If the object is not valid you must return a collection of ValidationResult. when saving the object, EF will execute the Validate method and verify that your ContractDetails object is coherent.

MVC 5 Code First scaffolding with simple relationship

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.

Categories

Resources