Skip to content

DotVVM 3.0

Compare
Choose a tag to compare
@tomasherceg tomasherceg released this 03 Apr 12:54
· 3674 commits to main since this release

New features

Calling JavaScript from DotVVM and vice versa

#935
We have added the new @js directive which allows to import a ECMAScript module in a page, master page or a markup control, and call its methods using _js.Invoke<TResult>("method", args...). Also, there is a new NamedCommand control which allows exposing DotVVM command or static command to the JavaScript code, so it can be called (including passing arguments). This allows easy interactions between DotVVM components and the world of JavaScript.

Variables are supported in binding expressions

#869
You can now declare variables in binding expression, which enhances the abilities especially in static command bindings — e.g. {staticCommand: var result = _myService.GetItems(); Items = result.Items; TotalCount = result.TotalCount}. The variable must be assigned immediately, and cannot be re-assigned to a different value (behaves similar to const in JavaScript).

Lambda support in binding expressions

#903
You can use lambdas in data-bindings, which opens many new possibilities, for example calling LINQ methods or expose command bindings to JavaScript code that can get custom parameter values.

New client-side event initCompleted

#915
This event is called after the viewmodel is applied to the page DOM.

Additional metadata can be returned with the command result

#916
This allows returning additional information together with results of command or static command calls. This information can be read e.g. in the afterPostback event or in a postback handler, and used to perform any client-side action (displaying an alert, custom validation, and so on).

Extension methods are supported in binding expressions

#931
Right now, we only support few white-listed extension methods from System.Linq namespace, but we'll allow to call any extension method based on @import directives in DotVVM 3.1. This is already implemented in #946, but the PR is still being reviewed so it didn't make it into 3.0.

NPM package with TypeScript definitions

#952 #956
If you want to write TypeScript code that interacts with DotVVM, you can now use the dotvvm-types package.

DotVVM uses non-minified version of scripts when config.Debug is true

#970
This helps with debugging script errors by peeking into non-minified DotVVM code.
Minified version of DotVVM has now about 48 kB, plus 69 kB for Knockout JS. With HTTP compression enabled, the total download size of DotVVM and Knockout together is ~55 kB. Make sure you don't deploy your apps to production with the debug flag — the debug scripts are significantly larger.

Verbose client-side logging flag

#971
If you want to see more detailed logs in the dev console, create a dotvvm-loglevel entry in the local storage of the site and set it to verbose. DotVVM will emit information about client-side events, and more.

Improvements and fixes

Refactoring of the client-side part, migrated to the modern TypeScript, rollup bundler.

#834
All client-side code of DotVVM was refactored and now takes advantage of the newest TypeScript language features (ES modules and so on). We are using rollup to create bundles for modern browsers as well as for Internet Explorer 11. We also have different bundles for SPA and non-SPA pages (non-SPA are slightly less).

Client-side events and postback pipeline

#885
We have reviewed and thoughtfully refactored the postback processing pipeline, fixed many issues, and resolved several inconsistencies (for example: some client-side events didn't get all arguments that one would expect, and the internal implementation of error handling was not very straight-forward and maintainable). See the Breaking changes section — there were some API changes which may affect you.

JavaScript tests migrated to jest

#883
We now have much more client-side tests as well as stress test which help us detect race conditions in postback concurrency handling.

Multiple SpaContentPlaceHolder controls can be used on the same page

#847
We have also removed the old format of SPA with the hashbang (#!) construct in the URL in favor of History API which is supported even in IE 11. The DefaultRouteName, PrefixRouteName and UseHistoryApi properties are deprecated — History API is used by default, and it's the only option. The links in the old format will still work — DotVVM will redirect to the new URL format.

Viewmodel state is represented by an immutable JavaScript object

#884
The state of the viewmodel is not kept in the hierarchy of Knockout observables, but in a new state manager's immutable object. The hierarchy of Knockout observables is still there, but it is “virtual”. Every change via Knockout observables will patch this immutable state, and the changes propagate asynchronously to all affected places in the Knockout observable tree. It helps to create a similar effect as deferred option in Knockout. The state manager offers new API which lets you access the viewmodel without messing with observables (state property, setState and patchState functions).

Improved resolving of generic methods and overloads for custom JS translations.

#892 #937
From version 2.0, DotVVM offers to supply custom C# to JS method translations. We have fixed some issues and enhanced the method matching to support generic arguments, param arrays, and more.

Type-safe viewmodels

#905
DotVVM passes type metadata alongside the viewmodel, so we can make sure the viewmodel won't allow assigning e.g. array to a property of string. DotVVM checks all assignments to the viewmodel properties against this type definition, and throws errors in case of type mismatch. In some situations, it can coerce the value to the correct type (e.g. number to string).

Static commands can be passed to markup controls

#928 #943
Markup controls did allow passing value and command bindings from the outside, but it didn't work for static commands.

Route redirection helpers enhancements

#938
You can modify query string arguments when you use AddRouteRedirection feature introduced in DotVVM 2.5.

Markup files can be referenced from a directory outside the application directory

#908

Fixed bug in static commands with multiple server calls

#910

Progress in our effort to use non-nullable reference types

#912

Fixed URL-encoding problems in RouteLink parameters

#922

Customizable active and disabled CSS classes in DataPager

#923

Fixed issue with async command execution

#933

Progress in making our UI tests more reliable

#949
We have introduced retry logic into our Selenium test helpers which will help us clean explicit waits in our tests. Thanks to this, the tests will hopefully be more readable, easily maintainable, and reliable. Right now, it is common that from the hundreds of UI tests, one of two just fail randomly — that's why the build status of DotVVM is often shown as failing.

Fixed culture-dependent letter case conversion to invariant in the serializer

#951
This was a community-authored PR which helped us realize that we have to consider the culture invariancy every time when ToUpper/ToLower is used. "I".ToLower() resolves to "i" in most cases, but in Turkish it is "ı". Many thanks!

Fixed bug in concurrency handler in static commands

#957

Breaking changes

Null propagation now passes nulls into methods

#817
Previously, any binding expression which evaluated to null caused to evaluate the parent expression to null as well. If there was a method call in the expression, and any of the arguments evaluated to null, the entire method call was skipped and evaluated to null. We changed this behavior so the null is passed in the method.

Script resources use defer by default

#930
DotVVM resources was marked as deferred, which means that all other scripts that depend on DotVVM need to be deffered too (otherwise, they would load before DotVVM and fail). We have changed the default behavior of ScriptResource so the Defer property is true by default.

Async IUploadedFileStorage and IReturnedFileStorage

#981
We changed these interfaces to use async methods everywhere. The behavior hasn't changed, you'll only need to add await to the GetFile or ReturnFile calls.

Type-safe viewmodels

#905

  • Objects in the viewmodel now always have the $type property which contains unique ID of the concrete type. When object without the $typeannotation is added in the viewmodel, DotVVM will infer the type automatically.
  • Properties of type DateTime are now validated (even if there is noRequired attribute). From DotVVM 3.0, empty date values won't be sent to the server.
  • If you call dotvvm.serialization.deserialize or dotvvmserialization.serialize methods in the client-side DotVVM, consider replacing them with the new state manager API (state property,setState and patchState functions on the observables). You can also assign plain JS objects to the viewmodel observables — they will be coerced automatically. We plan to remove the serialize anddeserialize methods from the public API in the future versions.

Client-side events and postback pipeline

#885
Due to the refactoring and cleanup, most of the client-side events had some changes in the structure of event arguments (new properties were added).

  • error — we have removed the isSpaNavigationError flag, and we have added a new event spaNavigationFailed that is fired in case of SPA navigation failure (network error, exception on page load etc.)
  • afterPostback — we have removed redirectPromise and handled parameters
  • spaNavigating — the newUrl parameter was renamed to url
  • spaNavigating — we have removed serverResponseObject and isSpa parameters
  • staticCommandMethodInvoking, staticCommandMethodInvoked and staticCommandMethodFailed — the command argument was renamed to methodId
  • staticCommandMethodInvoking, staticCommandMethodInvoked and staticCommandMethodFailed — the args argument was renamed to methodArgs
  • all events — removed xhr parameter — DotVVM uses fetch API instead of XMLHttpRequest

We have also made some changes in the order of the events being fired — the most important change is that the error event is triggered as the last event (it now fires after afterPostback for the command binding postbacks).

We've also made a change in the error thrown when the server reports validation errors in the viewmodel. The error reason now has { type: "validation" } and the responseObject.modelState contains the collection of errors. Until now, the validation errors were reported as { type: "commit" }.

If you've been using client-side events e.g. for displaying alerts for validation errors or disabling buttons during postbacks, make sure to test this functionality — the changes in DotVVM 3.0 might have broken it.

JavaScript value for checkbox inputs changed

The value property of input[type=checkbox is now "on" while it is checked, and "off" while it is not. Previous values were true / false.

dotvvmEnable Knockout binding handler renamed

The dotvvmEnable Knockout binding handler was renamed to dotvvm-enable. We have also renamed and reorganized other binding handlers used by DotVVM.