Fix enhanced form handling use defalt enctype, honor enctype and formenctype (#52359)

* 1. fix enhanced form handling use default enctype when not specified
2. fix enhanced form handling honor form enctype attribute
3. fix enhanced form handling honor submit button formenctype attribute

* use SupplyParameterFromQuery to provide enctype and formenctype in the tests
This commit is contained in:
Surayya Huseyn Zada 2023-11-28 13:38:24 +01:00 коммит произвёл GitHub
Родитель c8ef35df22
Коммит f7b9f6aa0c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 80 добавлений и 4 удалений

2
src/Components/Web.JS/dist/Release/blazor.web.js сгенерированный поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -31,6 +31,8 @@ Note that we don't reference NavigationManager.ts from NavigationEnhancement.ts
different bundles that only contain minimal content.
*/
const acceptHeader = 'text/html; blazor-enhanced-nav=on';
let currentEnhancedNavigationAbortController: AbortController | null;
let navigationEnhancementCallbacks: NavigationEnhancementCallbacks;
let performingEnhancedPageLoad: boolean;
@ -140,15 +142,28 @@ function onDocumentSubmit(event: SubmitEvent) {
formData.append(submitterName, submitterValue);
}
const urlSearchParams = new URLSearchParams(formData as any).toString();
if (fetchOptions.method === 'get') { // method is always returned as lowercase
url.search = new URLSearchParams(formData as any).toString();
url.search = urlSearchParams;
// For forms with method=get, we need to push a URL history entry equivalent to how it
// would be pushed for a native <form method=get> submission. This is also equivalent to
// how we push a URL history entry before starting enhanced page load on an <a> click.
history.pushState(null, /* ignored title */ '', url.toString());
} else {
fetchOptions.body = formData;
// Setting request body and content-type header depending on enctype
const enctype = event.submitter?.getAttribute('formenctype') || formElem.enctype;
if (enctype === 'multipart/form-data') {
// Content-Type header will be set to 'multipart/form-data'
fetchOptions.body = formData;
} else {
fetchOptions.body = urlSearchParams;
fetchOptions.headers = {
'content-type': enctype,
// Setting Accept header here as well so it wouldn't be lost when coping headers
'accept': acceptHeader
};
}
}
performEnhancedPageLoad(url.toString(), /* interceptedLink */ false, fetchOptions);
@ -174,7 +189,7 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
headers: {
// Because of no-cors, we can only send CORS-safelisted headers, so communicate the info about
// enhanced nav as a MIME type parameter
'accept': 'text/html; blazor-enhanced-nav=on',
'accept': acceptHeader,
},
}, fetchOptions));
let isNonRedirectedPostToADifferentUrlMessage: string | null = null;

Просмотреть файл

@ -1433,6 +1433,36 @@ public class FormWithParentBindingContextTest : ServerTestBase<BasicTestAppServe
Assert.Contains(logs, log => log.Message.Contains("A form cannot be enhanced when its target is different from the default value \\\"_self\\\"."));
}
[Fact]
public void FormEnctypeEqualsDefaultWhenNotSpecified()
{
GoTo("forms/form-with-enctype-and-submit-button-with-formenctype");
Browser.Exists(By.Id("submit-button")).Click();
Browser.Equal("application/x-www-form-urlencoded", () => Browser.Exists(By.Id("content-type")).Text);
}
[Fact]
public void FormEnctypeSetsContentTypeHeader()
{
GoTo("forms/form-with-enctype-and-submit-button-with-formenctype?enctype=multipart/form-data");
Browser.Exists(By.Id("submit-button")).Click();
Browser.Contains("multipart/form-data", () => Browser.Exists(By.Id("content-type")).Text);
}
[Fact]
public void SubmitButtonFormenctypeAttributeOverridesEnhancedFormEnctype()
{
GoTo("forms/form-with-enctype-and-submit-button-with-formenctype?enctype=text/plain&formenctype=application/x-www-form-urlencoded");
Browser.Exists(By.Id("submit-button")).Click();
Browser.Equal("application/x-www-form-urlencoded", () => Browser.Exists(By.Id("content-type")).Text);
}
// Can't just use GetAttribute or GetDomAttribute because they both auto-resolve it
// to an absolute URL. We want to be able to assert about the attribute's literal value.
private string ReadFormActionAttribute(IWebElement form)

Просмотреть файл

@ -0,0 +1,31 @@
@page "/forms/form-with-enctype-and-submit-button-with-formenctype"
@using Microsoft.AspNetCore.Components.Forms
@inject IHttpContextAccessor HttpContextAccessor
<h1>Form with enctype and Submit Button with formenctype</h1>
<form id="form" data-enhance method="post" enctype="@Enctype" @onsubmit="Submitted" @formname="someform">
<AntiforgeryToken />
<input id="submit-button" type="submit" formenctype="@Formenctype" />
</form>
@if (_submitted)
{
<p>Http request ContentType: <span id="content-type">@_contentType</span></p>
}
@code {
bool _submitted = false;
private string? _contentType;
[SupplyParameterFromQuery] public string? Enctype { get; set; }
[SupplyParameterFromQuery] public string? Formenctype { get; set; }
public void Submitted()
{
_submitted = true;
var httpContext = HttpContextAccessor.HttpContext;
_contentType = httpContext?.Request.ContentType;
}
}