Home > OS >  Make a form submitting both GET and POST
Make a form submitting both GET and POST

Time:09-18

I have a page, where I do a search. Then I can make some actions on results of the search. Here the page:

@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>

As you can see, either when I do the search or when I change the page, I submit the form using GET. But I would like to make a POST submit to modify (enable, disable or delete) the result of the search.

Here the 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);
    }
}

To semplify I let you see just one GET and one POST method. But, in any case I use same binded properties.

Now, when I make a GET submit everything works correctly. But when I make a POST submit I get an error 400 Bad request. I let you see a fiddler:

enter image description here

The http request is what I expected, but obviously not the response.

Any idea?

EDIT I never go in the methods OnPost*. It is like the way I have implemented the submit button is wrong. The problem is not the implementation of the OnPost* methods.

Thank you

CodePudding user response:

try to remove form that you have and make a special form for each button

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

CodePudding user response:

You have two options, Separate forms and write a form for each method. or jsut handle it using javascript.

look at this sample:

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

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

and script:

<script>

setTimeout(function () {

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

}, 2000)
</script>

CodePudding user response:

You can try to add method="post" to <form>.Example:<form method="post">.

I test with your code,when click the inputs with formmethod="post",it will lose __RequestVerificationToken in the form data.And after you add method="post" to form,it will have a hidden input as the following shows:

enter image description here

result: enter image description here

  • Related