I have a PWA Webapplication that was previously only in ASPNet Core MVC and I am now conevrting it to Blazor 8.
I am consuming shared data that is invoked outside of the app with the Web Share API. This worked perfectly in the MVC app and can receive shared text, urls, files etc.
In Blazor, however, it only works with the GET method. The POST method fails due to either AntiforgeryToken not present or formData not binding
The GET method is ok for just normal text and url's but I need the POST method to enable file shares as well.
But I cannot get the formData bound to the Blazor page.
MVC Option
In MVC this works for both GET and POST because [ValidateAntiForgeryToken] is not specified and is therefore not required.
MVC Controller
public class ShareController : Controller
{
public IActionResult MVCShareFromGet([FromQuery] string url, [FromQuery] string title)
{
return View("MVCShare", new Sharemodel(url, title));
}
public IActionResult MVCShareFromPost([FromForm] string url, [FromForm] string title)
{
return View("MVCShare", new Sharemodel(url, title));
}
For the POST method the properties are bound by [FromForm] whereas in the GET method it is [FromQuery]
MVCView:
@model DataCoord.Sharemodel
<p>Title: @Model.title</p>
<p>Url: @Model.url</p>
Blazor Option
In Blazor SSR Antiforgery is setup by default. Therefore in GET methods, it works, but with POST methods will fail.
Manifest:
"action": "/BlazorShareGet",
"method": "GET",
"params": {
"title": "title",
"text": "text",
"url": "url"
...
Blazor Page:
@page "/BlazorShareGet"
<p>Shared title: @title</p>
<p>Shared url: @url</p>
@code {
[SupplyParameterFromQuery]
string? title { get; set; }
[SupplyParameterFromQuery]
string? url { get; set; }
}
Manifest:
"action": "/BlazorSharePost",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url"
...
Blazor Page:
@page "/BlazorSharePost"
<p>Shared title: @title</p>
<p>Shared url: @url</p>
@code {
[SupplyParameterFromForm]
string? title { get; set; }
[SupplyParameterFromForm]
string? url { get; set; }
}
For the `POST` method the I try to bind the formData by `[SupplyParameterFromForm]` ???? but not sure if this is correct, whereas in the `GET` method it is `[SupplyParameterFromQuery]` which works.
I get the following ERROR:
A valid antiforgery token was not provided with the request. Add an antiforgery token, or disable antiforgery validation for this endpoint.
When I disable antiforgery entirely
app.MapRazorComponents<App>()
.DisableAntiforgery()
.AddInteractiveServerRenderMode()
I get
The POST request does not specify which form is being submitted. To fix this, ensure <form> elements have a @formname attribute with any unique value, or pass a FormName parameter if using <EditForm>.
I also tried [SupplyParameterFromForm], [SupplyParameterFromQuery], [Parameter], [CascadingParameter]
Note I don't have control over the request as it comes from third party / browser
Examining the request there is a matching matching .AspNetCore.Antiforgery Cookie present
Question
- How to disable antiforgery validation for this endpoint only?
- How to bind posted formData into Blazor Page
In my test adding this on the pagemodel, that is to do in a specific page handler way, is still controlled by the global filter. For a Blazor page, you can disable the antiforgery token through a specific action method using
[IgnoreAntiforgeryToken].Binding post data to Blazor page properties is not the typical use case since Blazor operates differently. You would typically handle form submission using C# methods and edit components with model binding.