How define properties as foreign keys in models to MVC Codetemplates generate it as FK
-
07-03-2021 - |
Question
I use EFCodefirst. Most of you know, but the following code is part of MVC3 T4 CodeTemplates in Edit.tt And also in Create.tt of AddView:
<div class="editor-field">
<#
if (property.IsForeignKey) {
#>
@Html.DropDownList("<#= property.Name #>", String.Empty)
<#
} else {
#>
@Html.EditorFor(model => model.<#= property.Name #>)
<#
}
#>
@Html.ValidationMessageFor(model => model.<#= property.Name #>)
</div>
As you see if the CodeTemplates find a property as a FK generate a DropDownList automatically, but the question is how can define props as a FK? this is my models:
public class Artist {
public long Id { get; set; }
public string Name { get; set; }
public Genre Genre { get; set; }
}
public class Genre {
public long Id { get; set; }
public string Title { get; set; }
public ICollection<Artist> Artists { get; set; }
}
public class MusicGalleryDB : DbContext {
public DbSet<Artist> Artists { get; set; }
public DbSet<Genre> Genres { get; set; }
}
I expected the Genre in Artist class be a FK and in create view of Artist I can select a Genre in dropdownlist, but the mvc don't generate any dropdownlist in views actually as mvc's view there is not any relation between Genre and Artist. whe I look at the Database tables I see the following:
Artist(Id, Name,Genre_Id)
Genre(Id, Title)
as you see there is a column name Genre_Id in Artist table that is a FK to Id of Genre Table This table is generated automatically with EFCodefirst but the MVC CodeTemplate can not recognize FKs.
How can I do this?
I know I can write my own views but I am interesting to mvc generate views automatically in correct way. Does anyone know about this?
Edit:
This is my controller (generated automatically by mvc):
public class ArtistController : Controller
{
private MusicGalleryDB db = new MusicGalleryDB();
//
// GET: /Artist/
public ViewResult Index()
{
var artists = db.Artists.Include(a => a.Genre);
return View(artists.ToList());
}
//
// GET: /Artist/Details/5
public ViewResult Details(int id)
{
Artist artist = db.Artists.Find(id);
return View(artist);
}
//
// GET: /Artist/Create
public ActionResult Create()
{
ViewBag.GenreID = new SelectList(db.Genres, "Id", "Title");
return View();
}
//
// POST: /Artist/Create
[HttpPost]
public ActionResult Create(Artist artist)
{
if (ModelState.IsValid)
{
db.Artists.Add(artist);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.GenreID = new SelectList(db.Genres, "Id", "Title", artist.GenreID);
return View(artist);
}
//
// GET: /Artist/Edit/5
public ActionResult Edit(int id)
{
Artist artist = db.Artists.Find(id);
ViewBag.GenreID = new SelectList(db.Genres, "Id", "Title", artist.GenreID);
return View(artist);
}
//
// POST: /Artist/Edit/5
[HttpPost]
public ActionResult Edit(Artist artist)
{
if (ModelState.IsValid)
{
db.Entry(artist).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.GenreID = new SelectList(db.Genres, "Id", "Title", artist.GenreID);
return View(artist);
}
//
// GET: /Artist/Delete/5
public ActionResult Delete(int id)
{
Artist artist = db.Artists.Find(id);
return View(artist);
}
//
// POST: /Artist/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Artist artist = db.Artists.Find(id);
db.Artists.Remove(artist);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
Solution
You have forgotten to include the GenreID
property in the Artist
table. Update it to following.
public class Artist
{
public int Id { get; set; }
public string Name { get; set; }
public int GenreId { get; set; } // You forgot this
public Genre Genre { get; set; }
}
BTW, you dont need to use long
, int
is good enough for Id
.