Blank VebWiew2 widget if run from an IExternalCommand

Blank VebWiew2 widget if run from an IExternalCommand

ghensi
Enthusiast Enthusiast
2,191 Views
9 Replies
Message 1 of 10

Blank VebWiew2 widget if run from an IExternalCommand

ghensi
Enthusiast
Enthusiast

Background: I'm trying to use the Forge three legged authentication to get the user BIM 360 projects and documents.

 

I followed the LearnForge guide to create a .NET core web server, and added an endpoint that redirects to the OauthUrl (instead of only returning it as string), so that a client can simply call that endpoint to begin the authentication process.

 

In order to display the login window (and retrieve the cookie needed for further API requests), I want to use the WebView2 control inside a small WPF window.

I correctly installed the WebView2 runtime (just in case somebody asks).

I tried to build a simple stand-alone client and everything is fine, the app connects to my server and then the Autodesk login appears.

 

Inserting this logic inside a Revit plugin, though, results in a blank WebView2 widget:

r_dV7EDK_1-1618405630585.png

 

I'm still learning c#/.NET, and I'm a newbie when it comes to WPF, did I miss something?

 

This is the minimum code to reproduce the issue

Command class

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace TestAutodeskLoginPlugin {
  [TransactionAttribute(TransactionMode.Manual)]
  public class TestAdskLoginCmd : IExternalCommand {
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) {
      var loginDialog = new LoginWindow();
      loginDialog.ShowDialog();
      //do something with loginDialog.Cookie;
      return Result.Succeeded;
    }
  }
}

 

The window Xaml

<Window x:Class="TestAutodeskLoginPlugin.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
        mc:Ignorable="d"
        Title="Autodesk Login" Height="450" Width="400">
  <DockPanel>
    <TextBlock Margin="10" DockPanel.Dock="Top">Please log in to BIM 360</TextBlock>
    <wv2:WebView2 Name="webView" Source="http://localhost:3000/api/forge/oauth/login"/>
  </DockPanel>
</Window>

 

The window logic (to get the cookie from webview2)

using Microsoft.Web.WebView2.Core;
using System.Windows;

namespace TestAutodeskLoginPlugin {
  /// <summary>
  /// Window that shows the Autodesk Bim360 login
  /// </summary>
  public partial class LoginWindow : Window {
    private const string FORGE_COOKIE = "ForgeApp";
    public string Cookie { get; set; }

    public LoginWindow() {
      InitializeComponent();
      webView.NavigationCompleted += GetForgeCookies;
    }

    private async void GetForgeCookies(
      object sender, CoreWebView2NavigationCompletedEventArgs args
    ) {
      if(args.IsSuccess && webView.Source.Host == "http://localhost:3000") {
        CoreWebView2 cwv = webView.CoreWebView2;
        var cookies = await cwv.CookieManager.GetCookiesAsync(cwv.Source);
        var forgeCookie = cookies.Find(c => c.Name == FORGE_COOKIE);
        if(forgeCookie != default) {
          Cookie = forgeCookie.Value;
          Close();
        }
      }
    }
  }
}

 

 

0 Likes
Accepted solutions (1)
2,192 Views
9 Replies
Replies (9)
Message 2 of 10

jeremy_tammik
Alumni
Alumni

This sounds more like a Forge question that a Revit API one.

 

If so, it would better be addressed through the standard Forge help channels:

 

https://forge.autodesk.com/en/support/get-help

  

That said, however, I do have a pointer to share with you which might be helpful after all.

 

Zhong Wu just shared a Revit 2022 utility to migrate Revit Worksharing models from BIM 360 Team to BIM 360 Docs, powered by the enhanced Revit 2022 Cloud Worksharing API:

 

https://forge.autodesk.com/blog/migrate-revit-worksharing-models-bim-360-team-bim-360-docs-powered-r...

 

I hope that will prove useful to you as well.

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 10

ghensi
Enthusiast
Enthusiast

Hi @jeremy_tammik ,

thanks for your reply.

 

The problem is not with Forge per se, but with WebView2 inside the Revit process, since I have the same problem with any URL I set as the starting page of the control.

You can reproduce it by replacing the XAML line

<wv2:WebView2 Name="webView" Source="http://localhost:3000/api/forge/oauth/login"/>

to something like 

<wv2:WebView2 Name="webView" Source="https://www.google.com"/>

 

You will need the Microsoft.Web.WebView2 package from nuGet (and the WebView2 runtime or a freview version of ms edge).

 

Regarding the forge part: unfortunately, the example you cited requires administrative rights to open a port in the windows firewall, in order to make the oauth callback work.

