Closed RickStrahl closed 2 weeks ago
Thanks for the bug report @RickStrahl! I've added this to our backlog.
Is there any word on whether this will be addressed?
Tested today with latest version and found this still doesn't work. Confirmed that:
.Content
property is null. @champnic Ping! Any progress or at least confirmation that this is a bug and will get addressed in the future? Or a workaround?
Thanks for the ping Rick. @yildirimcagri do you have any info on this issue?
I also ran into exactly this issue. Ran into it when using WebView2 from C++ but also reproduced it in C# WinForms.
This can be reproduced with the following JavaScript code:
const obj = { hello: "world" };
const blob = new Blob([JSON.stringify(obj, null, 2)], {
type: "application/json",
});
const data = new FormData();
data.append("val1", "val1");
data.append("blob", blob);
const req = new XMLHttpRequest();
req.addEventListener("load", () => {
alert("Received: " + req.responseText);
});
req.open("POST", "https://post.asset/");
req.send(data);
And the following C# code:
this.webView2Control.CoreWebView2.WebResourceRequested += CoreWebView2_WebResourceRequested;
this.webView2Control.CoreWebView2.AddWebResourceRequestedFilter("https://post.asset/", CoreWebView2WebResourceContext.All);
private void CoreWebView2_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs eventArgs)
{
System.IO.Stream content = eventArgs.Request.Content;
if(content != null)
{
byte[] bytes = new byte[content.Length + 10];
content.Read(bytes, 0, (int)content.Length);
var stringData = System.Text.Encoding.Default.GetString(bytes);
MessageBox.Show("Received: " + stringData);
}
else
{
MessageBox.Show("No content stream :(");
}
eventArgs.Response = this.webView2Control.CoreWebView2.Environment.CreateWebResourceResponse(null, 200, "OK", "");
}
The attached solution contains a running sample: WebView2BinaryResourceIssue.zip
Thanks for the sample code for this. I missed the earlier ping about this, but I will prioritize this issue now.
Any update on this @yildirimcagri? @champnic?
Are there any plans to address this issue @yildirimcagri-msft?
Same for me. The WebResourceRequested handler is the only way to intercept/filter requests and this bug makes this impossible. @yildirimcagri-msft , you say you will prioritize this issue for the last year or so and still nothing. Will it be possible finally this issue to be solved ?
I am also the same. This issue has caused my solution to be unable to proceed due to this bug. Will this issue be resolved? Looking forward to your reply
@champnic @yildirimcagri-msft Is there any status update on this? Is there a workaround? Thanks.
We are in the same situation, any updates? Is there a workaround to avoid this problem?
Is there any updates? Or some alternatives?
Here is a temporary solution:
const formData= new FormData();
formData.append("val1", "val1");
formData.append("blob", blob);
const req = new Request(uploadUrl, {
method: "POST",
body: formData,
});
const buffer = await req.arrayBuffer();
const headers = req.headers;
const response = await fetch(uploadUrl,{
method:"POST",
body:buffer,
headers
});
By transmut multi-part data into arrayBuffer, we can access the request body though Request.Content
.
Here is a temporary solution:
const formData= new FormData(); formData.append("val1", "val1"); formData.append("blob", blob); const req = new Request(uploadUrl, { method: "POST", body: formData, }); const buffer = await req.arrayBuffer(); const headers = req.headers; const response = await fetch(uploadUrl,{ method:"POST", body:buffer, headers });
By transmut multi-part data into arrayBuffer, we can access the request body though
Request.Content
.
Seems this workaround works, but not in my scenario, I'm appending to the body not a blob but a file from an input type file for upload it. Using arrayBuffer() the file is loaded in memory, and for upload of large files that's not good...
Any updates? This bug caused a complete reengineering of our solution. It's not possible do a multi-part POST request for uploading file!
From what I can see, this is being worked on. We will post any updates here.
Been watching this bug for a long time too. But this bug is not in Webview2, it is Chromium itself that has this problem. It can be seen in Devtools.
Even if you connect via DevTools Protocol FetchRequestPaused, the Post request will be empty.
BUT!
I found a workaround. The full Post request can be seen through:
DevTools Protocol Network.requestWillBeSent
It's a miracle! Next is a simple code:
protocol initialization:
private Dictionary<string, string> HelpPostNetworkData = new();
private async void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
await WebView.CoreWebView2.CallDevToolsProtocolMethodAsync("Network.enable", "{}");
WebView.CoreWebView2.GetDevToolsProtocolEventReceiver("Network.requestWillBeSent").DevToolsProtocolEventReceived += WebView2_NetworkData;
}
Processing our data and saving the Postdata to the backup dictionary
private async void WebView2_NetworkData(object sender, CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
{
if (e == null || e.ParameterObjectAsJson == null)
{
return;
}
var doc = JsonDocument.Parse(e.ParameterObjectAsJson);
string payload = "{\"requestId\":\"" + doc.RootElement.GetProperty("requestId") + "\"}";
string bodyResponse;
string nowurl = doc.RootElement.GetProperty("request").GetProperty("url").ToString().ToLower();
if (doc.RootElement.GetProperty("request").GetProperty("method").ToString().Equals("post", StringComparison.OrdinalIgnoreCase))
{
try
{
bodyResponse = await WebView.CoreWebView2.CallDevToolsProtocolMethodAsync("Network.getRequestPostData", payload);
}
catch
{
return;
}
if (!string.IsNullOrEmpty(bodyResponse))
{
HelpPostNetworkData.Remove(nowurl);
HelpPostNetworkData.Add(nowurl, bodyResponse);
}
}
}
And now you can use this dictionary to work and check if Content == null in CoreWebView2WebResourceResponseReceived, then take data from the dictionary at the URL
I tried leonidukg's comment. It works, but when the post data include file, the file values will omit. So, it still need to fix.
I tried leonidukg's comment. It works, but when the post data include file, the file values will omit. So, it still need to fix.
You are right because Network.requestWillBeSent is executed BEFORE it sends all the data. And most likely the file download is not included in this check. I only need the field names to work, the values are not important.
p.s. I have corrected my code to prevent requests from hanging by accident.
I tried leonidukg's comment. It works, but when the post data include file, the file values will omit. So, it still need to fix.
You are right because Network.requestWillBeSent is executed BEFORE it sends all the data. And most likely the file download is not included in this check. I only need the field names to work, the values are not important.
p.s. I have corrected my code to prevent requests from hanging by accident.
I mean file upload. you can't get upload file content.
Once again encountered this problem and even my workaround won't help. So I had to look for another one, but I already had a function to modify HTML code and I was surprised to see PostData perfectly through this function. So who needs not just POST variables, but their content, use it:
private Dictionary<string, string> HelpPostNetworkData = new();
private async void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
WebView.CoreWebView2.GetDevToolsProtocolEventReceiver("Fetch.requestPaused").DevToolsProtocolEventReceived += WebView2_FetchRequestPaused;
await WebView.CoreWebView2.CallDevToolsProtocolMethodAsync("Fetch.enable", "{\"patterns\":[{\"urlPattern\":\"*\", \"requestStage\":\"Response\"}]}");
}
private async void WebView2_NetworkData(object sender, CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
{
if (e == null || e.ParameterObjectAsJson == null)
{
return;
}
var doc = JsonDocument.Parse(e.ParameterObjectAsJson);
string payload = "{\"requestId\":\"" + doc.RootElement.GetProperty("requestId") + "\"}";
string nowurl = doc.RootElement.GetProperty("request").GetProperty("url").ToString().ToLower();
if (doc.RootElement.TryGetProperty("responseHeaders", out JsonElement JSHeadersPost))
{
if (!JSHeadersPost.ToString().Contains("application/json", StringComparison.OrdinalIgnoreCase))
{
if (doc.RootElement.GetProperty("request").GetProperty("method").ToString().Equals("post", StringComparison.OrdinalIgnoreCase))
{
if (doc.RootElement.GetProperty("request").TryGetProperty("postData", out JsonElement JSbodyResponse))
{
HelpPostNetworkData.Remove(nowurl);
HelpPostNetworkData.Add(nowurl, JSbodyResponse.ToString());
}
}
}
}
await Application.Current.Dispatcher.InvokeAsync(() => { try { WebView.CoreWebView2.CallDevToolsProtocolMethodAsync("Fetch.continueRequest", payload); } catch { } });
}
Hello, this should be working now. Please reactivate if it is not.
As of which release?
So I'm looking at this in the latest release build and I'm not sure what I'm looking at or how I'm supposed to get at this data.
It looks like Request content returns some sort of stream, but the stream is way too small - it doesn't contain the upload data:
and indeed when I try to read the actual file content it's always empty. I do get the headers now.
Here's what I do:
That works to give me the variables - content type, length of content, filename. But the data is always 0 length which makes sense since the incoming data does not reflect the full body that includes the full binary file size.
From the looks of it the payload captured is only the non-binary header data.
Using latest release SDK 1.0.2849.39
I have an application that captures Web Request data for later playback (WebSurge). This works great for standard text based content be it API requests or captured form data - the data gets captured into the Request stream and I can grab it out of there. Works great.
However, if the data is multi-part form data with binary data, the
Request.Content
is always null:In contrast, here is a POST request with standard form data which does work and returns a
Request.Content
stream:So for some reason it looks if the data is multi-part or contains binary data the request content is not provided.
AB#38186390