question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add a property on WebView to set additional headers

See original GitHub issue

Description

On the platform specific WebView you can launch the browser view with some additional headers set (for example for authentication). Maui WebView doesn’t have this capability at the moment and you must override handlers mapping for each platform

Public API Changes

<WebView Source={Binding Url} Headers={Binding Headers} />

Intended Use-Case

Simplify webview automatic authentication

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:4
  • Comments:13 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
manuelelucchicommented, Sep 10, 2022

Hi @Scriptman, currently I did something like this, but it’s far from ideal

public class AuthenticatedWebView : WebView
{
	static AuthenticatedWebView()
	{
		Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(nameof(IWebView.Source), (handler, view) =>
		{
			if (view is AuthenticatedWebView webView)
			{
				var url = webView.Url!;
#if ANDROID
                var headers = new Dictionary<string, string>
                {
                    ["Authorization"] = $"Bearer {webView.Token}"
                };
                handler.PlatformView.LoadUrl(url, headers);
#elif iOS
                var webRequest = new NSMutableUrlRequest(new NSUrl(url));
                var headerKey = new NSString("Authorization");
                var headerValue = new NSString($"Bearer {webView.Token}");
                var dictionary = new NSDictionary(headerKey, headerValue);
                webRequest.Headers = dictionary;

                handler.PlatformView.LoadRequest(webRequest);
#else
				throw new NotImplementedException();
#endif
			}

		});
	}

	public static readonly BindableProperty TokenProperty = BindableProperty.Create("Token", typeof(string), typeof(AuthenticatedWebView), "");

	public string? Token
	{
		get => GetValue(TokenProperty) as string;
		set => SetValue(TokenProperty, value);
	}

	public static readonly BindableProperty UrlProperty = BindableProperty.Create("Url", typeof(string), typeof(AuthenticatedWebView), "");
	public string? Url
	{
		get => GetValue(UrlProperty) as string;
		set => SetValue(UrlProperty, value);
	}
}
3reactions
HavenDVcommented, Mar 6, 2023

Here is the code that is tested and allows you to add additional headers to the WebView on major platforms

using System.Collections;
using DependencyPropertyGenerator;
using Microsoft.Maui.Handlers;
using WebView = Microsoft.Maui.Controls.WebView;
#if IOS || MACCATALYST
using Foundation;
#endif

namespace XamlExtensions;

[AttachedDependencyProperty<ICollection, WebView>("AdditionalHttpHeaders",
	Description = "Does not overwrite existing headers. Use ArrayList and DictionaryEntry to define headers from xaml.")]
public static partial class WebViewExtensions
{
	static partial void OnAdditionalHttpHeadersChanged(WebView webView, ICollection? newValue)
	{
		if (newValue is null)
		{
			return;
		}
		
		var headers = newValue
			.OfType<object>()
			.Select(static value => value switch
			{
				KeyValuePair<string,string> pair => pair,
				DictionaryEntry entry => new KeyValuePair<string,string>((string)entry.Key, entry.Value as string ?? string.Empty),
				_ => throw new NotImplementedException("This Header collection value is not supported."),
			})
			.ToDictionary(
				static pair => pair.Key,
				static pair => pair.Value);
		
		WebViewHandler.Mapper.AppendToMapping(nameof(IWebView.Source),
#if WINDOWS
			async
#endif
			(handler, view) =>
		{
			if (view.Source is not UrlWebViewSource urlWebViewSource)
			{
				return;
			}
			
			var url = urlWebViewSource.Url;
#if ANDROID
			handler.PlatformView.LoadUrl(url: url, additionalHttpHeaders: headers);
#elif IOS || MACCATALYST
			handler.PlatformView.LoadRequest(request: new NSMutableUrlRequest(new NSUrl(url))
			{
				Headers = NSDictionary.FromObjectsAndKeys(
					headers.Keys.Select(static key => (NSObject)new NSString(key)).ToArray(),
					headers.Values.Select(static value => (NSObject)new NSString(value)).ToArray())
			});
#elif WINDOWS
			await handler.PlatformView.EnsureCoreWebView2Async();

			var request = handler.PlatformView.CoreWebView2.Environment.CreateWebResourceRequest(
				uri: url,
				Method: "GET",
				postData: Stream.Null.AsRandomAccessStream(),
				Headers: null);
			foreach (var (key, value) in headers)
			{
				request.Headers.SetHeader(key, value);
			}

			handler.PlatformView.CoreWebView2.NavigateWithWebResourceRequest(request);
#else
			throw new NotImplementedException();
#endif
		});
	}
}

Android platform will need to set WebViewHandler.PlatformViewFactory before using WebView for the first time

#if ANDROID
	WebViewHandler.PlatformViewFactory =
		static handler => new Android.Webkit.WebView(context: handler.Context)
		{
			Settings =
			{
				JavaScriptEnabled = true,
			},
		};
#endif

Usage(Can also be used with IDictionary<string, string> in MVVM):

<WebView Source="https://manytools.org/http-html-text/http-request-headers">
    <extensions:WebViewExtensions.AdditionalHttpHeaders>
        <collections:ArrayList>
            <collections:DictionaryEntry Key="MyHeader" Value="MyHeaderValue" />
        </collections:ArrayList>
    </extensions:WebViewExtensions.AdditionalHttpHeaders>
</WebView>
Read more comments on GitHub >

github_iconTop Results From Across the Web

Add custom headers to WebView resource requests - android
First you need to create method, which will be returns your headers you want to add to request: private Map<String, String> getCustomHeaders() { ......
Read more >
Add custom headers to WebView resource requests - android
Android : Add custom headers to WebView resource requests - android [ Beautify Your Computer : https://www.hows.tech/p/recommended.html ] ...
Read more >
WKWebView setValue forHTTPHeaderField problem
I'm looking for a solution to navigate a URL with header's variable. I know we can create a request and setValue with forHTTPHeaderField...
Read more >
Adding Authorization Header in Web View - Xamarin Explorer
I put it on OnElementChanged method, as a result, whenever the user navigate to other page in web view, causing the url changed,...
Read more >
WebView | Android Developers
Build apps that give your users seamless experiences from phones to tablets, watches, and more. ... Learn to build for your use case...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found