Announcing Preview 7 of DotVVM 4.2.0

Publish date:

We’ve just published a new public preview of DotVVM 4.2 with a version tag 4.2.0-preview07-final. This version is available for all packages: open-source DotVVM framework, DotVVM Contrib controls, Bootstrap for DotVVM, and DotVVM Business Pack. All these packages are compatible with each other and have been tested together.

This is most probably the last preview before releasing the stable version of DotVVM 4.2, so we will be happy for any feedback or bug reports so we can fix it in this version.

What features you can look forward to?

Validation in static commands

The AllowStaticCommand attribute now has a new parameter which can specify whether the validation of command arguments should happen automatically (this is the Automatic mode), or whether the static command may emit model state errors and send them back to the client by calling FailOnInvalidModelState.

public string MyMethod(MyModel model)
    var modelState = new StaticCommandModelState();
    modelState.AddArgumentError(() => model.Property, "Property is invalid");

We believe that this feature will enable using static commands as a default way of calling the server. In general, static commands transfer less data and are faster as they don’t need to work with the entire viewmodel (serialization, deserialization, transferring it, comparing diffs, and so on). On the other hand, in case of static command validation, you need to perform a slight mental shift – you are not validating the viewmodel, but the arguments of the method. Thus, you are not able to emit a validation error for a property which you don’t pass to the static command as an argument.

See related forum post for more examples.

Custom primitive types

A lot of users like Domain-Driven Design or other architectural approaches where you typically work with strongly typed identifiers of domain objects. You don’t want to mess up an ID of an order with an ID of a customer, thus you have a special OrderId and CustomerId types. Often, both of them contain a Guid, but since they have different types, the compiler doesn’t allow you to assign one in the other.

DotVVM now allows to work with these types by implementing IDotvvmPrimitiveType. On the client side, they have to be represented as strings, so they need to implement the TryParse and ToString methods.

Thanks to that, you can use them as route or query string parameters, as a selected value in ComboBox and other controls (where it needs to be a primitive type), and you can compare them easily in expressions.

public struct OrderId : IDotvvmPrimitiveType
    public int Value { get; }

    public OrderId(int value)
        this.Value = value;

    public override string ToString() => Value.ToString();

    public static bool TryParse(string value, out OrderId result)
         if (int.TryParse(value, out var resultValue))
             result = new OrderId(resultValue);
             return true;
         result = default;
         return false;

Metrics and Prometheus support

We instrumented DotVVM with System.Diagnostics.Metrics so you can watch key performance metrics of your application, including sizes of the viewmodels, time the DotVVM needs for serialization and deserialization, and plenty of others.

If you want to use the prometheus-net library to expose the metrics in prometheus format, we recommend calling the Prometheus.MeterAdapter.StartListening method as soon as possible (at the start of Startup/DotvvmStartup is a good place), and configuring the buckets for histograms.

MeterAdapter.StartListening(new MeterAdapterOptions {
    ResolveHistogramBuckets = instrument => {
        // prometheus-net does not know which buckets will make sense for each histogram and System.Diagnostics.Metrics API
        // does not provide a way to specify it. The ResolveHistogramBuckets function will be called for each exported histogram in to define the buckets.
        return DotvvmMetrics.TryGetRecommendedBuckets(instrument) ?? MeterAdapterOptions.DefaultHistogramBuckets;

WebForms adapters

We have resurrected an old package which helps in the process of migrating Web Forms apps to the new .NET using DotVVM. Because the process is done incrementally (page by page), for most of the time you have some pages written in DotVVM and some in Web Forms. You cannot use DotVVM RouteLink control to point to a page which hasn’t been migrated yet, and you don’t want to hard-code URLs to the pages because you’d lose all benefits of the routing system.

The DotVVM.Adapters.WebForms package contains the HybridRouteLink control which is basically a RouteLink which can also look in the Web Forms route table and generate links to not-yet-migrated pages, and there is also the RedirectToRouteHybrid method which does the same thing with redirects: if the route is present in DotVVM route table, it will use it, otherwise it falls back to the Web Forms route table.

Bug fixes in Bootstrap 5

A lot of users started using the Bootstrap 5 version of Bootstrap for DotVVM. This version is utilizing the new Composite controls approach, so we are still catching and fixing bugs – not only in the library itself, but we also want to improve the experience in the DotVVM for Visual Studio extension.

If you try to upgrade your projects to this new preview versions, we’ll be happy to hear about your experience on our new DotVVM Forum (a replacement for Gitter).

Tomáš Herceg
Tomáš Herceg


I am the CEO of RIGANTI, small software development company located in Prague, Czech Republic.

I am a Microsoft Regional Director and Microsoft Most Valuable Professional.

I am the author of DotVVM, an open source .NET-based web framework which lets you build Line-of-Business applications easily and without writing thousands lines of Javascript code.

Others blog posts from category: DotVVM Blog