如何多次提交表单(asp.net core razor)

Posted

技术标签:

【中文标题】如何多次提交表单(asp.net core razor)【英文标题】:How to submit a form multiple times (asp.net core razor) 【发布时间】:2021-03-13 19:16:54 【问题描述】:

我正在尝试创建一个可以使用不同信息多次提交的表单,同时在一个字段中保留一个共同的值。

我有一个来自 ASP.NET Core Razor 中的 SQL 表的列表视图,它是构建项目的列表。对于列表中的每一行,我都有一个指向“创建”模板页面的链接,用户可以在其中为存储在不同表中的项目创建投标条目。项目编号分配给一个路由值(asp-route-Number = "上一个列表中的项目编号")并填充“创建新投标”表单中的隐藏字段。

使用剃须刀页面的默认代码,一切正常。您单击提交并返回到项目列表。

我想做的是在“创建新投标”表单上有另一个选项,它允许您保存并为同一项目输入另一个投标。我创建了另一个按钮和处理程序来执行此操作,但我坚持实际实现它。如果我使用 return Page() 表单发布并且页面返回完整的路由数据,但文本字段仍然包含以前的数据并且下拉列表为空。如果我使用 return RedirectToPage(CreateNewBid, Route data) 表单发布,但似乎没有传递路线数据并创建空值错误。

这是项目列表中的链接(在 foreach 表内),它会将您带到“创建投标”表单并且工作正常。

<a asp-page="CreateBid" asp-route-Number="@item.ProjectNumber" asp-route-opwid="@item.Id">New Bid</a>

创建投标表单具有以下提交和创建另一个条目

int num = int.Parse(Request.Query["Number"]);
int idnum = int.Parse(Request.Query["opwid"]); 

<input type="submit" value="Save and enter another" 
                   asp-page-handler="Another" asp-route-opwid="@idnum" 
                   asp-route-Number="@num" class="btn btn-primary"/>

还有处理程序:

public async Task<IActionResult> OnPostAnotherAsync(int Number, int opwid)
        
            if (!ModelState.IsValid)
            
                return Page();
            

            _context.OpwBids.Add(OpwBids);
            await _context.SaveChangesAsync();

            return Page();
            //return RedirectToPage("./CreateBid", (Number == num, opwid == idnum));
        

我还在“重定向到页面”中的路由参数(而不是使用变量)中尝试了几件事,但似乎没有任何效果。

有没有更简单的方法,还是我错过了什么?

这是cshtml文件:

@page 
@model Authorization_AD.Pages.GenSvc.BidEntry.CreateBidModel

@
    ViewData["Title"] = "CreateBid";


@ int num = int.Parse(Request.Query["Number"]);
   int idnum = int.Parse(Request.Query["opwid"]);       
 

<h1>Create Bid</h1>

<h4>OPW number @num</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <input asp-for="OpwBids.OpwProject" value="@idnum" hidden class="form-control" />
            </div>
            <div class="form-group">
                <label asp-for="OpwBids.OpeningDate" class="control-label"></label>
                <input asp-for="OpwBids.OpeningDate" class="form-control" />
                <span asp-validation-for="OpwBids.OpeningDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="OpwBids.Contractor" class="control-label"></label>
                <select asp-for="OpwBids.Contractor" class="form-control" asp-items="ViewBag.Contractor">
                    <option disabled selected>--- SELECT ---</option>
                </select>
            </div>
            <div class="form-group">
                <label asp-for="OpwBids.BidAmount" class="control-label"></label>
                <input asp-for="OpwBids.BidAmount" class="form-control" />
                <span asp-validation-for="OpwBids.BidAmount" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save and enter another" 
                       asp-page-handler="Another" asp-route-opwid="@idnum" 
                       asp-route-Number="@num" class="btn btn-primary"/>
                <input type="submit" value="Save and return to list" asp-page-handler="Done" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page="Index">Back to List</a>
</div>

@section Scripts 
    @await Html.RenderPartialAsync("_ValidationScriptsPartial");

这是 C# 文件:

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 Authorization_AD.Models;

