-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CoreWebView2
does not close stream content
#2513
Comments
Hey @oggy22 @victorthoang, just wanted to kindly follow-up on this issue, are there any updates by any chance? This is blocking our hot reload scenarios for Blazor Hybrid WinForms & WPF applications. |
Thanks for reaching out @TanayParikh - I've added this as a bug on our backlog, and also included @yildirimcagri who may have more insight here. Thanks! |
Hi @TanayParikh , I believe we made a fix in Edge 104 runtime about this, which should be in Beta now. Can you try the WebView2 runtimes with Edge Beta or Canary to see if this fixes your issue? |
@yildirimcagri do you happen to know if there's a 104 WebView2 runtime I can download? I'm only seeing 103 on the download page: Or would downloading the Edge Beta/Canary by itself (without a specific WebView2 standalone runtime) be sufficient? |
You can download the Edge Beta which is 104 and then specify the environment variable WEBVIEW2_BROWSER_EXECUTABLE_FOLDER to the Edge Beta installation directory and WebView2 will use that runtime. |
Overview: https://docs.microsoft.com/en-us/microsoft-edge/webview2/how-to/set-preview-channel You'll need the version info as well, as that's the folder that contains the You can also try setting the environment variable within your app. |
Yes, checking the user agent is sufficient. Sounds like the issue wasn't resolved in your case, so we'll take another look (Cagri is out of the office for a bit). Thanks! |
Hey folks, just wanted to follow-up on this as it's blocking several user scenarios. Edit: cc/ @yildirimcagri |
Hi @TanayParikh, MemoryStream mStream = new MemoryStream();
fileStream.CopyTo(mStream);
fileStream.Close(); We are trying better solutions. If you have any problems, please let me konw. |
Thanks @plantree, appreciate the investigation & looking forward to hearing more! We'd considered the |
Sorry for the confusion, the bug we had fixed was related to the WebView2 in fact leaking the stream object until navigating away. Could you rely on the |
Closing the stream on navigation completion could potentially be problematic in the event resources are loaded at a later point dynamically, and the stream is already closed. This also requires the client to maintain a reference to (every) stream the client sends to the CoreWebView2, till it's possible to close out. Given this, we'd prefer to not go down this particular path.
Can you please provide some more details about this. When is that possible / what considerations come into play here? Is the As a side note; we're also running into another file locking issue here: dotnet/maui#9197 This is using the WinRT API which uses a this is different from this issue (#2513) which is focused on this api using Initially, we didn't see the same locking behavior in .NET MAUI (WinRT / |
The main consideration is performance. We read the stream in a background thread in native code so the UI thread is not blocked on a network request. However, if the .NET stream is closed before the background thread could read it, we cannot read it from native side. Ideally, we would want to use the In the other issue you mentioned, it doesn't seem like the WebView2 is in play as you are copying the stream to a MemoryStream and passing that instead, if I understood right? |
Could you kindly clarify what should means in this context. What scenarios could we inadvertently close the stream before reading?
To confirm, it's not possible to just close the stream on the native side because the Close API isn't available on
Instead of providing this as a public API for consumption by frameworks/clients, could this instead be done internally within the
We (very) recently stopped copying the stream, but this issue still persists: dotnet/maui#9254 Given the stream is now sent directly to the CoreWebView2 could this be related? |
Since WebView2 reads the stream asynchronously after the app handles the
delegate(object sender, CoreWebView2WebResourceRequestedEventArgs args) {
using (MemoryStream ms = new MemoryStream(file)) {
response = webViewEnvironment.CreateWebResourceResponse(200, "OK", "", ms);
args.response = response;
}
} unfortunately, this doesn't work as the WebView2 will attempt to read
Automatically closing the stream from WebView2's side would be a breaking change of behavior. Some apps may have been coded in a way to rely on reusing the streams they provide for multiple
In that case, I agree these issues would be related. |
Hi, circling back on this with a fresh mind, I can think of a simpler workaround to this problem. When WebView2 reads the WebResourceResponse data stream, it reads it until the end or the Read fails, and does not have any further use to it afterwards. class ManagedStream : Stream {
public ManagedStream(Stream s)
{
s_ = s;
}
public override bool CanRead => s_.CanRead;
public override bool CanSeek => s_.CanSeek;
public override bool CanWrite => s_.CanWrite;
public override long Length => s_.Length;
public override long Position { get => s_.Position; set => s_.Position = value; }
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
return s_.Seek(offset, origin);
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
int read = 0;
try
{
read = s_.Read(buffer, offset, count);
if (read == 0)
{
s_.Dispose();
}
} catch (Exception e)
{
s_.Dispose();
throw e;
}
return read;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
private Stream s_;
} If you wrap the stream you are passing to WebView with this ManagedStream class, this should ensure that the stream is disposed when WebView is done with it. This should hopefully be a simpler workaround. |
Hey @yildirimcagri, thanks for the comment. That's exactly the workaround we're using presently 😄 |
Ohh great, I must have missed that reference. :) To prevent any breaking changes, I think we will retain the behavior here, so we will add this workaround to our guidance with regarding the streams passed to WebView2 that need to be disposed. Closing this issue for now, please let me know if you need a different resolution here. |
If this workaround is the long term "fix", why not create an official class in the SDK, say |
Description
In Blazor WebView (Blazor Hybrid on WinForms & WPF), a
content
stream given toCoreWebView2
isn't closed byCoreWebView2
after serving the content.The open stream that was sent to
CoreWebView2
leads to Visual Studio being unable to save updates to that file._coreWebView2Environment!.CreateWebResourceResponse
:https://github.com/dotnet/maui/blob/d6bc1ca6ff47d49d0ce2d254df7416f0aee52e68/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs#L307
_webview.CoreWebView2.WebResourceRequested
:https://github.com/dotnet/maui/blob/d6bc1ca6ff47d49d0ce2d254df7416f0aee52e68/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs#L256
Repro Steps
Note: if this is expected behavior for CoreWebView2 to not close the content stream, when is it appropriate for the callee to close out the stream? Is there a lifecycle event we can hook into to know when it's acceptable to close the stream?
Additional Context:
Version
SDK: Latest
Runtime: Latest
Framework: WinForms and WPF
OS: Windows 11
AB#40512420
The text was updated successfully, but these errors were encountered: