Delete.cshtml.cs
#region snippet_All
using Project.Models; //using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace Project.Pages.Albums //ContosoUniversity.Pages.Students
{
public class DeleteModel : PageModel
{
private readonly Chinook _context;
public DeleteModel(Chinook context)
{
_context = context;
}
[BindProperty]
public Album Album { get; set; }
public string ErrorMessage { get; set; }
public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}
Album = await _context.Albums
.AsNoTracking()
.FirstOrDefaultAsync(m => m.AlbumId == id);
if (Album == null)
{
return NotFound();
}
if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var album = await _context.Albums.FindAsync(id);
if (album == null)
{
return NotFound();
}
try
{
_context.Albums.Remove(album);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("./Delete",
new { id, saveChangesError = true });
}
}
}
}
#endregion
Delete.cshtml
@page
@model Project.Pages.Albums.DeleteModel
@{
ViewData["Title"] = "Delete";
}
<h1>Delete</h1>
<p class="text-danger">@Model.ErrorMessage</p>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Album</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.ArtistId)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.ArtistId)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.AlbumId)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.AlbumId)
</dd>
</dl>
<form method="Delete">
<input type="hidden" asp-for="AlbumId" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>
Album.cshtml
@page
@model Project.Pages.AlbumsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Albums</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Album ID, artist ID, Album title</th>
</tr>
</thead>
<tbody>
@foreach (string album in Model.Albums)
{
<tr>
<td>@album</td>
<td><a asp-page="./Delete" asp-route-id="@album">Delete</a></td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<p>Enter a title & ArtistID for a new album: </p>
<form method="POST">
<div><input asp-for="Album.Title" /></div>
<div><input asp-for="Album.ArtistId" /></div>
<input type="submit" />
</form>
@* <p>Enter a value and Album ID for a new album title: </p>
<form method="POST">
<div><input asp-for="Album.Title" /></div>
<div><input asp-for="Album.AlbumId" /></div>
<input type="submit" />
</form> *@
</div>
Album.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Project.Models;
using System;
namespace Project.Pages
{
public class AlbumsModel : PageModel
{
private Chinook db;
public AlbumsModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<string> Albums { get; set; }
public void OnGet()
{
ViewData["Title"] = "Chinook Web Site - Albums";
// Albums = db.Albums.Select(s => s.Title);
Albums = db.Albums.Select(s => s.AlbumId.ToString() + ". " + s.ArtistId + ". " + s.Title);
}
[BindProperty]
public Album Album { get; set; }
public IActionResult OnPost()
{
if (ModelState.IsValid)
{
db.Albums.Add(Album);
db.SaveChanges();
return RedirectToPage("/albums");
}
return Page();
}
// void RemoveAlbum(int albumId)
// {
// var album = db.Albums.Find(albumId);
// if (album == null)
// throw new ArgumentOutOfRangeException();
// db.Albums.Remove(album);
// db.SaveChanges();
// }
public IActionResult DeleteAlbum(int AlbumId)
{
var album = db.Albums.Find(AlbumId);
if (album == null) return Page();
db.Albums.Remove(album); db.SaveChanges(); return RedirectToPage("/albums");
}
}
}
My project builds and runs fine, but the Delete button does nothing but refresh the page. I've tried reloading the page, but that makes no odds. I'm not convinced <td><a asp-page="./Delete" asp-route-id="@album">Delete</a></td>
is right, but when I try to plug the AlbumId
in there instead of just album
, I always get errors. Any help please? TIA.
According to your code and description, it looks that in the Album.cshtml
page, you will list the albums, and if click the "delete" hyperlink, it will redirect to the Delete.cshtml
page and show the selected album, after that, click the "Delete" button to delete the item and redirect to the Index page. If that is the case, please refer the following steps to modify your code.
First, in the Album.cshtml
page:
Since the Delete.cshtml
page located in the "Albums" folder, when you add the hyperlink (<a>
tag), the asp-page
attribute should like this: asp-page="/Albums/Delete"
.
The <a>
tag like this: <a asp-page="/Albums/Delete" asp-route-id="@album">Delete</a>
.
Second, in the Delete.cshtml.cs
file:
If you check the Album.cshtml.cs file or use F12 developer tool to check the parameter, you can see the id is a string value, instead of int type. So, change the code as below:
public async Task<IActionResult> OnGetAsync(string? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}
//using string.split method to split the id parameter, and get the albumid.
var albumid = System.Convert.ToInt32(id.ToString().Split('.')[0]);
Album = await _context.Albums
.AsNoTracking()
.FirstOrDefaultAsync(m => m.AlbumId == albumid);
if (Album == null)
{
return NotFound();
}
if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}
return Page();
}
and in the Delete.cshtml
page, you should also add the tag helper reference at the head of the page, and use asp-route-id
attribute to pass the albumid to the Post method, code like this:
@page "{id?}"
@model Project.Pages.Albums.DeleteModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div>
<form method="post">
@*<input type="hidden" asp-for="Album.AlbumId" />*@
<input type="submit" value="Delete" asp-route-id="@Model.Album.AlbumId" class="btn btn-danger" /> |
<a asp-page="/Index">Back to List</a>
</form>
</div>
After modified, the result as below (After test your sample on my machine, I have deleted them):
Here are some references about Asp.net Core Razor Page routing and event handler, you could refer them:
Handler Methods in Razor Pages
The detail updated page resource as below:
album.cshtml:
@page
@model Project.Pages.AlbumsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Albums</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Album ID, artist ID, Album title</th>
</tr>
</thead>
<tbody>
@foreach (string album in Model.Albums)
{
<tr>
<td>@album</td>
<td><a asp-page="/Albums/Delete" asp-route-id="@album">Delete</a></td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<p>Enter a title & ArtistID for a new album: </p>
<form method="POST">
<div><input asp-for="Album.Title" /></div>
<div><input asp-for="Album.ArtistId" /></div>
<input type="submit" />
</form>
@* <p>Enter a value and Album ID for a new album title: </p>
<form method="POST">
<div><input asp-for="Album.Title" /></div>
<div><input asp-for="Album.AlbumId" /></div>
<input type="submit" />
</form> *@
</div>
album.cshtml.cs:
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Project.Models;
using System;
namespace Project.Pages
{
public class AlbumsModel : PageModel
{
private Chinook db;
public AlbumsModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<string> Albums { get; set; }
public void OnGet()
{
ViewData["Title"] = "Chinook Web Site - Albums";
// Albums = db.Albums.Select(s => s.Title);
Albums = db.Albums.Select(s => s.AlbumId.ToString() + ". " + s.ArtistId + ". " + s.Title);
}
[BindProperty]
public Album Album { get; set; }
public IActionResult OnPost()
{
if (ModelState.IsValid)
{
db.Albums.Add(Album);
db.SaveChanges();
return RedirectToPage("/albums");
}
return Page();
}
// void RemoveAlbum(int albumId)
// {
// var album = db.Albums.Find(albumId);
// if (album == null)
// throw new ArgumentOutOfRangeException();
// db.Albums.Remove(album);
// db.SaveChanges();
// }
public IActionResult DeleteAlbum(int AlbumId)
{
var album = db.Albums.Find(AlbumId);
if (album == null) return Page();
db.Albums.Remove(album); db.SaveChanges(); return RedirectToPage("/albums");
}
}
}
Delete.cshtml:
@page "{id?}"
@model Project.Pages.Albums.DeleteModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{ ViewData["Title"] = "Delete"; }
<h1>Delete</h1>
<p class="text-danger">@Model.ErrorMessage</p>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Album</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.ArtistId)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.ArtistId)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Album.AlbumId)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Album.AlbumId)
</dd>
</dl>
<form method="post">
@*<input type="hidden" asp-for="Album.AlbumId" />*@
<input type="submit" value="Delete" asp-route-id="@Model.Album.AlbumId" class="btn btn-danger" /> |
<a asp-page="/Index">Back to List</a>
</form>
</div>
Delete.cshtml.cs:
#region snippet_All
using Project.Models; //using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace Project.Pages.Albums //ContosoUniversity.Pages.Students
{
public class DeleteModel : PageModel
{
private readonly Chinook _context;
public DeleteModel(Chinook context)
{
_context = context;
}
[BindProperty]
public Album Album { get; set; }
public string ErrorMessage { get; set; }
public async Task<IActionResult> OnGetAsync(string? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}
var albumid = System.Convert.ToInt32(id.ToString().Split('.')[0]);
Album = await _context.Albums
.AsNoTracking()
.FirstOrDefaultAsync(m => m.AlbumId == albumid);
if (Album == null)
{
return NotFound();
}
if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var album = await _context.Albums.FindAsync(id);
if (album == null)
{
return NotFound();
}
try
{
//_context.Albums.Remove(album);
//await _context.SaveChangesAsync();
return RedirectToPage("/Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("/Albums/Delete",
new { id, saveChangesError = true });
}
}
}
}
#endregion