namespace Authorization_AD.Pages.GenSvc.BidEntry

    public class CreateBidModel : PageModel
    
        private readonly Authorization_AD.Models.OPWContext _context;

        public CreateBidModel(Authorization_AD.Models.OPWContext context)
        
            _context = context;
        

        public IActionResult OnGet()
        
        ViewData["Contractor"] = new SelectList(_context.Contractors, "Id", "ContractorName");
        ViewData["OpwProject"] = new SelectList(_context.MainProjectsListing, "Id", "ProjectNumber");
            return Page();
        

        [BindProperty]
        public OpwBids OpwBids  get; set; 

        public async Task<IActionResult> OnPostDoneAsync()
        
            if (!ModelState.IsValid)
            
                return Page();
            

            _context.OpwBids.Add(OpwBids);
            await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        

        public async Task<IActionResult> OnPostAnotherAsync(int Number, int opwid)
        
            if (!ModelState.IsValid)
            
                return Page();
            

            _context.OpwBids.Add(OpwBids);
            await _context.SaveChangesAsync();

            return Page();
            //return RedirectToPage("./CreateBid", (Number == OpwBids.OpwProjectNavigation.ProjectNumber, opwid == OpwBids.OpwProject));
        
    

【问题讨论】:

您能谈谈您的具体需求吗?你需要达到什么目标?在 Create 页面上创建多个 OpwBids? 如果可以的话,您可以发布您的创建页面的代码。 我想要的是一个底部有两个按钮的表单。一个是“保存并退出”,另一个是“保存并创建另一个”,它创建数据库记录,重新加载相同的表单并记住预先填充到隐藏字段中的项目编号。 【参考方案1】:

您可以向您的页面添加一个属性,该属性将用于绑定单击按钮的值。

public class CreateBidModel : PageModel 

    //...

    //Add this property to your page.
    [BindProperty]
    public string Button get;set;
    
    public void OnGet(int number,string opwid)
        //Set the number and opwid to the target properties
    
    
    public Task<IActionResult> OnPostAsync()
        
        if (!ModelState.IsValid)
        
            return Page();
        

        _context.OpwBids.Add(OpwBids);
        await _context.SaveChangesAsync();
        if(Button == "finish")
            return RedirectToPage("./Index");
        
        else 
            return RedirectToPage("./CreateBid", (Number == OpwBids.OpwProjectNavigation.ProjectNumber, opwid == OpwBids.OpwProject));
        
    

您需要向视图添加两个具有相同名称的按钮,并且该值将映射到 Button 属性。

<form method="post">
... Other content goes here

    <button name="@Html.NameFor(m => m.Button)" value="another">Create another</button>
    <button name="@Html.NameFor(m => m.Button)" value="finish">Finish</button>
</form>

点击按钮的值会被解析为Pagemodel的Button属性。根据该值,您可以决定如何进一步处理请求的响应(在您的情况下完成/创建另一个)。

【讨论】:

【参考方案2】:

感谢大家的帮助。通过将以下内容添加到“OnPostAnotherAsync”任务中,我得到了它做我想做的事情:

public async Task<IActionResult> OnPostAnotherAsync(int Number, int opwid)
    
        if (!ModelState.IsValid)
        
            return Page();
        

        _context.OpwBids.Add(OpwBids);
        await _context.SaveChangesAsync();

        ViewData["Contractor"] = new SelectList(_context.Contractors, "Id", "ContractorName");
        ModelState.SetModelValue("OpwBids.BidAmount", new ValueProviderResult(string.Empty, CultureInfo.InvariantCulture));
        ModelState.SetModelValue("OpwBids.Contractor", new ValueProviderResult(string.Empty, CultureInfo.InvariantCulture));
        
        return Page();
     

在“保存更改”之后,我需要重新加载“承包商”下拉列表的视图数据。那么只需要在返回页面之前清除表单字段即可。

【讨论】:

以上是关于如何多次提交表单(asp.net core razor)的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 5 MVC:在模态窗口之前验证表单

如何使用 ASP.NET Core 更新由依赖表组成的记录 [关闭]

如何在 asp net core 2.2 中间件中多次读取请求正文?

PartialViewResult 表单不会清除 ajax 结果上的值 - ASP.NET Core Razor c#

如何在第一次提交(在客户端)后立即禁用 ASP.NET 按钮?

请问asp.net中如何在后台代码里提交表单