c# - 如何将主键值传递给我的 CRUD 函数?
问题描述
这是我的代码:
专辑.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>
<td><a asp-page="/Albums/Edit" asp-route-id="@album">Edit title</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>
</div>
专辑.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.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();
}
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");
}
}
}
删除.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="submit" value="Delete" asp-route-id="@Model.Album.AlbumId" class="btn btn-danger" /> |
<a asp-page="/Albums">Back to List</a>
</form>
</div>
删除.cshtml.cs
#region snippet_All
using Project.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace Project.Pages.Albums
{
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) //changed int -> string
{
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();
}
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("/Albums");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("/Albums/Delete",
new { id, saveChangesError = true });
}
}
}
}
#endregion
编辑.cshtml
@page
@model Project.Pages.Albums.EditModel
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Album</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Album.AlbumId" />
<div class="form-group">
<label asp-for="Album.Title" class="control-label"></label>
<input asp-for="Album.Title" class="form-control" />
<span asp-validation-for="Album.Title" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="/Albums">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
编辑.cshtml.cs
using Project.Models;
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 Microsoft.EntityFrameworkCore;
namespace Project.Pages.Albums
{
public class EditModel : PageModel
{
private readonly Chinook _context;
public EditModel(Chinook context)
{
_context = context;
}
[BindProperty]
public Album Album { get; set; }
public string ErrorMessage { get; set; }
#region snippet_OnGetPost
// public async Task<IActionResult> OnGetAsync(int? id)
// {
// if (id == null)
// {
// return NotFound();
// }
// Album = await _context.Albums.FindAsync(id);
// if (Album == null)
// {
// return NotFound();
// }
// return Page();
// }
public async Task<IActionResult> OnGetAsync(string? id, bool? saveChangesError = false) //changed int -> string
{
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();
}
public async Task<IActionResult> OnPostAsync(int id)
{
var albumToUpdate = await _context.Albums.FindAsync(id);
if (albumToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Album>(
albumToUpdate,
"album",
s => s.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("/Albums");
}
return Page();
}
#endregion
private bool AlbumExists(int id)
{
return _context.Albums.Any(e => e.AlbumId == id);
}
}
}
我的代码构建并运行正常,但是当我去编辑时,我得到了,例如
找不到此本地主机页面 没有找到该网址的网页:https://localhost:5001/Albums/Edit/353.%20123.%20Test
我确定它应该只是传递AlbumId
,如
https://localhost:5001/Albums/Edit/353
...当我手动将 URL 更改为该 URL 时,它可以工作。
例如,删除功能适用于...
https://localhost:5001/Albums/Delete/353.%20123.%20Test2
...其中“353”是AlbumId
,“123”是ArtistId
,“Test2”是Title
。
...但这确实有效。那么我怎样才能让 Delete 和 Edit 都能从AlbumId
? 这就是所需要的,对吧?TIA 寻求帮助。
解决方案
在我看来,您的问题在于您从 Album.cshtml.cs 返回信息的方式。而不是构建一个字符串的 IEnumerable,而是返回专辑的 IEnumerable
public IEnumerable<Album> Albums { get; set; }
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Albums";
Albums = db.Albums;
}
现在,在 Album.cshtml 文件中,您可以使用强类型模型创建每个专辑的列表,其中包含删除和编辑具有正确 ID 的每一行的链接
<thead class="thead-inverse">
<tr>
<th>Album ID</th>
<th>artist ID</th>
<th>Album title</th>
<th></th><th></th>
</tr>
</thead>
<tbody>
@foreach (Album album in Model.Albums)
{
<tr>
<td>@album.AlbumID</td>
<td>@album.ArtistID</td>
<td>@album.Title</td>
<td><a asp-page="/Albums/Delete" asp-route-id="@album.AlbumID">Delete</a></td>
<td><a asp-page="/Albums/Edit" asp-route-id="@album.AlbumID">Edit title</a></td>
</tr>
}
</tbody>
最后,您可以改回编辑和删除代码以接收 asp-route-id 中传递的整数
public async Task<IActionResult> OnGetAsync(int id, bool? saveChangesError = false)
{
Album = await _context.Albums
.AsNoTracking()
.FirstOrDefaultAsync(m => m.AlbumId == id);
if(Album == null)
.....
}
推荐阅读
- sql - 正则表达式用破折号、空格破折号、点空间、点和带有空字符串的撇号替换空格
- python - 与 Python 装饰器中的范围混淆
- reactjs - 刷新页面时如何转到主页?
- python - python - 如何在python中的字符串内捕获两个大括号内的字符串,并在字符串内捕获更多大括号?
- css - 在第一个 div 的高度增加时将第二个 div 推到下面
- gradle - 如何自定义 gradle build 控制台输出?
- c - for 循环中的 and 运算符和 or 运算符有什么区别?
- python - 如果第 1 列值小于第 2 列,如何交换第 1 列第 2 列值的条件,那么我想交换
- python - 如何使用条件更新字典的值?
- wordpress - 安装步骤 2 上 Azure 404 上的 Wordpress 错误