Since our users don't have admin rights, this is not feasible.

That's why I used the LearnForge example to create the server that handles the callback and I need to display the login window inside Revit to catch the cookie.

 

Thanks again for you help!

0 Likes
Message 4 of 10

jeremy_tammik
Alumni
Alumni

Looking for the most efficient way forward... is there any chance you could separate the login from the Revit add-in? Say, log in first in a separate process, and then run the add-in afterwards?

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 10

ghensi
Enthusiast
Enthusiast
Accepted solution

Thanks again @jeremy_tammik, that could be a good way to go; I also thought about spawning the login page inside the default browser and check its cookies (but its quite a bit of work to handle all the possible browsers...).

 

Eventually, since WebView2 is still in its infancy and is "the road less (or not at all) travelled" among this community, I fell back on the trusty CefSharp, and it works with minor modification (event handlers runs on a separated cef thread, so they need to dispatch to a method inside the plugin/window thread).

 

For future reference, this is the updated logic:

 

using CefSharp;
using System.Windows;

namespace TestAutodeskLoginPlugin {
  /// <summary>
  /// Window that shows the Autodesk Bim360 login
  /// </summary>
  public partial class LoginWindow : Window {
    private const string FORGE_COOKIE = "ForgeApp";
    private const string SERVER_URL = "http://localhost:3000";
    public string Cookie { get; set; }

    public LoginWindow() {
      InitializeComponent();
      Browser.LoadingStateChanged += PageLoadedHandler;
    }

    private async void GetCookie() {
      if(Browser.Address.StartsWith(SERVER_URL)) {
        var cookieManager = Cef.GetGlobalCookieManager();
        var cookies = await cookieManager.VisitUrlCookiesAsync(
          Browser.Address, true);
        var forgeCookie = cookies.Find(c => c.Name == FORGE_COOKIE);
        if(forgeCookie != default) {
          Cookie = forgeCookie.Value;
          Close();
        }
      }
    }

    private void PageLoadedHandler(
      object sender, LoadingStateChangedEventArgs args
    ) {
      if(!args.IsLoading) {
        Dispatcher.Invoke(() => GetCookie());
      }
    }
  }
}

 

of course, SERVER_URL should point to the base uri of a project created following the LearnForge tutorial, with the following added endpoint in the OAuthController class:

 

    [HttpGet]
    [Route("api/forge/oauth/login")]
    public IActionResult LoginRedirect() {
      return Redirect(GetOAuthURL());
    }

 

Of course, you need to add the CefSharp nuget package and use the ChromiumWebBrowser component in the XAML:

 

<Window x:Class="TestAutodeskLoginPlugin.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:cef="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
        mc:Ignorable="d"
        Title="Autodesk Login" Height="450" Width="400">
  <DockPanel>
    <TextBlock Margin="10" DockPanel.Dock="Top">Please log in to BIM 360</TextBlock>
    <cef:ChromiumWebBrowser x:Name="Browser" Address="http://localhost:3000/api/forge/oauth/login"/>
  </DockPanel>
</Window>

  

Message 6 of 10

jeremy_tammik
Alumni
Alumni

Brilliant. I am a great proponent of keeping it simple and not fighting the system. That sounds like an efficient way forward. Thank you for your appreciation and sharing your solution.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 7 of 10

ctoASWG6
Explorer
Explorer

also had that issue with the blank webview2.

After loooong (and frustrating) research, I found out, that in the most revit examples with wpf webview2 visual studio projects are configured, that forces revit to start in english.

ctoASWG6_0-1654158425681.png

 

But if you had installed the lasted edge in another language (for me its german) then the webview2 component remains blank.

After removing the "/language ENU" in debug settings, revit starts in system language (for me its german) and the component isn't blank anymore...

 

0 Likes
Message 8 of 10

jeremy_tammik
Alumni
Alumni

Thank you very much for this crucial bit of information. Sorry to hear about your struggles. Who or what set up that debugging switch, please? I have never used it myself in that context. Where did your Visual Studio project and that setting come from?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 9 of 10

ctoASWG6
Explorer
Explorer

thx for your reply!

The "/language ENU" in visual studio debug settings comes f.e. from

 

https://github.com/mitevpi/revit-wpf-template

https://github.com/zahmadsaleem/revit-webview2-demo

 

0 Likes
Message 10 of 10

jeremy_tammik
Alumni
Alumni

Aha. Yes, well, they presumably have their own good reasons for that. And your reasons are different. Pick what you need and can use, and omit everything else.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes