ASP.NET Core Razor Pages 中处理多个Form表单提交请求

admin
admin
2022-03-04
分享:

ASP.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。

1624425371312.png

要加载此编辑学生 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中处理多个表单的比较合理的实践,他可以帮助我们处理多个表单提交。