Announcing DotVVM and Business Pack 2.3.0

Published: 6/25/2019 6:46:00 AM

You may have noticed that DotVVM 2.3.0 appeared on NuGet few days ago. This was an important milestone for us as we have published the first stable release of DotVVM Business Pack.

DotVVM 2.3 brings several new improvements and fixes, and adds a few infrastructural enhancements (support for emitting HTML templates by controls) that will be important in the future releases of Business Pack.


Local Redirects

We have added the support for local-only redirects. This is an important security feature and we recommend to pay attention to it. The most common scenario for this feature are the redirects made from the login pages.

Most login pages have a query string parametr that specifies the destination URL, e.g. /Account/Login?ReturnUrl=/Account/MyProfile. If the user tries to access a page which requires authentication, he is redirected to the login screen and the URL of the page is passed as the parameter. After the user signs in, he’s taken back to the previous page.

However, the attacker might create a link with an absolute URL pointing to his domain. If you use context.RedirectToUrl, the user might be redirected to the attacker’s website. This site may present a login dialog that looks the same as your own one, and prompt the user to enter his credentials again.

We encourage you to use context.RedirectToLocalUrl on all places where the URL can be modified by the user.


LoadFromQueryableAsync Helper

For a very long time, we were missing the LoadFromQueryableAsync method on the GridViewDataSet. But unfortunately it hasn’t been possible to implement is, because ToListAsync and CountAsync methods are not a part of the standard .NET API. They are always implemented in the library that needs async operations on IQueryable, like Entity Framework, MongoDB client, and others.

However, we can at least help you to build your own extension method that will do the job using the specific library you are using in your project. That’s why we’ve the IQueryable helper methods on GridViewDataSet public – you can use them to implement an async version of LoadFromQueryable yourself.

Since DotVVM 2.3, you can add a following code in your project (place it in a static class):

public static async Task LoadFromQueryableAsync(this GridViewDataSet<T> dataSet, IQueryable<T> source)
{
    source = dataSet.ApplyFilteringToQueryable(source);
    dataSet.Items = await dataSet.ApplyOptionsToQueryable(source).ToListAsync();
    dataSet.PagingOptions.TotalItemsCount = await source.CountAsync();
    dataSet.IsRefreshRequired = false;
}

Please note that you will need to import the namespaces in which the actual implementations of ToListAsync and CountAsync reside.


There are more features and improvements in the framework – see the Release notes for more details.


Stable Release of DotVVM Business Pack

There was a huge delay between the stable version of DotVVM 2.0 and stable release of DotVVM Business Pack, our bundle of enterprise controls for line of business applications. We have redesigned many things in the project, and tested Business Pack extensively on our customer projects until we were not afraid of releasing it to the wide audience.

We have made a tremendous number of changes and improvements to all the controls, including a total rewrite of the CSS part from LESS to SCSS which is much more popular these days.

  • The controls have much nicer CSS selectors and their appearance can be tweaked easily – not like in the 1.x version where you need to override many things and use the !important flag all the time.
  • Along with the Enterprise and Bootstrap4 themes, we have also the None theme – a special theme that has no appearance and contains only CSS rules that handle the layout of controls. This allows you to implement your own look and feel for all the controls.
  • The controls respond to keyboard actions much better than the ones from the previous version of Business Pack.
  • We have changed the user experience of the DateTimePicker control and made the time selection more user friendly, and made many other UX changes in all of our controls. The control was split in three controls.

There is still plenty of work and we have a lot of plans for future Business Pack releases, but the API has now been stabilized and the future versions shouldn’t introduce breaking changes.


Experimental Controls

During our preview releases, the Business Pack contained several unfinished controls, for example the FilterBuilder – a control that can be used in GridView to let the user filter the columns.

The stable release of Business Pack 2.3.0 doesn’t include these experimental controls. If you need to use them, stay on 2.3.0-preview08 – this last preview is exactly the same as the stable version, only with the experimental controls included. Even in the future, we will always release a preview together with a new stable version so you will have a release with both stable and experimental controls.

If you have been using the preview versions of Business Pack, you have probably noticed that there have been some API changes in the names of control properties. If you haven’t tried Diagnostics Status Page package yet, it may be a good time to install it in your project – you can then visit /_diagnostics/status and see which pages contain any compile errors.


What’s Cooking

We are working on a very nice feature that can possibly change one of the main principles used in DotVVM from its early days. Until now, the viewmodel needed to be transferred from the client to server on every postback.

We are now experimenting with a feature called Server-Side ViewModel Caching which can store viewmodels (without encrypted data) in a key-value storage. In case of one server, it can be just in-memory cache. For web farm deployments, there are plenty of options – Redis for example.

Basically, the viewmodel is stored in the cache before it is sent to the client, and its cache ID is included in the page. When the client makes a postback, the difference between the original and current state of the viewmodel is produced and sent to the server. Thanks to this, a lot of data transferred can be saved.

Imagine a page with a GridView control with hundred rows. The user just needed to change the sort order, but by default the entire viewmodel was sent to the server, even if it was unchanged (the SortExpression of GridViewDataSet is changed on the server during the postback). Now, only the cache ID and the diff is sent to the server, which will apply the diff on the value from the cache.

There might be situations in which the viewmodel is not in the server cache any more – the cache item might be expired, the web application might got restarted and its cache might got lost, or there was not enough memory and some cache items were removed. In such cases, the server will return a short response indicating that it needs the entire viewmodel, and the client will issue a second request with a full postback immediately.

We are using SHA256 hash of the viewmodel JSON as the cache ID. We have found out that there are many pages which return always the same viewmodel. Thanks to this, such viewmodels will be stored in the cache just once and won’t take much space.

There is still a lot of work on this feature – we need to make reasonable performance measurements and investigate how to prevent spawning the cache with thousands of viewmodels. We’ll have to introduce a mechanism that will allow to configure this feature so it can be used for example by the authenticated users only, or to limit the number of items in the cache for each route.


Your Feedback Is Crucial

As always, we’d love to hear from you. If you’ve requested a trial version of DotVVM Business Pack before, you can request it again to get the most recent version. Try it and tell us what you think!

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.