【问题标题】:Make a form submitting both GET and POST制作一个同时提交 GET 和 POST 的表单
【发布时间】:2021-11-01 22:00:21
【问题描述】:

我有一个页面,我在其中进行搜索。然后我可以对搜索结果进行一些操作。 页面如下:

@page "{handler?}"
@model Pricelists.ListModel

<form>
    <div><label><input autocomplete="off" type="checkbox" asp-for="OnlyEnabled" /> Only enabled</label></div>

    //all other filters used in the search

    <input type="submit" formmethod="get" asp-page-handler="Search" />

    @if (Model.SearchResult.PaginatedResults != null)
    {
        <input type="hidden" asp-for="PageNumber" value="@Model.PageNumber" />
        <input type="hidden" asp-for="TotalPages" value="@Model.TotalPages" />

        <table>
            <tr>
                //header result
            </tr>
            @foreach (var item in Model.SearchResult.PaginatedResults)
            {
                <tr>
                    //result
                </tr>
            }
        </table>

        <label>Page @Model.PageNumber of @Model.TotalPages (Number of records: @Model.SearchResult.Count)</label>
        <input type="submit" formmethod="get" asp-page-handler="Previous" value="<" />
        <input type="submit" formmethod="get" asp-page-handler="Next" value=">" />

        <div>
            <input type="submit" formmethod="post" asp-page-handler="Enable" value="Enable" />
            <input type="submit" formmethod="post" asp-page-handler="Disable" value="Disable" />
            <input type="submit" formmethod="post" asp-page-handler="Delete" value="Delete" />
        </div>
    }
</form>

如您所见,当我进行搜索或更改页面时,我使用GET 提交表单。 但我想提交POST 以修改(启用、禁用或删除)搜索结果。

这里是PageModel:

public class ListModel : PageModel
{
    private const int RECORDS_PER_PAGE = 20;
    private readonly AdminApiClient _client;

    #region Selected Filters
    [BindProperty(SupportsGet=true)]
    public bool OnlyEnabled { get; set; }

    [BindProperty(SupportsGet = true)]
    public long[] SelectedCategories { get; set; }

    [BindProperty(SupportsGet = true)]
    public string[] SelectedCarriers { get; set; }

    [BindProperty(SupportsGet = true)]
    public string[] SelectedDepartures { get; set; }

    [BindProperty(SupportsGet = true)]
    public string[] SelectedArrivals { get; set; }

    [BindProperty(SupportsGet = true)]
    public int PageNumber { get; set; }

    [BindProperty(SupportsGet = true)]
    public int TotalPages { get; set; }
    #endregion


    [BindProperty(SupportsGet = true)]
    public PriceListSearchViewModel SearchResult { get; set; }


    public ListModel(AdminApiClient clientFactory)
    {
        _client = clientFactory;
    }

    public async Task OnGet()
    {
        await this.LoadViewDataAsync();
    }

    public async Task OnGetSearch()
    {
        this.PageNumber = 1;

        await this.LoadViewDataAsync();
        this.SearchResult = await this._client.Pricelists.Search(this.SelectedCategories, this.SelectedCarriers, this.SelectedDepartures, this.SelectedArrivals, this.OnlyEnabled, this.PageNumber, RECORDS_PER_PAGE);

        this.TotalPages = (int)Math.Ceiling(this.SearchResult.Count / (decimal)RECORDS_PER_PAGE);
    }

    public async Task OnGetNext()
    {
        ...
    }

    public async Task OnGetPrevious()
    {
        ...
    }
    
    public async Task OnPostEnable()
    {
        await this.LoadViewDataAsync();
        await this._client.Pricelists.ChangeStatus(this.SelectedCategories, this.SelectedCarriers, this.SelectedDepartures, this.SelectedArrivals, this.OnlyEnabled, this.PageNumber, RECORDS_PER_PAGE, enable: true);
    }

    public async Task OnPostDisable()
    {
        await this.LoadViewDataAsync();
        await this._client.Pricelists.ChangeStatus(this.SelectedCategories, this.SelectedCarriers, this.SelectedDepartures, this.SelectedArrivals, this.OnlyEnabled, this.PageNumber, RECORDS_PER_PAGE, enable: false);
    }

    public async Task OnPostDelete()
    {
        await this.LoadViewDataAsync();
        await this._client.Pricelists.Delete(this.SelectedCategories, this.SelectedCarriers, this.SelectedDepartures, this.SelectedArrivals, this.OnlyEnabled, this.PageNumber, RECORDS_PER_PAGE);
    }
}

为了简单起见,我让您只看到一种 GET 方法和一种 POST 方法。但是,无论如何我都使用相同的绑定属性。

现在,当我提交 GET 时,一切正常。但是当我提交POST 时,我收到一个错误400 Bad request。我让你看一个fiddler:

http 请求是我所期望的,但显然不是响应。

有什么想法吗?

编辑 我从不使用OnPost* 的方法。这就像我实现提交按钮的方式是错误的。问题不在于OnPost* 方法的实现。

谢谢

【问题讨论】:

  • 如果您不显示任何代码,我们如何告诉您输出是什么。
  • 我已经编写了整个cshtml和相关的PageModel。为什么你说我不显示任何代码? OnGetNext 和 OnGetPrevious 与 OnGetChange 相同,只是 PageNumber 不同。您想查看表格结果吗?我认为应有尽有,但如果您需要更多代码,请告诉我您想看什么
  • 对不起,我在 PostDelete 看不到任何代码。我怎么知道它为什么返回 400 状态。
  • 我已经修改了帖子。但是我从不进入OnPostEnable、OnPostDisable和OnPostDelete...所以问题不在于方法的实现。
  • 那你应该多解释一下。你有 404 或 400 错误吗?

标签: asp.net-core post get form-submit razor-pages


【解决方案1】:

您有两个选择,分开表格并为每种方法编写一个表格。或者 jsut 使用 javascript 处理它。

看看这个样本:

<form id="frm" action="/test" method="post">

<button type="submit">save</button>

和脚本:

<script>

setTimeout(function () {

    var frmElement = document.getElementById('frm');
    frmElement.setAttribute('method', 'get')

}, 2000)
</script>

【讨论】:

    【解决方案2】:

    尝试删除您拥有的表单并为每个按钮制作一个特殊的表单

    <form asp-page-handler="delete" method="post">
         <button class="btn btn-default">Delete</button>
    </form>
    .... and so on
    

    【讨论】:

      【解决方案3】:

      您可以尝试将method="post" 添加到&lt;form&gt;。示例:&lt;form method="post"&gt;。

      我用你的代码测试,当点击带有formmethod="post"的输入时,会在表单数据中丢失__RequestVerificationToken。并且在你将method="post"添加到表单后,它将有一个隐藏的输入,如下所示:

      结果:

      【讨论】:

        猜你喜欢
        • 2014-12-07
        • 1970-01-01
        • 1970-01-01
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-22
        • 1970-01-01
        相关资源
        最近更新 更多