ServiceStack Studio Preview

Excited to announce ServiceStack Studio Desktop App which is intended to provide a rich UI for accessing your ServiceStack instances.

It replaces the ServiceStack Admin UI where it provides a UX-friendly UI for accessing AutoQuery & Crud Services but will also gain UI features for taking advantage of various ServiceStack Plugins & Features, e.g. in this initial release it includes a UI for managing DB Validation Rules & for viewing the executable Audit History of Tables updated through AutoCrud Services.

It’s a capability-based Admin UI where it only enable its different management UI’s depending on which features each remote ServiceStack Instance has enabled & whether the Signed In User has access to them.

To enable this a new /metadata/app endpoint returns metadata information about which plugins are enabled, what features they’re configured with and whether they’re protected behind User Roles. As such it will only be able to manage ServiceStack instances running the latest v5.8.1 (soon to be v5.9).

You’ll also need the latest app dotnet tool which is bundled with the latest Chromium which provides the Desktop UI:

$ dotnet tool update -g app

Which you’ll need to run once to register the app:// url scheme, e.g:

$ app -version

Studio Desktop App vs ServiceStack.Admin

The primary limitations with ServiceStack Admin was its deployment model where it had to be explicitly registered as a plugin in each ServiceStack instance, this means it could only be used on ServiceStack instances that explicitly had it registered, also it maintained the long release cadence of ServiceStack major releases which means the UI couldn’t be updated frequently and the feedback loop was too long.

Frequent out-of-band release cadence

To overcome this ServiceStack Studio is delivered as a Gist Desktop App which like a website will be running the latest version each time it’s run. To reduce its download footprint the app and x dotnet tools now include the new ServiceStack.Desktop project which includes the common framework libraries that most Vue & React Apps use which saves it from needing to be included in each Download. It also includes Google Material Design Icons SVG’s & a copy of fontawesome free icons that all Desktop Apps will be able to use without the bandwidth cost for using them.

Light Footprint + Always use latest version

ServiceStack/Studio is a vue-lite App that only uses SVG icons as they’re small, high-quality at every scale, are customizable & have built-in css classes making them easy to use declaratively where it takes advantage of ServiceStack’s built-in SVG support which allows optimal css bundles containing only the svg’s your App’s use. All SVG icons used in Studio are defined in its _init.ss startup script which defines which Material Design SVG to make available under which css bundle. It also registers its own custom SVG icons not contained in ServiceStack.Desktop’s embedded resources and includes them as part of its /css/app.css bundle.

As a result of its architecture Studio gets bundled down to a 58kb .zip which includes its 46kb (Uncompressed) Studio.dll plugin containing all its C# back-end logic (thanks to all ServiceStack .dll’s being deployed with the dotnet tools as well). As it’s published as a Gist it adds a bit more overhead and Gist APIs aren’t particularly fast so there’s a slight delay in loading from a Gist which should still load its home page in around 2-3s, which includes the start time of the ServiceStack .NET Core App and the Chromium CEF Browser. The number of restarts should be minimal thanks to Studio being designed as a single UI to manage all your ServiceStack instances so you can reuse the same Desktop UI to manage different remote ServiceStack instances.

Desktop Features

Thanks to it being a Desktop App we have features that wouldn’t be possible in a Web App, e.g. we can use built-in proxies to by-pass CORS & IFrame embedding limitations to be able to access ServiceStack instances that don’t have CORS enabled & native Windows features like easy access to clipboard, launch external programs, control Desktop Windows, e.g. Launch into “kiosk” mode or in/out of full-screen with F11, etc.

ServiceStack.Desktop

Studio is powered by exciting new features in the latest app .NET Core Desktop Apps tool which in addition to its small footprint & able to run “always up-to-date”, it also includes seamless integration into invoking server functions with #Script which allows you to use the same syntax to call JavaScript functions.

The integration makes it trivial to call Win32 APIs from JavaScript which are accessible behind typed async TypeScript function definitions which ends up being much more pleasant than trying to call them in C#, e.g. you can Copy + Paste to the Windows clipboard with just:

import { setClipboard, clipboard } from '@servicestack/desktop'

await setClipboard('Some Text')
await clipboard() //= Some Text

The TypeScript APIs are just typed wrappers around calling DesktopScripts Script Methods which invoke the the appropriate Win 32 API, e.g:

async function clipboard() { 
    return await evaluateCode('clipboard'); 
}

Highly productive live-reloading Development experience

When running inside an app .NET Core Desktop App is uses an IPC mode similar to Unix Pipes where communication is streamed over internal processes with the Desktop Scripts invoked by app.exe. To enable an optimal development experience it also supports a decoupled mode where in Debug builds you can launch the app.exe Chromium browser to open a remote URL, e.g:

$ app start https://localhost:5002

Which allows you to develop your Desktop App as a regular .NET Core WebSite whilst still being hosted inside the app CEF shell which instead of using a Chromium inter-process IPC to invoke #Script server functions, will invoke them over https where the Win 32 APIs end up being invoked by the back-end .NET Core Server instead of the app.exe Desktop App, but the end result remains the same.

If it weren’t for the productivity possible for being able to only needing to develop for Chrome’s state-of-the-art rendering engine where you can use advanced features like CSS grid along with the productivity of high-level productive Reactive UI frameworks like Vue, the effort into create a Desktop App like ServiceStack Studio wouldn’t be justifiable. Being able to develop in a highly productive environment with hot-reloading and a fast iterative development loop makes all the difference which I’d never consider otherwise if needing to use C# & XAML UI FX or WinForms to develop Desktop Apps.

It brings the enjoyment back to developing native apps which gives you web development productivity, access to the latest Chrome features & access to native Windows features when needed.

After the next release we’ll create pre-packaged project templates for vue-desktop and react-desktop Desktop Apps to make it easy develop Vue & React Desktop Apps along with scripts to bundle it & publish it to gist. If preferred app.exe also lets you deploy the published app to your own private repo & limit access to only users accessible with a GitHub token which they can open with from a URL with:

app://user/repo?token={GITHUB_TOKEN}

Or on the command line (which you can create a Shortcut Icon for) with:

$ app user/repo -token $GITHUB_TOKEN

Or without a token by setting it in the GITHUB_TOKEN Environment variable

Anyone wanting an early look at an example of a project built in this development model can have a look at ServiceStack/Studio code base to see how it’s implemented.

Starting ServiceStack Studio

The initial release of ServiceStack Studio primarily provides a UI around AutoQuery Services and the latest features in this release like Executable Audit History and DB Declarative validators.

If you don’t have a project using the latest v5.8.1 features on hand you can launch a copy of NetCoreApps/NorthwindCrud which uses the new AutoCrud features to generate AutoQuery Services around all its RDBMS tables, which you can run locally with:

$ x download NetCoreApps/NorthwindCrud
$ cd NorthwindCrud
$ dotnet run

You can then use URL scheme support in app to launch ServiceStack Studio from a URL & automatically registers the Northwind Crud instance from:

app://studio?connect=https://localhost:5001

This URL scheme gets translated & is equivalent to running Studio on the command-line with:

$ app open studio -connect https://localhost:5001

Which downloads the Studio Gist Desktop App, loads it as a Gist VFS whose static assets are then served by the .NET Core Server and loaded in the CEF Chromium browser.

The connect param is used by ServiceStack Studio to auto register the remote Northwind Crud instance where it auto downloads its App Metadata containing its enabled plugins & features, within a few seconds you should see it appear on the home page:

Desktop-less x-plat app

Although not optimized for it, ServiceStack Studio can also be launched headless in your default Browser using the x cross-platform dotnet tool:

xapp://studio?connect=https://localhost:5001

$ x open studio -connect https://localhost:5001

Where you’ll then be able to view it by going to https://localhost:5002. Note if not launched in a browser Studio will have limited capacity and features, but will eventually be a supported mode for accessing ServiceStack Studio from macOS or Linux.

Home Page

From the home page you’ll see all the top-level Admin Sections available that’s enabled on the remote instance, in the initial release there’s a UI for accessing AutoQuery Services and a UI for maintaining DB Validation Rules.

AutoQuery

Because of the rich declarative metadata of AutoQuery & Crud Services we can infer greater knowledge about them, e.g. from their implemented interfaces & base Type we know the data model that each AutoQuery Service operates on and can infer the type of Operation each Service provides. As a result can logically group each Service around the Data Model they operate on and provide a more intuitive & natural UI for each of the different AutoQuery/CRUD operation types.

What UI features & tables are visible is reflected by whether the AutoQuery Service for that type exists and whether the currently authenticated User has access to them (i.e. Have the role required by each Service). So an unauthenticated user will see Northwind Crud’s read-only Region table with no ability to update it & the Territory table, which as it isn’t protected by a role will be visible to everyone, but as all CRUD Write operations require authentication all edit controls will require authentication.

Here are the relevant NorthwindCrud auto-generation rules which defines this behavior:

var readOnlyTables = new[] { "Region" };
GenerateCrudServices = new GenerateCrudServices {
    ServiceFilter = (op,req) => {
        // Require all Write Access to Tables to be limited to Authenticated Users
        if (op.IsCrudWrite())
        {
            op.Request.AddAttributeIfNotExists(new ValidateRequestAttribute("IsAuthenticated"), 
                x => x.Validator == "IsAuthenticated");
        }
    },
    //Don't generate the Services or Types for Ignored Tables
    IncludeService = op => !ignoreTables.Any(table => op.ReferencesAny(table)) &&
        !(op.IsCrudWrite() && readOnlyTables.Any(table => op.ReferencesAny(table))),
}

