ASP.NET Core Razor Pages 中处理多个Form表单提交请求
admin
2022-03-04ASP.NET Core 中使用托管启动程序集
导航:
•Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
•
•IHostingStartup(托管启动)实现在从外部程序集启动时向应用程序添加增强功能。
•
•https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation/6.0.0-preview.2.21154.6
•
•
•"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
ASP.NET Core Razor Pages 中处理多个Form表单提交请求
在本视频中,我们将讨论如何在ASP.NET Core Razor Pages中handler方法的使用,它主要服务于多个表单提交请求的时候使用。
Razor Pages中的handler处理程序方法
ASP.NET Core Razor Pages框架使用命名约定来选择处理程序方法。考虑以下编辑学生 Razor Pages。

要加载此编辑学生 Razor 页面,浏览器会发出GET请求。为了处理此GET请求,ASP.NET Core Razor Pages框架在对应的PageModel类中查找一个名为OnGet()的方法。
单击更新按钮时,浏览器会发出POST请求。为了处理此POST请求,ASP.NET Core Razor Pages框架在对应的PageModel类中寻找一种名为OnPost()的方法。
因此,以下是razor pages框架用于查找处理程序方法的命名约定。单词On是请求动词的前缀。因此,对于GET请求,它将查找OnGet,而对于POST请求,它将查找OnPost。
Razor Pages上有多个Form表单
如果给定的 Razor Pages上有2个或更多表单,该怎么办呢。在以下 Razor Pages上,我们有2种需求业务,如下:。
- Form表单1-用于更新通知首选项
- Form表单2-用于更新学生数据

