Extensibility Web Views in C#

Last modified: September 26, 2025

Introduction

Wherever the Studio Pro Extensibility API allows you to add custom UI, you can implement it using web technologies.

Studio Pro includes a built-in web view for displaying your web-based UI. It also provides a built-in web server that can be used to serve both the web UI and the data it requires.

Additionally, a two-way message passing mechanism enables direct communication between the web content and the C# part of your extension.

Showing a Web View in the UI

There are a number of places where the Extensibility API allows you to add custom UI.

Typically, the Extensibility API requires you to return a view model for your UI. Every view model type has a corresponding base class used to display the UI in a web view.

The table below lists the APIs that support custom UI and the corresponding view model base class:

UI element API for adding UI Base class for view model
Tab (in working area) IDockingWindowManager.OpenTab(...) WebViewTabViewModel
Document tab (in working area) AppExplorerExtension.EditDocument(...) WebViewDocumentTabViewModel
Dockable pane DockablePaneExtension.Open(...) WebViewDockablePaneViewModel
Modal dialog IDialogService.ShowDialog(...) WebViewModalDialogViewModel

The view model base classes are abstract, so you are required to create your own view model class that derives from the base class.

Each view model class has a method called InitWebView that you must override to initialize the web view.

In this method, you can tell the web view to navigate to the (local) URL that contains your web content.

In addition, the view model class can be used to house the logic for communicating with the web view.

Serving Content to the Web View

For serving content to the web view and communicating both ways with it, see Build a Todo Example Extension.

Troubleshooting

Web Content Fails to Load

If your pane or tab was open when Studio Pro was closed, your web content might fail to load when you reopen Studio Pro. This is because the WebServerBaseUrl property is null due to timing issues in the startup sequence.

To resolve this, listen to OnWebServerBaseUrlChanged in your WebServerExtension. This will get the URL when it is reinitialized.

You can use the following code:

[Export(typeof(WebServerExtension))]
class ContentServer : WebServerExtension
{
    [ImportingConstructor]
    public ContentServer(INotificationPopupService notificationPopupService)
    {
        OnWebServerBaseUrlChanged += () =>  notificationPopupService.ShowNotification("Web Server Base Url Initialized", WebServerBaseUrl.ToString(), null, 2);
    }
}