Clicking on any of the Auth icons or the Sign In button on the top right will open up the Sign In dialog.

Integrated Auth

The Sign In dialog supports most of ServiceStack’s built-in Auth Providers with a different Auth Dialog tab depending which Auth Providers are enabled. It looks at “auth family type” to determine how to Authenticate with each Auth Provider so it should still support your Custom Auth Providers if they inherit from existing Auth Providers, otherwise they can explicitly specify which Type of Auth they use by overriding the Type property getter with one of the following:

  • Bearer - Authenticate with HTTP Authentication Bearer Token (e.g. JWT or API Key)
  • credentials - Authenticate with Username/Password at /auth/credentials
  • oauth - Authenticate with OAuth
  • session - Alternative session-based Auth Provider

The session tab is also displayed if a credentials or auth provider is enabled. It should serve as a fallback Auth option if your Custom Auth Provider doesn’t fit into the existing family types as it will open the /auth page of the remote ServiceStack instance:

Where you can login to the remote site via the new fallback /login page or uses your custom Login Page if exists. If your remote instance is configured to allow Studio CORS access, i.e:

appHost.Plugins.Add(new CorsFeature(allowOriginWhitelist:new[]{ "https://localhost:5002" }));

Then clicking on the copy link button will be able to post the session Id back to Studio & close the auth popup otherwise you’d need to manually close the popup and paste the session in.

The OAuth tab is a little different since it requires an OAuth redirect and most 3rd Party OAuth providers disallow embedding in iframes it needs to popup an external url in your default browser which still provides a nice auth UX as you’d typically already be signed in with your Default browser, where it will redirect you back to your /auth page where you can copy either the Session Id or the OAuth Access Token if you enable including OAuth Access Tokens in your AuthenticateResponse DTO with:

appHost.Plugins.Add(new AuthFeature(...) {
    IncludeOAuthTokensInAuthenticateResponse = true, // Include OAuth Keys in authenticated /auth page
});

Which will allow you to Authenticate via OAuth Access Token which allows you to test the same Authentication that Mobile and Desktop using pre-existing Sign In Widgets who also authenticate via OAuth Access Tokens obtained by their native UI widget:

Studio is able to provide a seamless UX where it’s able to monitor the Windows clipboard for changes & when detected close the window, return focus back to Studio who uses it to automatically Sign In with the copied token.

Desktop User State & Preferences

As expected from a normal Desktop App, the User State of the App is preserved across restarts, which Studio maintains in its $HOME/.servicestack/studio/site.settings JSON file which preserves amongst other things what remote ServiceStack instances you’ve connected to & last queries made on each table, etc. To force a save you can press Ctrl+S or click on the save icon on the top right.

AutoCrud Partial Updates

The UI is designed to look similar to a generic RDBMS Admin UI Table Editor where you can edit records in a table grid. If a IPatchDb<Table> AutoQuery Service exists for the Data Model that the Authenticated User has access to, all fields (excl PK) on that Request DTO will be editable in the UI, otherwise they’ll appear Read-only like the Id column:

AutoCrud Create

If the user has access to the ICreateDb<Table> Service they’ll be able to add records by clicking the + icon on the top-right of the resultset which brings up the Create Entity popup:

AutoCrud Update and Delete

If the user has access to the IUpdateDb<Table> Service they’ll be able to update records by clicking on the edit icon which will bring up the Edit Entity dialog. If they have access to the IDeleteDb<Table> Service they’ll also be able to delete the entity from that screen:

API Log Viewer

All API Requests the UI makes to remote ServiceStack instances are made via a generic .NET Core back-end Service Proxy which attaches the Signed In Authentication Info to each Request. Each API Request Studio makes is recorded in the log viewer at the bottom, showing the Verb and Parameters each API was called with:

You can copy the URL from GET API Requests or open them up in a new browser to view it in isolation.

Executable Audit History

If you Sign In as the Admin User (i.e. using AuthSecret=zsecret) you’ll get super user access to access the other protected features like being able to view an Audit History of updates made to each record via AutoQuery which is enabled in Northwind Crud with:

// Add support for auto capturing executable audit history for AutoCrud Services
container.AddSingleton<ICrudEvents>(c => new OrmLiteCrudEvents(c.Resolve<IDbConnectionFactory>()));
container.Resolve<ICrudEvents>().InitSchema();

Where users in the AutoQueryFeature.AccessRole (default: Admin) role will be able to view the Audit history of each row:

