【发布时间】:2021-05-10 12:07:13
【问题描述】:
这是我的代码:
albums.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>
albums.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
edit.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");}
}
edit.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 时,它可以工作。
delete 函数的工作原理例如...
https://localhost:5001/Albums/Delete/353.%20123.%20Test2
...其中“353”是AlbumId,“123”是ArtistId,“Test2”是Title。
...但实际上 确实 工作。那么我怎样才能让删除和编辑都从AlbumId 工作呢?这就是所需要的,对吧? TIA 寻求帮助。
【问题讨论】:
-
通常参数在 URL 中问号后,用 & 分隔。见维基:en.wikipedia.org/wiki/Query_string?force_isolation=true
-
asp-route-id="@album"> 应该是 asp-route-id="@album.AlbumID"> 并且,当然,您应该将 Edit.cshtml.cs 中的 OnGetAsync 改回接收整数
-
@jdweng - 不,不是这样,
Delete和Edit的 URL 就像 localhost:5001/Albums/Edit/353.%20123.%20Test -
@Steve - 我试过了,但我得到 "Pages\albums.cshtml(18,75): error CS1061: 'string' does not contain a definition for 'AlbumID' and no access extension method可以找到接受“字符串”类型的第一个参数的“AlbumID””编辑:我现在正在尝试处理
OnGetAsync建议,谢谢。 -
为什么要从 Select 中构建一个 IEnumerable 字符串?这是你问题的根源。返回一个专辑的 IEnumerable 并为您要显示的每个元素构建一个列,然后您可以使用 @album.AlbumID
标签: c# asp.net asp.net-core crud razor-pages