зеркало из https://github.com/dotnet/aspnetcore.git
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:
Родитель
c8ef35df22
Коммит
f7b9f6aa0c
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -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;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче