Announcing DotVVM 2.5
Published: 11/6/2020 11:23:00 AMWe’ve just released a new minor version of DotVVM – the version 2.5. It took longer than we expected, but there were several fixes and features we wanted to squeeze in this release.
DotVVM 2.5 brings several new features which may simplify the use of DotVVM in older ASP.NET Web Forms projects, as well as significant performance and stability improvements.
The main improvements were already present in the Preview 2, but let’s remind them here.
Experimental feature: Explicit assembly loading
Those of you who tried to install DotVVM into an old ASP.NET Web Forms project probably run into several issues with incorrect project references. Until now, DotVVM tried to load all referenced assemblies (including transitive ones) and scan them for various things (namespaces in the @import directive, attached property declarations and so on). This was quite inefficient, and caused problems as the mess references often found in legacy projects prevented the application to run.
Now, it is possible to turn this feature on, and then explicitly list assemblies that DotVVM should work with:
// enable the feature
config.ExperimentalFeatures.ExplicitAssemblyLoading.Enable();
// add assemblies
config.Markup.Assemblies.Add("assemblyName");
Startup and background view compilation
Until now, all DotVVM views (pages, master pages and user controls) were compiled on demand - during the first request that needed them. This flow is great for developer inner loop as you typically work with just a few pages you are working on.
// default behavior
dotvvm.Markup.ViewCompilation.Mode = ViewCompilationMode.Lazy;
In production, you can take advantage of two new modes:
- Deployment slots? Use DuringApplicationStart!
If you use deployment slots, the new version is launched on a second instance and the infrastructure is waiting until the app is fully initialized. The traffic still goes to the original instance. When the new version responds to a first HTTP request, the infrastructure switches the slots and the traffic will be forwarded to the new version, so there is no downtime. It can be set up quite easily for example in Azure App Service.
This mode compiles all the views during the startup routine. It increases the app startup time (in larger apps it can take a minute or two) and the app starts responding to the HTTP requests after it has been fully initialized. That’s why it’s a great choice for deployment slots scenario.
Do not use this mode without deployments slots unless you don’t care about the downtime – this mode can make the app unavailable for minutes because the view compilation happens during startup. - Single-instance deployment? AfterApplicationStart is the choice!
In this case, the startup time is similar to the Lazy mode. The views will be compiled on a background thread immediately after the startup is finished. Thanks to this, there is a high chance that the pages will be already compiled when accessed by the users, at least in less-frequently used apps.
If someone visits a page that hasn’t been compiled yet, it will be compiled immediately, same as in the Lazy mode.
If the application makes additional actions after its startup (e. g. populating caches), you can delay the background compilation using the BackgroundCompilationDelay so the CPU is not stressed with too many things at the same time. Also, there is an option to disable parallelism so all CPU cores are not exhausted by doing the view compilation.
Redirection helpers in route table
Sometimes it is useful to be able to register a route which makes a redirect. We’ve seen users writing their own IDotvvmPresenter implementations to do this, and so we added an easier way. You can now use AddRouteRedirection and AddUrlRedirection, which allows you to hook up on a URL you want to redirect, and specify a targer route or URL. There is also an option to process query string and route parameters so the opportunities are endless.
// redirect from "article/15" to "content/article/15"
config.RouteTable.AddUrlRedirection("ArticleRedirection", "article/{id}", c => "content/article/" + c.Parameters["id"]);
// redirect from "calendar" to "calendar/{DateTime.Now.Year}/{DateTime.Now.Month}"
config.RouteTable.Add("Calendar", "calendar/{year}/{month}", "Views/Calendar.dothtml");
config.RouteTable.AddRouteRedirection("CalendarRedirection", "calendar", "Calendar", parametersProvider: (context) => {
var now = DateTime.Now;
return new Dictionary<string, object>()
{
{ "year", now.Year },
{ "month", now.Month },
};
});
You can find a complete list of changes and fixes in the Release notes.
We also continue to improve the DotVVM for Visual Studio extension. Along with many performance & stability improvements, we’ve worked on several new features. Here is one of them:
“Add DotVVM” feature in DotVVM for Visual Studio
We’ve also released a new feature of our Visual Studio extension – it’s called Add DotVVM, and it dramatically simplifies the process required to start using DotVVM in an ASP.NET Web Forms, MVC or other app.
Instead of having to install several NuGet packages, update the csproj file, create the Startup.cs and DotvvmStartup.cs files, the process now requires just one button click.
DotVVM 3.0 is ahead
The team will now fully focus on delivery of DotVVM 3.0. There is one big feature we are really looking forward – the ability to write a client-side logic in TypeScript and be able to call it from DotVVM and vice-versa.
Imagine you want to display a Google Map on a page that is powered by DotVVM, and display a pin on the map based on some values in the viewmodel.
Until now, you’d have to create a script file, register it so it’s loaded after DotVVM, and then hook up to dotvvm.events.init and use something like dotvvm.viewModels.root.viewModel.CurrentLocation().Latitude(). And if you’d need to make a postback based on something that happened in the map, the only way was to use a hidden button and click on it using JavaScript. There was even not a way to determine whether the postback was successful or if there was some error.
We want to simplify this experience to something much easier.
In the page, you’ll be able to import a “JS module” (this is not a final name of the feature, but that’s how we call it right now):
@jsModule Scripts/map
Then, you can add a map.js file in the wwwroot/Scripts folder. Of course, you can use TypeScript that will create the JS file for you. The file should be a JS module that can export several things:
* init function that will be called after DotVVM is initialized
* commands – a JS object with functions that can be called from DotVVM controls using a static command:
<dot:Button Click="{staticCommand: _js.Invoke("AddPin", Latitude, Longitude)}" />
There will be other things the module can export – custom postback handlers, handlers for DotVVM events and more!
Also, we plan to introduce a nice API that you can use to invoke postbacks and static commands in the page and update the viewmodel safely (we don’t want you to deal with Knockout observables as there are so many things that could be broken easily).
Join us on a virtual event on November 16 to learn more about DotVVM 3.0
The DotVVM team hosts an online event on November 16 at 2:00 PM UTC (3:00 PM CET) as part of .NET Conf local events.
Add to calendar
We’ll talk about new features we've added to DotVVM, and we'll share our future plans:
- Support of .NET 5
- How easy it is to "Add DotVVM" into your legacy ASP.NET apps
- What's new in DotVVM 2.5
- Roadmap for DotVVM 3.0 - JS modules & client-side extensibility, validation improvements, web components and more!
Your feedback is important to us. We’ll be happy to talk on our Gitter chat.
I am the CEO of RIGANTI, a small software development company located in Prague, Czech Republic.
I am Microsoft Most Valuable Professional and the founder of DotVVM project.