DotVVM 3.0
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
Fixed bug in static commands with multiple server calls
Progress in our effort to use non-nullable reference types
Fixed URL-encoding problems in RouteLink
parameters
Customizable active and disabled CSS classes in DataPager
Fixed issue with async command execution
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
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
- Objects in the viewmodel now always have the
$type
property which contains unique ID of the concrete type. When object without the$type
annotation 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
ordotvvmserialization.serialize
methods in the client-side DotVVM, consider replacing them with the new state manager API (state
property,setState
andpatchState
functions on the observables). You can also assign plain JS objects to the viewmodel observables — they will be coerced automatically. We plan to remove theserialize
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 theisSpaNavigationError
flag, and we have added a new eventspaNavigationFailed
that is fired in case of SPA navigation failure (network error, exception on page load etc.)afterPostback
— we have removedredirectPromise
andhandled
parametersspaNavigating
— thenewUrl
parameter was renamed tourl
spaNavigating
— we have removedserverResponseObject
andisSpa
parametersstaticCommandMethodInvoking
,staticCommandMethodInvoked
andstaticCommandMethodFailed
— thecommand
argument was renamed tomethodId
staticCommandMethodInvoking
,staticCommandMethodInvoked
andstaticCommandMethodFailed
— theargs
argument was renamed tomethodArgs
- all events — removed
xhr
parameter — DotVVM usesfetch
API instead ofXMLHttpRequest
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.