在Form表单1上-我们具有更新消息通知按钮
在Form表单2-我们有更新按钮
在EditModel类中,我们有以下2个处理程序方法
public void OnPostUpdateNotificationPreferences()
{
// 处理更新消息通知内容
}
public IActionResult OnPost(Student student)
{
// 处理更新学生信息的功能
}
在表单1上,单击 更新通知首选项按钮时,我们希望OnPostUpdateNotificationPreferences()方法处理该请求。我们使用<form>元素上的asp-page-handler标记助手来指定它,如下所示。
OnPost前缀不是必需的,但是您可以根据需要指定它。
<form method="post" asp-page-handler="UpdateNotificationPreferences">
@*Form 1 - 消息通知配置开关*@
</form>
在Form 2上,当单击更新按钮时,我们希望OnPost()方法处理该请求。我们使用<form> 元素上的asp-page-handler标记助手 来指定它,如下所示。
<form method="post" asp-page-handler="OnPost">
@*Form 2 - 处理学生数据*@
</form>
当更新通知首选项按钮被点击,处理程序名称在URL作为查询字符串参数传递。
http://localhost:2221/students/edit/2/?handler=updatenotificationpreferences
修改处理程序名称路由参数
如果您希望将处理程序名称updatenotificationpreferences作为路由参数而不是查询字符串参数传递,请在视图文件中包含路由参数,如下。
@page "{id:min(1)}/{handler?}"
进行此更改后,现在将处理程序名称作为路由参数传递到URL中,生成的url如下。
http://localhost:2221/students/edit/1/updatenotificationpreferences/
Edit.cshtml视图
@page "{id:min(1)}/{handler?}"
@model StudentManagement.RazorPage.Pages.Students.EditModel
@{
ViewData["Title"] = "编辑";
// 如果学生没有照片信息,就默认给他一张空照片
var photoPath = "~/images/" + (Model.Student.PhotoPath ?? "noimage.png");
}
<div class="row">
<div class="col-md-12">
<h1>消息通知配置开关</h1>
<form method="post" asp-page-handler="UpdateNotificationPreferences">
<div class="form-check">
<input asp-for="Notify" class="form-check-input" />
<label asp-for="Notify" class="form-check-label">
允许接收消息通知信息
</label>
</div>
<button type="submit" class="btn btn-primary">
更新消息通知
</button>
@if (!string.IsNullOrEmpty(Model.Message))
{
<div class="alert alert-primary">
@Model.Message
</div>
}
</form>
<hr />
</div>
<div class="col-md-12">
<h1>编辑学生</h1>
<form method="post" class="mt-3">
@*使用隐藏的input标签来存储提交表单时需要的学生id*@
<input hidden asp-for="Student.Id" />
@*asp-for TagHelper 负责在处理在不同的标签中显示现有的数据*@
<div class="form-group row">
<label asp-for="Student.Name" class="col-sm-2 col-form-label">
</label>
<div class="col-sm-10">
<input asp-for="Student.Name" class="form-control" placeholder="Name">
</div>
</div>
<div class="form-group row">
<label asp-for="Student.Email" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Student.Email" class="form-control" placeholder="Email">
</div>
</div>
<div class="form-group row">
<label asp-for="Student.Major" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<select asp-for="Student.Major" class="custom-select mr-sm-2"
asp-items="Html.GetEnumSelectList<MajorEnum>()">
<option value="">请选择</option>
</select>
</div>
</div>
<div class="form-group row">
<label asp-for="Photo" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
@*Photo属性类型是IFormFile,ASP. NET Core会根据这个属性自动创建一个FileUpload控件 *@
@* 有关更具体的信息在《深入浅出ASP.NET Core》那本书有介绍 *@
<input asp-for="Photo" class="custom-file-input form-control">
<label class="custom-file-label">更换图片</label>
</div>
</div>
</div>
@*显示有照片的学生信息*@
<div class="form-group row col-sm-4 offset-4">
<img class="imageThumbnail" src="@photoPath" asp-append-version="true" />
</div>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">更新</button>
<a asp-page="/Students/Index" class="btn btn-primary">取消</a>
</div>
</div>
@section Scripts {
<script>
$(document).ready(function () {
$('.custom-file-input').on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).next('.custom-file-label').html(fileName);
});
});
</script>
}
</form>
</div>
</div>
Edit.cshtml.cs
public class EditModel : PageModel
{
private readonly IStudentRepository studentRepository;
private readonly IWebHostEnvironment webHostEnvironment;
public EditModel(IStudentRepository studentRepository,
IWebHostEnvironment webHostEnvironment)
{
this.studentRepository = studentRepository;
//使用 IWebHostEnvironment 服务,我们可以获取wwwroot文件夹下的路径地址信息
this.webHostEnvironment = webHostEnvironment;
}
//这是显示模板将用于的属性,显示现有的学生数据
public Student Student { get; set; }
// 我们使用这个属性来存储和处理新上传的照片
[BindProperty]
public IFormFile Photo { get; set; }
[BindProperty]
public bool Notify { get; set; }
public string Message { get; set; }
public IActionResult OnGet(int id)
{
Student = studentRepository.GetStudent(id);
if (Student == null)
{
return RedirectToPage("/NotFound");
}
return Page();
}
public IActionResult OnPost(Student student)
{
if (Photo != null)
{
//上传新照片的时候,需要检查当前学生是否有已经存在的照片,如果有的话,就需要删除它,再上传新照片。
if (student.PhotoPath != null)
{
string filePath = Path.Combine(webHostEnvironment.WebRootPath,
"images", student.PhotoPath);
System.IO.File.Delete(filePath);
}
// 将新照片保存到wwwroot/images文件夹中,并更新student 的PhotoPath属性
student.PhotoPath = ProcessUploadedFile();
}
Student = studentRepository.Update(student);
return RedirectToPage("Index");
}
public void OnPostUpdateNotificationPreferences(int id)
{
if (Notify)
{
Message = "您已经打开了消息通知功能";
}
else
{
Message = "你已经关闭了消息通知功能";
}
Student = _studentRepository.GetStudent(id);
}
private string ProcessUploadedFile()
{
string uniqueFileName = null;
if (Photo != null)
{
string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + Photo.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
Photo.CopyTo(fileStream);
}
}
return uniqueFileName;
}
}
以上便是在一个 Razor Pages中处理多个表单的比较合理的实践,他可以帮助我们处理多个表单提交。
52ABP框架ASP.NET Core与Angular开发教程