pipalot
pipalot

Reputation: 100

Set cookies for WebView2, in WebResourceRequested event

I am using the new WebView2 control (which is in developer preview) to replace the WebBrowser control in a Windows.Forms application.

The main reason for switching to the WebView2 control is that it is based on Chromium which works with WebRTC, whereas the WebBrowser control is powered by Internet Explorer which does not support WebRTC.

So the problem I am having is finding a way to set a cookie for the url that I want WebView2 to navigate to. In the past, when using WebBrowser, cookies could be set by calling InternetSetCookie before webBrowser.Navigate, but InternetSetCookie only works with Internet Explorer.

The cookie needs to be set for auth on a third party website, i.e. to prove to the website that my app is already logged in (done moments earlier by other parts of my app that are not using WebView2). The app successfully captures the auth cookie in the login response, but I just can't find how to pass the cookie back to the website when navigating with the WebView2 control. The WebView2 control is used to navigate to another page on the same website, where WebRTC is used.

https://github.com/MicrosoftEdge/WebViewFeedback/issues/4 explains that there is no quick mechanism provided for setting cookies in WebView2 yet, but suggests handling the WebResourceRequested event and then setting a cookie by amending the request.Header from inside the WebResourceRequested event handler.

So can anyone explain how to actually get the WebResourceRequested event to fire for a WebView2 please? I have tried this unsuccessfully:

        private string myUrl = "https://www.somedomain.com";

        private void WebView_CoreWebView2Ready(object sender, EventArgs e)
        {
            webView.CoreWebView2.AddWebResourceRequestedFilter(myUrl,CoreWebView2WebResourceContext.All);
            webView.CoreWebView2.WebResourceRequested += CoreWebView2_WebResourceRequested;
        }

        private void CoreWebView2_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs e)
        {
            Uri myUri = new Uri(myUrl);

            if (myUri.IsBaseOf(e.Request.RequestUri))
            {
                e.Request.Headers.Add("Cookie", cookieName, authToken);
            }
        }

The WebResourceRequested event never fires. I have tried getting it to fire by calling WebView2.Navigate, WebView2.CoreWebView2.Navigate and WebView2.Source, but none of them cause the WebResourceRequested event to fire.

The reason I am hooking up the event handler for WebResourceRequested from within WebView_CoreWebView2Ready event is because if you try to hook it up earlier (such as in form load), then CoreWebView2 will be null because it needs more time. I have successfully hooked up other events inside WebView_CoreWebView2Ready and they did fire (such as the NavigationStarting event).

Thanks.

Upvotes: 3

Views: 7949

Answers (2)

pipalot
pipalot

Reputation: 100

I discovered that the reason why I can't set cookies from within in the WebResourceRequested event handler is because that is a known bug which has already been reported to Microsoft here:

Unable to set headers in WebResourceRequested event handler

So in conclusion, my code does show what would be the correct way to add cookies, but it won't work until the bug is fixed by Microsoft.

I appreciate that this answer doesn't provide a workaround, but it does at least answer the question as to why the code currently fails to add a cookie.

Upvotes: 0

ZiggZagg
ZiggZagg

Reputation: 1427

The WebResource Requested event is only fired when an active filter for a resource exists and that filter is matched. You can add a filter that intercepts all request by using

WebView2.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);

To narrow down and update the filter of the actual requests you are interested in you can check args.Request.RequestUri inside of the CoreWebView2OnWebResourceRequested event.

By creating a local server and connecting to it via the WebView you can see that the WebView Preview does not copy the cookies when converting the .NET HttpRequest to a COM WebRequest that is used by the WebView itself.

using (HttpListener listener = new HttpListener())
{
    listener.Prefixes.Add($"http://localhost:8080/");
    listener.Start();

    while (listener.IsListening)
    {
        var context = await listener.GetContextAsync();

        using (var response = context.Response)
        {
            for (int i = 0; i < context.Request.Headers.Count; i++)
            {
                Console.WriteLine($"{context.Request.Headers.GetKey(i)} : {context.Request.Headers.Get(i)}");
            }
            
            using (var writer = new StreamWriter(response.OutputStream))
            {
                context.Response.ContentType = "text";
                writer.WriteLine("Test.");
                writer.Flush();
            }
        }
    }
}

You should probably file a bug report for the Edge WebView Preview.

Upvotes: 3

Related Questions