Yes, it is. The trick to accepting the post is to include IgnoreAntiforgeryToken in the _Host page. The trick to reading the data is to catch the OnPost in the PageModel. The downfall is that Blazor is a single page application and the ignore attribute will be turned on globally.
I can't find an effective way to programmatically add the IgnoreAntiforgeryToken or change the PageModel for an individual page component. Instead I create a list of PostComponentPages that will accept post data.
Hopefully someone can build on this answer and find a better way to turn on IgnoreAntiforgeryToken for an individual component.
Note: In my example I only accept post data to the Counter page.
_Host.cshtml
@{
Layout = "_Layout";
@model HostPageModel;
}
HostPageModel.cs
// Required for accepting post data from 3rd party resource.
[IgnoreAntiforgeryToken]
// Not required, but gives us access to the post data and exception handling per request.
public class HostPageModel : PageModel
{
/// <summary>
/// A list of components we accept post request on.
/// </summary>
public static List<string> PostComponentPages = new List<string>() { "/counter" };
// postFormService is injected by the DI
public HostPageModel(PostFormService postFormService)
{
PostFormService = postFormService;
}
private PostFormService PostFormService { get; }
// Hook in to the OnPost.
public void OnPost()
{
if (PostComponentPages.Any(c => Request.Path.ToString().Contains(c)))
PostFormService.Form = Request.Form; // acceptable component, store the post form in the PostFormService
else
throw new Exception("HTTP 401 Error – Unauthorized");
}
}
PostFormService.cs
Responsible for storing the post data in a service collection.
public class PostFormService
{
public IFormCollection? Form { get; set; }
}
Program.cs
Register the service.
builder.Services.AddScoped<PostFormService>();
Counter.razor
Inject our service, and read the post data from third party.
@inject PostFormService PostFormService;
protected override void OnInitialized()
{
base.OnInitialized();
// These fields are based on the third party.
var PaymentID = PostFormService.Form?["PaymentID"];
var ReturnCode = PostFormService.Form?["ReturnCode"];
var ReturnMessage = PostFormService.Form?["ReturnMessage"];
}
Note: Just noticed this only works in ServerPrerendered. Since the Post request is always treated as a new scope/session, I handle this by making the _Host.cshtml force ServerPrerendered for pages supporting Post requests.
@if (HostPageModel.PostComponentPages.Any(c => Request.Path.ToString().Contains(c)))
{
<component type="typeof(App)" render-mode="ServerPrerendered" />
}
else
{
<component type="typeof(App)" render-mode="Server" />
}