'Foreign Key word display blank when the app is run
I have built a Book app in ASP.NET Core razor pages CRUD using Entity Framework. However, when I run the app and view it on https://localhost:44370/, the Foreign Key word appears blank. Here is my code:
Models Author
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BookStore.Models
{
public class Author
{
public int ID { get; set; }
[StringLength(50)]
[Display(Name = "Country Name")]
public string CountryName { get; set; }
[StringLength(50)]
[Display(Name = "Author Name")]
public string AuthorName { get; set; }
[ForeignKey("AuthorID")]
public ICollection<Book> Books { get; set; }
[ForeignKey("AuthorID")]
public ICollection<Tour> Tours { get; set; }
}
}
The Models Book class
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BookStore.Models
{
public class Book
{
[Key]
public int BookID { get; set; }
[StringLength(50)]
[Column("BookTitle")]
[Display(Name = "Book Title")]
public string BookTitle { get; set; }
[StringLength(50)]
[Column("BookPublisher")]
[Display(Name = "Book Publisher")]
public string BookPublisher { get; set; }
[ForeignKey("AuthorID")]
public Author Author { get; set; }
public int AuthorID { get; set; }
public ICollection<BookReview> BookReviews { get; set; }
}
}
Models Tour class
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BookStore.Models
{
public class Tour
{
[Key]
public int TourID { get; set; }
[StringLength(50)]
[Column("TourName")]
[Display(Name = "Tour Name")]
public string TourName { get; set; }
[StringLength(50)]
[Column("TourPlace")]
[Display(Name = "Tour Place")]
public string TourPlace { get; set; }
[ForeignKey("AuthorID")]
public Author Author { get; set; }
public int AuthorID { get; set; }
public ICollection<BookRating> BookRating { get; set; }
}
}
Initially, when I had scaffolded the Pages for the Book Folder and the Tour Folder, the generated Create.cshtml.cs and Edit.cshtml.cs pages showed the Foreign key as "CountryName" and so I modified it to "AuthorName"
Pages:Book:Create.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using BookStore.Models;
namespace BookStore.Pages.Books
{
public class CreateModel : PageModel
{
private readonly BookStore.Models.BookWorkContext _context;
public CreateModel(BookStore.Models.BookWorkContext context)
{
_context = context;
}
public IActionResult OnGet()
{
ViewData["AuthorID"] = new SelectList(_context.Author, "ID", "AuthorName");
return Page();
}
[BindProperty]
public Book Book { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Book.Add(Book);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Data: 'DbInitilializer.cs'
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using BookStore.Models;
namespace BookStore.Data
{
public class DbInitializer
{
public static void Initialize(BookWorkContext context)
{
context.Database.EnsureCreated();
// Look for any Authors.
if (context.Author.Any())
{
return; // DB has been seeded
}
var Authors = new Author[]
{
new Author {CountryName="United States of America",AuthorName="John Coltrane"},
new Author {CountryName= "United States of America",AuthorName= "Jim Meyers"}
};
foreach (Author a in Authors)
{
context.Author.Add(a);
}
context.SaveChanges();
var Tours = new Tour[]
{
new Tour {AuthorID = Authors.Single(a => a.AuthorName == "John Coltrane").ID,TourName = "The Prairie Tour",TourPlace = "Town Center"},
new Tour {AuthorID = Authors.Single(a => a.AuthorName == "Jim Meyers").ID,TourName = "Santa Barbara Tours",TourPlace = "Long Circular Mall"},
};
foreach (Tour t in Tours)
{
context.Tour.Add(t);
}
context.SaveChanges();
var Books = new Book[]
{
new Book {AuthorID = Authors.Single(a => a.AuthorName == "Tim Hendricks").ID, BookTitle = "Three Stooges",BookPublisher = "Penguin"},
new Book {AuthorID = Authors.Single(a => a.AuthorName == "Andy Ford").ID, BookTitle = "Tom Sawyer",BookPublisher = "Collins"},
};
foreach (Book b in Books)
{
context.Book.Add(b);
}
context.SaveChanges();
}
}
}
On running the app, if I try to create a new entry, I see the AuthorName in the dropdown field but once I save the new entry, the Foreign Key column is blank and the other columns are filled with data.
My question is how do I get the Foreign Key word "AuthorName" to appear in the app once I run the app?
Solution 1:[1]
Here is a solution: -
1.Model: -
public class Author
{
public int ID { get; set; }
[StringLength(50)]
[Display(Name = "Country Name")]
public string CountryName { get; set; }
[StringLength(50)]
[Display(Name = "Author Name")]
public string AuthorName { get; set; }
[ForeignKey("AuthorID")]
public ICollection<Book> Books { get; set; }
[ForeignKey("AuthorID")]
public ICollection<Tour> Tours { get; set; }
}
public class Book
{
[Key]
public int BookID { get; set; }
[StringLength(50)]
[Column("BookTitle")]
[Display(Name = "Book Title")]
public string BookTitle { get; set; }
[StringLength(50)]
[Column("BookPublisher")]
[Display(Name = "Book Publisher")]
public string BookPublisher { get; set; }
// [ForeignKey("AuthorID")]
public Author Author { get; set; }
public int AuthorID { get; set; }
}
public class Tour
{
[Key]
public int TourID { get; set; }
[StringLength(50)]
[Column("TourName")]
[Display(Name = "Tour Name")]
public string TourName { get; set; }
[StringLength(50)]
[Column("TourPlace")]
[Display(Name = "Tour Place")]
public string TourPlace { get; set; }
// [ForeignKey("AuthorID")]
public Author Author { get; set; }
public int AuthorID { get; set; }
}
2.Create.cshtml: -
@page
@model CreateModel
<h4>Book</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Book.BookTitle" class="control-label"></label>
<input asp-for="Book.BookTitle" class="form-control" />
<span asp-validation-for="Book.BookTitle" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Book.BookPublisher" class="control-label"></label>
<input asp-for="Book.BookPublisher" class="form-control" />
<span asp-validation-for="Book.BookPublisher" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Book.AuthorID" class="control-label"></label>
<select asp-for="Book.AuthorID" class ="form-control" asp-items="ViewBag.AuthorID"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
3.Index.cshtml:
@page
@model IndexModel
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Book[0].BookTitle)
</th>
<th>
@Html.DisplayNameFor(model => model.Book[0].BookPublisher)
</th>
<th>
@Html.DisplayNameFor(model => model.Book[0].Author)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Book) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.BookTitle)
</td>
<td>
@Html.DisplayFor(modelItem => item.BookPublisher)
</td>
<td>
@Html.DisplayFor(modelItem => item.Author.AuthorName)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.BookID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.BookID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.BookID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
3.Index.cshtml.cs:
public class IndexModel : PageModel
{
private readonly RazorProj2_2.Models.RazorProj2_2Context _context;
public IndexModel(RazorProj2_2.Models.RazorProj2_2Context context)
{
_context = context;
}
public IList<Book> Book { get;set; }
public async Task OnGetAsync()
{
Book = await _context.Book
.Include(b => b.Author).ToListAsync();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | wire_jp |