Search code examples
asp.net-corerazor-pagesasp.net-core-tag-helpers

How can I post the same data to two different handlers depending on the button clicked?


[See updates at bottom]

I have a Razor page with a form on it. I want to have two buttons on that form, that perform a slightly different action - both using the same posted form data.

I tried using the asp-page-handler helper on the second button, but it doesn't seem to add anything to the HTML (I would expect it to add a formaction attribute to the <button> element, but it doesn't add anything at all).

Here's an example page:

@page  "{id?}"
@model IndexModel

@tagHelperPrefix x:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Current value is @Model.Foo</p>

<x:form method="post">
    <input type="text" name="foo" />
    <button type="submit">Default</button>
    <button type="submit" x:asp-page-handler="Alternative">Alternative</button>
</x:form>

... and here's the corresponding page model:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MyWebApplication.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public string Foo { get; set; }

        public void OnGet(int? id)
        {
        }

        public void OnPostAsync(string foo)
        {
            Foo = foo;
        }

        public void OnPostAlternativeAsync(string foo)
        {
            Foo = foo.ToUpper();
        }
    }
}

This is rendered as:

enter image description here

...where the generated HTML for the form is:

<form method="post">
    <input type="text" name="foo" />
    <button type="submit">Default</button>
    <button type="submit" x:asp-page-handler="Alternative">Alternative</button>
</form>

The fact that the x:asp-page-handler attribute is still in the generated HTML makes me think that the Razor engine hasn't recognized it. I've tried taking off the x: prefix, but that didn't help.

What am I doing wrong?


UPDATE

OK, I tried removing the tag prefix and removing the @tagHelperPrefix line, and that made a difference. A formaction is added to the second <button> element as expected.

However:

  • that's really annoying - the @tagHelperPrefix is not something I want to lose, and
  • now both buttons are triggering the "Alternative" action, even though only one of them has the formaction!

Here's the new generated HTML:

<form method="post">
    <input type="text" name="foo" />
    <button type="submit">Default</button>
    <button type="submit" formaction="/?handler=Alternative">Alternative</button>
</form>

SECOND UPDATE

OK, so If I put asp-page-handler="" on the "default" button, then each button goes to the correct handler, which is fine.

The last question that remains, then, is: how can I make this work with the tag helper prefix?


Solution

  • [Answering my own question in case this helps others.]

    It turns out that:

    1. The tag-helper-prefix only applies to elements, not attributes, so it should be asp-page-handler="..." rather than x:asp-page-handler="..." even if the tag-helper-prefix is x:.
    2. Those asp- attributes are only recognized within a tag that is tag-helper-enabled - which is all elements when no tag-helper-prefix is specified, or only elements with the tag-helper-prefix where one is specified. In my case, I had to change <button ...> to <x:button ...>.
    3. If you specify asp-page-handler for one button, you need to specify it on all the buttons, even if you specify it as "" to get the default action.