Search code examples
javascriptc#wpffunctionwebview2

WebView2 (WPF) - Load website from local folder and call C# Function and call JS Function


I am making a WPF application use WebView2.

There will be an installer that will installer the WPF application in a folder and will also download and write the website into a subfolder of the installation directory. Such as this:

Installation Directory
├───Website
│   ├───index.css
│   └───index.html
└───WPF Self Contained EXE

The WebView2 will load the website using this (I think): webView.CoreWebView2.Navigate(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Website");

This should load index.html and all the files it references such as index.css.

Now my main concern is that how do I call a JavaScript function from C#. So far after googling I have only found ways for WebView1. And I couldn't find anything about calling a C# method from JavaScript.

So three things:

  1. Is this webView.CoreWebView2.Navigate(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Website"); correct for loading a website from a local folder?
  2. How would I call a JavaScript function and pass an C# object to it from a C# method.
  3. How would I call a C# function from the JavaScript script?

Is this even possible?

Thanks.


Solution

  • Using file URI

    I'm not sure if AppDomain.CurrentDomain.BaseDirectory will always get you the correct path. You can use something like the following:

    string exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
    string exeFolder = System.IO.Path.GetDirectoryName(exePath);
    string websiteFolder = Path.Combine(exeFolder, "website");
    string htmlPath = Path.Combine(websiteFolder, "index.html");
    
    webView.CoreWebView2.Navigate(htmlPath);
    

    You must include the path to the index.html itself and not just the folder containing the index.html.

    Normally Navigate should take a URI, but if you provide a Windows file path instead it will convert it to a file URI for you and should work.

    File URIs have some limitations when trying to incorporate http(s) URIs and other web platform features that require https.

    Using a virtual HTTPS URI

    If you hit issues using file URIs you can use CoreWebView2.SetVirtualHostNameToFolderMapping to map a Windows file path to a fake HTTPS hostname:

    string exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
    string exeFolder = System.IO.Path.GetDirectoryName(exePath);
    string websiteFolder = Path.Combine(exeFolder, "website");
    
    webView.CoreWebView2.SetVirtualHostNameToFolderMapping("appassets.example", websiteFolder, CoreWebView2HostResourceAccessKind.DenyCors);
    webView.CoreWebView2.Navigate("https://appassets.example/index.html");
    

    This will make a fake hostname 'appassets.example' that will map to your Windows file path. And since its HTTPS URIs you don't hit the same issues as you do with file URIs.

    Host objects in script

    For your questions 2 & 3 you can use CoreWebView2.AddHostObjectToScript. The current implementation of AddHostObjectToScript requires your C# classes to be specially marked. You can see it in the AddHostObjectToScript documentation.