POST Form Data to Blazor razor component (application/x-www-form-urlencoded)

Viewed 3672

I just started learning Blazor so please be patient with me if the question is strange.

Is it possible to POST Data as content-type "application/x-www-form-urlencoded" to Blazor razor component so when the page is being opened in browser it will show the provided initial values by the caller? It works well when using querystring and calling razor component url with HTTP GET method and with help of navigationManager. In this case I am not able to change how the data will be sent. I need to be able to handle a HTTP POST call with content-type application/x-www-form-urlencoded and the body providing initial value as a key=value. Data shall be showing on screen when page is loaded. User should then be given some options on page and selecting by clicking buttons.

If this is not possible what would be the proper approach for this specific requirement, i.e. cannot change how data is being sent (must be HTTP POST with content-type application/x-www-form-urlencoded) and receiving application being Blazor.

Update: The Blazor app should preferably be server-side but can be changed to web assembly (client-side) if required.

2 Answers

In Blazor Server, in-app navigation is done via websocket, there is no HTTP request made, thus no GET or POST action. You can only handle external HTTP requests, which should be exactly the case in question.

Blazor Components, or actually Razor Components, despite some of them act like pages with the @page tag, are just components. They do not live independently, but have to be hosted in a Razor Page, i.e. your _Host.cshtml by default. Any external HTTP request to your Blazor app is actually a request to the hosting page, which in turn loads the corresponding page component depending on the request URI. These requests cannot be seen in the components, but they can be handled in the hosting page because it is just a plain old Razor Page.

To do this:

  1. Create a PostFormService which passes the post form between the host page and your components:
using Microsoft.AspNetCore.Http;

public class PostFormService
{
    public IFormCollection? Form { get; set; }
}
  1. Register the PostFormService to the DI. In the ConfigureServices method in Startup.cs, add:
services.AddScoped<PostFormService>();
  1. Add the following code block to your host page:
@using Microsoft.AspNetCore.Mvc.RazorPages;

<!-- ignore anti-forgery token for external post requests -->
@attribute [IgnoreAntiforgeryToken]

<!-- specify model for the page -->
@model HostPageModel

@{

public class HostPageModel : PageModel
{
    // postFormService is injected by the DI
    public HostPageModel(PostFormService postFormService)
    {
        PostFormService = postFormService;
    }

    private PostFormService PostFormService { get; }

    public void OnPost()
    {
        // store the post form in the PostFormService
        PostFormService.Form = Request.Form;
    }

}

}
  1. Now you can inject PostFormService into your Razor Components and access the request form:
@inject PostFormService PostFormService;
@code{
    protected override void OnInitialized()
    {
        base.OnInitialized();

        // PostFormService.Form will be null if the page is not requested by 
        // a POST method
        var data = PostFormService.Form?["data"];
        Console.WriteLine(data);
    }
}

Sounds like you are looking for an MVC flavoured solution but implemented in a Blazor page component- So am I currently. A Blazor post request using an EditForm or just a vanilla HTML submit action is an easy topic to find guidance on, but equipping a Blazor page component such that it can process incoming form body data as if it were an MVC controller [HttpPost] decorated method is a challenge. And yet, in some scenarios like an external card payment portal that redirects to your app when a transaction succeeds or fails, that is what you need. Many payment portals are only equipped to serve and post back to consumers with hidden input fields and form body key-value tuples as if it was 20 years ago! I feel your pain. I suspect we'll need a combination of MVC and Blazor functionality to achieve this.

Related