If creating & deleting an entity with the same Id, the Audit History of the previous entity will be retained and visible in its audit history.

Validators

As an Admin you’ll also have access to the DB Validation Source Admin UI which will let you add declarative Type and Property Validators for each Request DTO in Studio. This is enabled in NorthwindCrud in Configure.Validation.cs:

// Add support for dynamically generated db rules
services.AddSingleton<IValidationSource>(c => 
    new OrmLiteValidationSource(c.Resolve<IDbConnectionFactory>()));

//...
appHost.Plugins.Add(new ValidationFeature());
appHost.Resolve<IValidationSource>().InitSchema();

Admin limited to users in the ValidationFeature.AccessRole (default: Admin).

Clicking on the Validation Lock Icon on the top right will take you to the Validation Editor for that AutoQuery Request DTO which will include quick links to jump to different AutoQuery/Crud Services for the same Data Model.

In the validation editor you’ll be able to create Type and Property Validation Rules that either make use of an existing Validator or you can enter a custom #Script expression that must validate to true. The Validator UI is smart and will list all built-in and Custom Script Methods returning ITypeValidator or IPropertyValidator that’s registered in the remote instance. The pre-defined list of validators are displayed in a list of “quick pick” buttons that enables fast adding/editing of validation rules.

The ModifyValidationRules Service that Studio calls performs a lot of validation to ensure the Validation rule is accurate including executing the validator to make sure it returns the appropriate validator type and checking the syntax on any Script validation rules to ensure it’s valid.

The ModifyValidationRules back-end Service also takes care of invalidating the validation rule cache so that any saved Validators are immediately applied. Note that despite being sourced from a DB, after the first access the validation rules are cached in memory so would have similar performance to validators declaratively added on Request DTOs in code, until the cache is invalidated which only requires a single DB hit to populate the cache for a Request DTO again.

After you add your validation rules you will be able to click the AutoQuery icon on the top right to return to the AutoQuery editor. Be mindful of what Validation Rule you’re adding to which DTO, e.g. a validation rule added to CreateCategory Service will only be applied to that Service which is used when creating entities, e,g. not for full entity or partial field updates.

Future Updates

I hope this provides a quick glimpse into ServiceStack Studio which I hope most will find useful. Currently this release focuses on getting the foundational architecture pieces in place that makes it possible for ServiceStack Studio to enable its compatibility-based UI with the metadata of the different plugins & features that are enabled and the roles that have access to them.

Thanks to the productive workflow of an integrated .NET Core Chromium Desktop App updates will be able to frequently continue out-of-band of ServiceStack releases where they’ll be immediately available after the next time the Studio is run. Currently on the TODO list will be to implement the last remaining features from ServiceStack Admin UI which it replaces, with support for multiple queries + paging and richer edit UIs where we should be able to use more optimal input controls as we have the type information of every field. It also shouldn’t be too hard to implement a better UI for invoking ServiceStack APIs than generic REST API UIs like Postman as we have richer metadata about each API and access to the richer functionality around ServiceStack Services.

ServiceStack Studio should be considered to be in beta at least until v5.10 where it’s likely additional changes will be needed in the App Metadata as more UI features are implemented. I welcome any feedback if you get a chance to try it out, please report any issues in these forums where they should be able to resolved relatively quickly.

2 Likes

Very cool. Looking forward to trying it out. What’s licensing like on this? Can we provide to our end users to connect only to our service? Is the source available so we can possibly customize look and feel and other functionality?

The Source code for the Studio App is maintained at:

I’ve just added a new BSD License so you’re free to use/customize the Studio UI source code but haven’t decided on whether to allow unrestricted usage of all ServiceStack libs within the dotnet tools yet.

If you’re only developing a pure Sharp App with #Script then it’s unlikely to hit the free-quota restrictions which are limited by typed ServiceStack Services, typed OrmLite/Redis data models, etc. which #Script doesn’t use. But Studio has backend StudioServices.cs implementation which just exceeds the 10 Services free-quota limit which would typically require registering a commercial license key, but it’s currently unrestricted for the time being whilst it’s still under active development.

I’ll see what the reception for ServiceStack.Desktop is like, if there’s a lot of interest in it I’ll make it unrestricted to be able to use all ServiceStack libraries within the dotnet tools without needing to register a commercial license key, otherwise licensed ServiceStack devs can always register their license key in their custom AppHost and/or plugins to enable unrestricted usage & royalty-free distribution as normal. Either way you should be able to freely distribute your own customized versions of it.

But it’s not a design goal that it supports derivatives, e.g. the .csproj is referencing Source projects directly, you’d either need to download the source code for the referenced projects or change it to reference ServiceStack pre-release packages.

1 Like