Now, we can embed web content (HTML
, CSS
, and JavaScript
) in our native applications with Microsoft Edge WebView2
. Earlier, it was announced only for Win32 C/C++
apps but later, it was announced available for use in .NET 5
, .NET Core
, and .NET Framework
Windows Forms and WPF applications.
It uses the modern Microsoft Edge (Chromium) platform to host web content within native Windows applications.
In the future, the Evergreen
Microsoft recommendationWebView2
Runtime plans to ship with future releases of Windows. Deploy the Runtime with your production app until the Runtime becomes more universally available.
Power of Native
With growing presence of online world, desktop applications are pushed to use more of online like capabilities. Further, web solution also helps reuse most of the code across different platforms and easy change delivery. This is leading desktop applications more and more towards hybrid approach where best of both (native and web) can be leveraged.
Microsoft WebView2
comes to rescue. It helps build powerful applications with controlled access to native capabilities.
WebView2
uses the same process model as the Microsoft Edge browser. A browser process is associated with only one user data folder. A request process that specifies more than one user data folder is associated with the same number of browser processes.
More details about browser process model can be read here.
Microsoft – Managing user data folder
WebView2
apps create a user data folder to store data such as cookies, credentials, permissions, and so on. After creating the folder, your app is responsible for managing the lifetime of the user data folder, including clean up when the app is uninstalled
Microsoft has laid here some best practices for developing secure WebView2 application.
Distribution
When distributing your WebView2
app, ensure the backing web platform, the WebView2 Runtime, is present before the app starts.
By default, WebView2
is evergreen and receives automatic updates to stay on the latest and most secure platform.
- Evergreen Bootstrapper – a tiny installer that downloads the Evergreen Runtime matching device architecture and installs it locally.
- Evergreen Standalone Installer – a full-blown installer that can install the Evergreen Runtime in offline environment.
- Fixed Version – to select and package a specific version of the WebView2 Runtime with your application.
The
WebView2
Runtime is a redistributable runtime and serves as the backing web platform for WebView2 apps.
Download the runtime from here. Supported platforms are mentioned here.
Sample Application
I built a sample WPF application (runs on .NET Framework and not Core) to try WebView2
. This was to evaluate how comparatively older .NET applications would work out.
I tried to display my blog in the WPF application using a WebView2
control. Sample application had capabilities to post message to host application and back as well as hook events as per need.
public MainWindow()
{
InitializeComponent();
// NavigationEvents
webView.NavigationStarting += WebView_NavigationStarting; ;
webView.SourceChanged += WebView_SourceChanged;
webView.ContentLoading += WebView_ContentLoading;
webView.NavigationCompleted += WebView_NavigationCompleted;
// Embedded at CoreWebView2 level
InitializeOnceCoreWebView2Intialized();
}
/// <summary>
/// initialization of CoreWebView2 is asynchronous.
/// </summary>
async private void InitializeOnceCoreWebView2Intialized()
{
await webView.EnsureCoreWebView2Async(null);
// Hook other events
webView.CoreWebView2.FrameNavigationStarting += CoreWebView2_FrameNavigationStarting;
webView.CoreWebView2.HistoryChanged += CoreWebView2_HistoryChanged;
// For communication host to webview & vice versa
webView.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(\'Message from App to WebView2 on navigation!\'));");
}
/// <summary>
/// Web content in a WebView2 control may post a message to the host
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
// Retrieve message from Webview2
String uri = e.TryGetWebMessageAsString();
addressBar.Text = uri;
// Send message to Webview2
webView.CoreWebView2.PostWebMessageAsString(uri);
log.Content = $"Address bar updated ({uri}) based on WebView2 message!";
}
/// <summary>
/// Execute URL
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonGo_Click(object sender, RoutedEventArgs e)
{
try
{
Uri uri = new Uri(addressBar.Text);
if (webView != null && webView.CoreWebView2 != null)
{
webView.CoreWebView2.Navigate(uri.OriginalString);
}
}
catch (UriFormatException)
{
MessageBox.Show("Please enter correct format of url!");
}
}
/// <summary>
/// Allow only HTTPS calls
/// WebView2 starts to navigate and the navigation results in a network request.
/// The host may disallow the request during the event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
String uri = e.Uri;
if (!uri.StartsWith("https://"))
{
e.Cancel = true;
//MessageBox.Show("Only HTTPS allowed!");
// Inject JavaScript code into WebView2 controls at runtime
webView.CoreWebView2.ExecuteScriptAsync($"alert('{uri} is not safe, try an https link please.')");
}
}
Various events run when specific asynchronous actions occur to the content displayed in a WebView2
instance.
NavigationStarting | WebView2 starts to navigate and the navigation results in a network request. The host may disallow the request during the event. |
SourceChanged | The source of WebView2 changes to a new URL. The event may result from a navigation action that does not cause a network request such as a fragment navigation. |
ContentLoading | WebView starts loading content for the new page. |
HistoryChanged | The navigation causes the history of WebView2 to update. |
NavigationCompleted | WebView2 completes loading content on the new page. |
ProcessFailed | To react to crashes and hangs in the browser and renderer processes |
Close | To safely shut down associated browser and renderer processes |
Working with the sample application, I was able to display a webpage, intercept calls both ways and embed message/code to my need. It provides all the capabilities that seems to be needed for a stable web app display control.
Complete sample application can be downloaded from here: https://github.com/sandeep-mewara/WebView2WpfBrowserApp
Reference
https://developer.microsoft.com/en-us/microsoft-edge/webview2/
https://docs.microsoft.com/en-us/microsoft-edge/webview2/gettingstarted/wpf
https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution