Skip to content

DotVVM 2.5 Preview 2

Pre-release
Pre-release
Compare
Choose a tag to compare
@tomasherceg tomasherceg released this 23 Aug 20:14

New Features

Experimental: Explicit assembly loading

Until now, DotVVM was searching all assemblies referenced by the application (including transitive references) to be able to find attached properties of controls (which may be declared in a different assembly than the controls), @import namespaces and other types. This was causing longer startup times as all assemblies were being searched.

We've introduced the explicit assembly loading mode that loads and searches only the assemblies that you list explicitly in DotvvmStartup:

config.Markup.Assemblies.Add("assemblyName");

This feature is experimental and must be turned on:

config.ExperimentalFeatures.ExplicitAssemblyLoading.Enable();

We expect this feature to help a lot especially in the Web Forms modernization story - many legacy applications have unused references that are not even present in the bin directory. Without this feature, DotVVM was forcing the developers to fix all these issues first, which hurts the experience with getting DotVVM running.

Redirection Helpers in the Route table

(#858)

We've added AddUrlRedirection and AddRouteRedirection in the DotVVM route table to simplify creating URLs that redirect to another place.

It can be used e. g. for preserving old links when you need to change the URL for your pages.
You can now register these old routes like this:

// 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 },
    };
});

View compilation on startup or on background

(#841 and #846)

Until now, all DotHTML files (views, master pages, and user controls) were compiled to their C# representation on the first HTTP request that needed them. Because of this, the first load of every DotVVM page took longer.

We've added two new options:

  • DuringApplicationStart - this mode compiles all views and delays the startup of the application until the compilation is finished. The first HTTP request will be handled after all views have been compiled. This option is meant for production scenarios where you are using deployment slots (which will be switched once the application starts responding), or where downtime of a minute or two is not an issue.
  • AfterApplicationStart - this mode doesn't delay the startup of the application but compiles all views on a background thread. It is possible to set a delay (configuration.Markup.ViewCompilation.BackgroundCompilationDelay) so it doesn't stress the CPU when other app initialization (populating caches etc.) tasks may be in progress. This option is great for applications that prioritize the page load time and have enough compute power so the background compilation won't affect the overall server performance.

For development scenarios, we recommend sticking to the default Lazy mode as it doesn't slow down the application startup and compiles only the views that are actually needed (in the typical dev loop, the developer is not working with all pages of the app at the same time).

REST API bindings upgraded to latest Swashbuckle.AspNetCore

(#855)

ASP.NET Core 3.0 introduced the new System.Text.Json serializer that replaced Newtonsoft.Json. This, and other changes, affected our Swashbuckle extensions for REST API bindings that helped DotVVM to generate better API clients based on Swagger / Open API metadata.

The DotVVM.Api.Swashbuckle.AspNetCore package now references Swashbuckle.AspNetCore 5.4.1 which works with both ASP.NET Core 2.x and 3.x.

If the API consumed by DotVVM app is hosted in ASP.NET Core 2.x, or if it explicitly uses the Newtonsoft.Json serializer in 3.x, you'll need to install Swashbuckle.AspNetCore.NewtonsoftJson package as well - otherwise the Open API metadata are not generated correctly.
See the Swashbuckle 5.x release notes for more details.

ValidationSummary improvement

  • #838 The ValidationSummary control has now a new property HideWhenValid that can hide the entire <ul> element when no errors are present. It helps when you need to apply styles like padding or border on the <ul> element.

CancellationToken

  • #857 We've added the Context.GetCancellationToken() which returns the request cancellation token. You can pass this token to async methods if you expect they'll take long - it will allow them to cancel the operation if the user cancels the HTTP request (e. g. by refreshing the page or closing the browser).

Startup performance tool

  • #851 We've created a command-line tool that helps with measuring the startup performance of (not only DotVVM) ASP.NET web apps. It is not very sophisticated, but it is easy to use.

It can be used like this:

DotVVM.Tools.StartupPerfTester.exe Path/To/The/MyApp.csproj -t owin|aspnetcore --verbose --repeat 10

The tool will publish the project in Release mode and try to run it 10 times while measuring the time until the app responds to the first HTTP request.

Other small improvements

  • #819 Added AddRequiredResource method to ResourceManager to allow adding any kinds of resources to the current page.
  • #789 and #826 We've done some improvements of build and testing scenarios for developers who work with the DotVVM repo on Linux.

Fixes

ViewModel Serialization

  • #871 Until now, DotVVM didn't support nesting [Protect] attributes in the viewmodels. If you used the [Protect] attribute on a complex object or array in the viewmodel, and the attribute was used inside too, DotVVM didn't serialize the viewmodel correctly. We've redesigned parts of the serializer so the nesting is now supported. There are some restrictions - basically, the protection is additive: if you protect the parent object e.g. by SignData, the child cannot use None on any of its members. Also, if you use EncryptData, the child object cannot use just SignData.
  • #853 We've fixed serialization of KeyValuePair in viewmodels.

Race conditions and problems in the postback pipeline

  • #816 We've fixed several bugs in the postback pipeline that caused freezing of the page or skipping some postbacks, especially when using PostBack.Concurrency="Queue". The issue was happening when multiple postbacks were invoked quickly (e. g. triggered by the incoming SignalR messages).
  • #816 When the client received the Redirect response from the server, the next postbacks from the queue were still being sent which could lead to unexpected behavior. We've fixed the issue so now when the client gets redirect response, subsequent postbacks in the queue are discarded. It was causing issues, especially in SPAs when the postback responses could arrive even after another page was loaded.
  • #860 Another PR related to cleaning up the postback queues in SPA apps.
  • #876 When the user navigated to another page in SPA and then triggered a postback, it canceled the SPA navigation and the page may stop working. We've fixed this so all postbacks during SPA navigation are ignored. In case the SPA navigation fails, the postbacks start working again so the user is able to repeat the action and continue using the old page.

DotVVM for Visual Studio compatibility issues

  • #818 Cleaned the DotvvmConfiguration JSON representation (getting rid of freezable collection wrappers) to fix the behavior of the VS extension.
  • #822 We've fixed several issues in the binding expression parser so IntelliSense now works better in the VS extension.
  • #824 Added the [PropertyGroup] attribute (for properties like class-* or Param-*) that easies the discovery of the property groups for the VS extension IntelliSense.

Binding expression cache on OWIN

  • #805 We've implemented a custom LRU (least recently used) cache for binding expressions that replaces the System.Web.Caching.Cache on OWIN. This fixes a memory leak that occurred in applications that generated a lot of binding expressions dynamically (e. g. by using DotVVM Dynamic Data). A temporary solution was to use ConcurrentDictionary-based cache, but this approach couldn't release unused bindings that weren't needed anymore.

Other issues

  • #856 Fixed NullReferenceException when calling task-based methods without async/await statement.
  • #804 We've fixed passing non-primitive command arguments to methods (it was affecting mostly the staticCommand calls).
  • #859 Fixed the dependency cycle detection in the registration of resources in DotvvmStartup.