WebView2Feedback
WebView2Feedback copied to clipboard
Unable to cast to Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Cookie
I am using Visual Studio 2019 with a VB.Net application and DLLs that target .NET Framework 4.8 These components use the WebBrowser control and I'm now trying to convert it to use the WebView2 control I have installed the Canary Channel MicrosoftEdgeSetupCanary.exe file version 1.3.153.53 and I'm using NuGet WebView2 version 1.0.1054.31 Currently I'm trying to use WebView21.CoreWebView2.CookieManager.GetCookiesAsync(m_loginHandler.BaseUrlPath) to retrieve the cookies that the WebBrowser control used to give me. The List(Of CoreWebView2Cookie) returned has 1 item in it but when I try and access the cookie name & value I get
System.NotImplementedException
HResult=0x80004001
Message=Unable to cast to Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Cookie.
This may happen if you are using an interface not supported by the version of the WebView2 Runtime you are using.
For instance, if you are using an experimental interface from an older SDK that has been modified or removed in a newer runtime.
Or, if you are using a public interface from a newer SDK that wasn't implemented in an older runtime.
For more information about WebView2 versioning please visit the following: https://docs.microsoft.com/microsoft-edge/webview2/concepts/versioning
Source=Microsoft.Web.WebView2.Core
StackTrace:
at Microsoft.Web.WebView2.Core.CoreWebView2Cookie.get__nativeICoreWebView2Cookie()
at Microsoft.Web.WebView2.Core.CoreWebView2Cookie.get_Name()
at Thunderhead.Web.LoginHandler.UpdateCookies(CookieCollection httpCookies) in C:\source.net\WebView\VB.NET\ThWeb\Login\LoginHandler.vb:line 237
I'm trying the following approach to get the html source and the cookies; the html source comes back perfectly.
Private WithEvents m_htmlSourceTimer As Timers.Timer
Private m_htmlSourceTask As Threading.Tasks.Task(Of String)
Private m_htmlSource As String
Private WithEvents m_getCookiesTimer As Timers.Timer
Private m_getCookiesTask As Threading.Tasks.Task(Of List(Of CoreWebView2Cookie))
Private WithEvents m_metaDataCheckTimer As Timers.Timer
Private Sub NavigationCompleted(ByVal sender As Object, ByVal e As EventArgs)
EnableTimers()
End Sub
Private Sub EnableTimers()
If m_domContentedLoaded Then
If m_htmlSourceTimer Is Nothing Then
m_htmlSourceTimer = NewTimer()
End If
If Not m_htmlSourceTimer.Enabled Then
m_htmlSourceTask = WebView21.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML;")
m_htmlSourceTimer.Start()
End If
If m_getCookiesTimer Is Nothing Then
m_getCookiesTimer = NewTimer()
End If
If Not m_getCookiesTimer.Enabled Then
m_getCookiesTask = WebView21.CoreWebView2.CookieManager.GetCookiesAsync(m_loginHandler.BaseUrlPath)
m_getCookiesTimer.Start()
End If
End If
End Sub
Private Function NewTimer() As Timers.Timer
Dim result As New Timers.Timer
result.Interval = 250
result.AutoReset = True
Return result
End Function
Private Sub CookieAndHtmlSourceTimerElapsed(ByVal sender As Object, ByVal e As EventArgs) Handles m_htmlSourceTimer.Elapsed, m_getCookiesTimer.Elapsed
If m_htmlSourceTask.IsCompleted Then
m_htmlSourceTimer.Stop()
m_htmlSource = WebView2Helper.WebViewHTML(m_htmlSourceTask.Result)
End If
If m_getCookiesTask.IsCompleted Then
m_getCookiesTimer.Stop()
m_loginHandler.WebView2Cookies = m_getCookiesTask.Result
End If
If m_htmlSourceTask.IsCompleted AndAlso m_getCookiesTask.IsCompleted Then
If m_metaDataCheckTimer Is Nothing Then
m_metaDataCheckTimer = NewTimer()
End If
If Not m_metaDataCheckTimer.Enabled Then
m_metaDataCheckTimer.Start()
End If
End If
End Sub
Private Sub MetaDataCheckTimerElapsed(ByVal sender As Object, ByVal e As EventArgs) Handles m_metaDataCheckTimer.Elapsed
m_metaDataCheckTimer.Stop()
CheckForSalesforceLogin()
CheckForToken()
End Sub
I have a couple of questions
- Should I be using WebView21.CoreWebView2.CookieManager.GetCookiesAsync?
- If so, what am I doing wrong?
I've checked that I'm using the latest Canary version and I think that I am. I've also tried to use the NuGet WebView2 1.0.1083-prerelease and that has the same problem
Using the debugger the cookie shows up like this
Hey @JimWard2018 - You can verify the version of the runtime that your app is using by looking at the command-line of the launched child msedgewebview2.exe
process in Task Manager or Process Explorer, or by looking at CoreWebView2Environment.BrowserVersionString
.
Are you following this guidance to make your app use the Canary runtime? If not, it's possible it's using a really old stable WebView2 runtime or something. https://docs.microsoft.com/en-us/microsoft-edge/webview2/how-to/set-preview-channel
I'm unfamiliar with the approach you took for waiting for the completion of the async handlers, but you'll want to make sure that when you try to access the cookies you are doing so on the same thread you created the WebView2 on. It's possible the timer function is being run on a background thread.
- WebView21.CoreWebView2.Environment.BrowserVersionString is 98.0.1090.0 canary
- I have looked at that web page. I do not have the WebView evergreen runtime installed. According to https://www.nuget.org/packages/Microsoft.Web.WebView2 the latest prerelease is 1.0.1083-prerelease which I tried yesterday and that gave me the same problem as I said. I'm currently using the last stable build which is 1.0.1054.31. Both became available recently.
So is '98.0.1090.0 canary' compatible with WebView2 version 1.0.1054.31?
- It looks like I have a thread problem I introduced timers to get the html source of the loaded page. I was originally calling WebView21.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML;") in the NavigationCompleted event and that didn't work. It does work using a timer
I've been experimenting calling
WebView21.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML;")
in timers and using pool tasks
Task.Run(Of String)(Function() WebView21.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML;"))
In pool tasks I always get errors like
System.InvalidOperationException HResult=0x80131509 Message=CoreWebView2 can only be accessed from the UI thread. Source=Microsoft.Web.WebView2.WinForms StackTrace: at Microsoft.Web.WebView2.WinForms.WebView2.get_CoreWebView2()
but in timers I don't; so I'm assuming that I the timers are running in the UI thread where the WebView2 control was created
However I'm still getting the same error I reported yesterday and I believe that I am retrieving the cookies on the same thread as the WebView2 control with my timer solution
Thanks for the added info and confirmations! It might be worth trying to use a dispatcher to make sure the cookies are accessed from the WebView2 thread, but from what you've said above that seems unlikely to be the cause.
Looking at the screenshot, it also looks like you are saving the cookies list from the function into a separate variable, and then accessing it later. If you access the cookies right away when you get them, do you run into this error? I'm wondering if maybe the list of cookies is getting out of date.
I get the same error if I access the cookies straightaway
I don't understand what you mean by trying to use a dispatcher; could you elaborate?
This is what I had in mind with the dispatcher, although I realize now it's WPF and you are using Winforms :/ https://docs.microsoft.com/en-us/dotnet/api/system.windows.threading.dispatcher?view=windowsdesktop-6.0
Thanks for your help so far Nic.
I did explore the dispatcher option. I've changed my solution slightly to use
`
WebView21.BeginInvoke(Sub() m_getCookiesTask = WebView2Helper.GetCookies(WebView21, WebView21.Source.AbsoluteUri))
WebView21.BeginInvoke(Sub() m_htmlSourceTask = WebView2Helper.GetHtmlSource(WebView21))
`
to ensure I'm using the WebView21 thread but I still get the SystemNotImplemented exception whenever I try and access any of the cookie properties returned by
WebView21 .CoreWebView2.CookieManager.GetCookiesAsync(uri)
I guess it's an issue that needs fixing
Thanks for confirming. I've added this as a bug on our backlog. Have you also tried using "await"?
Yes, the helper functions that I call use await already
`
Public Shared Async Function GetCookies(ByVal wv As Microsoft.Web.WebView2.WinForms.WebView2, ByVal uri As String) As Task(Of List(Of CoreWebView2Cookie))
Return Await wv.CoreWebView2.CookieManager.GetCookiesAsync(uri)
End Function
Public Shared Async Function GetHtmlSource(ByVal wv As Microsoft.Web.WebView2.WinForms.WebView2) As Task(Of String)
Return Await wv.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML;")
End Function
`
Hi Nic,
Is there a bug reference number?
We have an internal bug link that's been appended to your original post, but otherwise we'll use this GH issue to track and add updates.
Hi @champnic Do you have any idea when this may be fixed? This is a show stopper for me now as I need those cookies for my application to log in.
No timeline on this issue.
Any updates? It seems I am facing the same problems with (Nuget) version 1.0.1938.49 inside a Windows Forms application.
WebView().ContinueWith(webViewTask =>
{
var webView = webViewTask.Result;
webView.Invoke(new Action(() =>
{
var cookieManager = webView.CoreWebView2.CookieManager;
webView.CoreWebView2.CookieManager.GetCookiesAsync(null).ContinueWith(
cookieListTask =>
{
var cookieList = cookieListTask.Result;
foreach (var t in cookieList)
{
Debug.WriteLine("Cookie: " + t.Domain + ", " + t.Name + ", " + t.Value);
}
}
);
}));
});
gives me
System.NotImplementedException: 'Unable to cast to Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Cookie.
This may happen if you are using an interface not supported by the version of the WebView2 Runtime you are using.
For instance, if you are using an experimental interface from an older SDK that has been modified or removed in a newer runtime.
Or, if you are using a public interface from a newer SDK that wasn't implemented in an older runtime.
For more information about WebView2 versioning please visit the following: https://learn.microsoft.com/microsoft-edge/webview2/concepts/versioning'
Update: awaiting the list instead of using a ContinueWith works... but why?
WebView().ContinueWith(webViewTask =>
{
var webView = webViewTask.Result;
webView.Invoke(new Action(async () =>
{
var cookieList = await webView.CoreWebView2.CookieManager.GetCookiesAsync(null);
foreach (var t in cookieList)
{
Debug.WriteLine("Cookie: " + t.Domain + ", " + t.Name + ", " + t.Value);
}
}));
});
Found the issue after getting
Exception thrown: 'System.NotImplementedException' in Microsoft.Web.WebView2.Core.dll Unable to cast to Microsoft.Web.WebView2.Core.Raw.ICoreWebView2_2.
The fix is to make sure you call whatever CoreWebView2
methods on the UI thread.
Just ran into the same issue. Would be more than nice, if the control would just throw an exception that the access is not done on the UI thread, to avoid looking for other sources for the error...