通过 Razor 页面传递多个参数值
Posted
技术标签:
【中文标题】通过 Razor 页面传递多个参数值【英文标题】:Passing Multiple Parameter Values via a Razor Page 【发布时间】:2020-04-21 12:27:51 【问题描述】:我正在尝试使用 ASP.NET Core 3.0 和 Entity Framework 6 对 Razor 页面上具有复合键的实体进行删除操作。有问题的实体是 CourseAssignment
,其复合键由InstructorID
值和 CourseID
值。
对于具有普通单字段键的实体(例如,具有 CourseID
主键的 Course
实体),剃刀页面上的代码如下:
<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
生成这样的 URL: https://localhost:44388/Courses/Delete?id=1045
作用于此的 C# 代码是:
public async Task<IActionResult> OnPostAsync(int? id)
if (id == null)
return NotFound();
Course = await _context.Courses.FindAsync(id);
if (Course != null)
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
如何更改 razor 页面和 C# OnPostAsync
操作以处理具有需要两个值的复合键的实体?
谢谢!
【问题讨论】:
【参考方案1】:您可以通过添加额外的隐藏字段来传递表单中的多个值。因此,假设您的复合主键中的辅助字段是Course.Instructor
;在这种情况下,您可以添加:
<input type="hidden" asp-for="Course.Instructor" />
然后,您可以扩展 OnPostAsync()
操作的签名以包含该字段:
public async Task<IActionResult> OnPostAsync(int? id, string instructor) …
注意:如果您使用 C# 8.0 的可空注释上下文,那么您可能需要
string?
作为参数类型。
此时,您应该可以将值作为第二个参数传递给FindAsync()
:
Course = await _context.Courses.FindAsync(id, instructor);
注意:这是可行的,因为
FindAsync()
方法接受与主键约束相对应的params Object[] keyValues
。
显然,您需要确认为隐藏字段生成的name
与您的操作参数名称匹配,或者提供绑定提示。
【讨论】:
【参考方案2】:将您的 html 表单更新为如下内容:
<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="hidden" asp-for="Course.InstructorID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
创建一个新类来处理复合键。您也可以使用现有的视图模型类。
public class DeleteCourseRequest
public int CourseId get; set;
public int InstructorId get; set;
然后将控制器的 OnPostAsync 操作更新为如下内容:
public async Task<IActionResult> OnPostAsync(DeleteCourseRequest request)
if (request == null)
return NotFound();
Course = await _context.Courses.FirstOrDefaultAsync(c => c.CourseID == request.CourseID && c.InstructorID == request.InstructorID);
if (Course != null)
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
问题在于,当使用多个参数执行 Post 时,您必须在参数上使用 [FromBody]
或 [FromUri]
绑定。这告诉 ASP.NET Web API 在哪里解析参数。另一种选择是使用视图模型将信息从表单传递到控制器。
【讨论】:
【参考方案3】:好吧,碰巧,我的问题出在Index.cshtml
的 POST 代码中,它调用删除页面,而不是在 的 POST 代码中删除页面本身。在Delete.cshtml.cs
页面的OnGetAsync()
方法中也存在一个问题,而不是它的OnPostAsnc()
方法(尽管也必须调整它以接受两个参数)。
通过Cameron Tinker 和Jeremy Caney 答案中提供的提示,我明白了。 非复合主键的实体的删除页面链接如下所示:
<a asp-page="./Delete" asp-route-id="@item.CourseID">Delete</a>-->
对于具有复合键的实体,它需要看起来像这样:
<a asp-page="./Delete" asp-route-courseID="@item.CourseID" asp-route-instructorID="@item.InstructorID">Delete</a>
asp-route
助手的最后一部分是要传递的参数的名称。 (除了 Razor 页面本身的清晰度之外,这可能无关紧要,如果您只是传递一个常量作为值,而不是像我正在做的那样传递命名属性的值,这将是一个问题。)
作用于此的C#代码在被调用页面的OnGetAsync()
方法Delete.cshtml.cs
中:
public async Task<IActionResult> OnGetAsync(int? courseID, int? instructorID)
if (courseID == null || instructorID == null)
return NotFound();
CourseAssignment = await _context.CourseAssignments
.AsNoTracking()
.Include(c => c.Course)
.Include(c => c.Instructor)
.FirstOrDefaultAsync(m => m.CourseID == courseID && m.InstructorID == instructorID);
if (CourseAssignment == null)
return NotFound();
return Page();
【讨论】:
很高兴听到您弄明白了。如果您不需要[post]
,请使用标签助手语法构造 [get]
链接。
除此之外,请务必将您的答案标记为已接受的答案,以便将您的问题标记为已回答。这将使未来的读者知道这个问题已经解决,并让他们轻松找到您认为最有用的解决方案。 (接受您自己的答案完全没问题;您不会因此获得任何 积分,但它仍会向读者传达解决您问题的方法。)以上是关于通过 Razor 页面传递多个参数值的主要内容,如果未能解决你的问题,请参考以下文章