Releases: riganti/dotvvm
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 re...
DotVVM 2.5
This release includes all changes from DotVVM 2.5 Preview 2, as well as a few additional improvements:
Features
- #880 - Inline editing is now supported in nested
GridView
controls - #890 - DotVVM uses its own
JsonSerializerSettings
and doesn't rely onDefaultSettings
- #877 - Control developers now may create attached property groups (e. g.
<element MyExtensions.SomeGroup-SomeKey="something" />
) - #896 - The
AddDotVVM
andUseDotVVM
methods now allow passing a custom instance of theDotvvmStartup
class so it is possible to set its properties and so on. If you plan to use this feature, we recommend keeping a default constructor - otherwise, the DotVVM Compiler (used by the Visual Studio extension) will be unable to create the instance of this class.
Fixes
- Fixed references to
netstandard
in view compilation - these didn't work on older versions of .NET Framework. - Fixed deadlock occurring on the first HTTP request on OWIN.
- Fixed incorrect invocation of the
beforePostback
event on static commands.
Enhancements for framework developers
- #874 - Infrastructure for end-to-end testing without the need of using Selenium.
- All paths are using forward slashes so everything in the repo should work on non-Windows machines.
DotVVM 2.5 Preview 2
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
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 propertyHideWhenValid
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 toResourceManager
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. bySignData
, the child cannot useNone
on any of its members. Also, if you useEncryptData
, the child object cannot use justSignData
. - #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 likeclass-*
orParam-*
) 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 useConcurrentDictionary
-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 withoutasync/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
.
DotVVM 2.4
Server side caching of view models (experimental)
This feature can dramatically reduce data transferred between the server and the client.
To enable this feature, add the following code snippet in DotvvmStartup.cs:
config.ExperimentalFeatures.ServerSideViewModelCache.EnableForAllRoutes();
When the feature is enabled, the viewmodels are cached on the server. When the client needs to do a postback, DotVVM can send only the diff of the viewmodel instead of serializing and transmitting the entire object. Thanks to this, we can save a lot of network traffic – almost 100% in extreme cases. Imagine a page with a GridView and a Delete button in every row – when you click on the button, the viewmodel on the client hasn’t changed at all. Thus the diff will be empty and the postback will transfer only a tiny JSON object with an identification of the button that was clicked – no viewmodel data at all. There were other ways to save this traffic, but this one is very convenient to use.
The viewmodels are stored in memory by default, but the mechanism is extensible so you can use any storage you need – just implement the IViewModelServerStore
interface. They are also deduplicated – we are using a hash of the viewmodel as a cache key, so when you use this feature on a public facing site which has the same “static” viewmodel for many users, the viewmodel will be kept in memory only once. And if the item is not in the cache any more, DotVVM will signal it to the client which will immediately issue a new postback with a full viewmodel.
The feature can be enabled for all routes, or only for specific routes in the application. We recommend to enable it on less frequently used pages at first, and watch the memory consumption on the server – the cache should be cleaned up when the server gets low on memory, but still – we encourage to start using this feature carefully.
We are still working on providing diagnostic tools that will help you identify how much this feature actually helped - how much traffic it saved and how much memory on the server it consumed.
see #704 for more info
Public API is using C# 8 nullable reference
Most of the DotVVM API is now annotated by C#8 nullable reference types. If you are already using this C# feature, this may create bunch of new warnings when you upgrade DotVVM, but we recommend you do that as it may reveal new issues. If you are not using it, we suggest you give it a try, we have already discovered few glitches in DotVVM caused by nulls :)
Frozen config
To prevent strange behavior the entire DotvvmConfiguration
is now frozen at runtime - it can not be modified after DotVVM is initialized.
Unfortunately, this may break some of your code if you have attempted to modify some option at runtime. On the bright side, it will fail early rather than running into race conditions (or what could happen).
If you been modifying configuration just after the UseDotvvm
function, you'll have to move the config modification into a lambda argument modifyConfiguration
. For example, this works fine - the configuration is modified just before it gets frozen.
app.UseDotVVM<DotvvmStartup>(..., modifyConfiguration: c => {
c.RouteTable.Add(...);
});
Combining css classes
When binding is assigned to both class
attribute and Class-my-class
property it used to behave in quite a strange way. With this release, the classes are combined.
This will render a div
with class="a b"
<div Class-a="{value: true}" class="{value: true ? 'a' : 'x'}" />
see #783 for more info
Validation of grid view cells
We have added properties to add validators to grid view cells (for the inline-edit mode). The validator can be added by setting the property ValidatorPlacement="AttachToControl"
or ValidatorPlacement="Standalone"
(or both when separated by comma). Validator placement AttachToControl
will add the Validator.Value
to the rendered input control, placement Standalone
will place separate element after the input. To control what the validator does, you can place Validator.InvalidCssClass
and similar properties to the GridView
.
Added InlineStylesheetResource
Like the InlineScriptResource
, you can now add inline CSS (in the <style>
tag) using the InlineStylesheetResource
. Unlike the script
, style
is placed in the head
, so be careful not to add styles when rendering the page.
ItemValueBinding
(and friends) must return primitive types
We have decided to fix one design debt. Controls based on SelectorBase
control (which is ComboBox
, ListBox
, and MultiSelect
) have ItemValueBinding
. You could put any value in ItemValueBinding
- there was no validation and it caused unpredictable behavior. When the result of ItemValueBinding
was primitive type everything was fine. When the result type was a complex type the behavior got strange and there is unfortunately no way how to guarantee consistent behavior. So we have added a validation that the result type is primitive to make sure everything works fine.
"Primitive" in this case means anything that is not translated to object on client-side - which are numbers, string
and enum
s.
Redirects from static commands
You can now safely use IDotvvmRequestContext.RedirectToUrl
and IDotvvmRequestContext.RedirectToRoute
from static commands. Note that you can get the IDotvvmRequestContext
from the standard dependency injection.
API for runtime warnings
We have added infrastructure that will allow DotVVM to warn you at runtime when something suspicious happens. It will be reported to Asp.Net Core (that you'll probably see in the output of the server) and it will be propagated to JavaScript console.
For example, it will warn you if you put something inside elements that must be self-closing in HTML. We will add more of these diagnostics in future releases. It is only enabled in debug mode.
see #750 for more details (the API is described there)
StyleBuilder.SetControlProperty polishing
The SetControlProperty
method used to add new controls to properties using Server Side Styles got polished. It should now work correctly in all three mode (Overwrite
, Append
, Ignore
) regardless if the target is a control collection, a template or a single control.
You can for example add a postback handler to all buttons that satisfy some conditions:
config.Styles
.Register<LinkButton>(m => m.HasHtmlAttribute("data-hashandler"))
.SetControlProperty<ConfirmPostBackHandler>(PostBack.HandlersProperty, s => s.SetProperty(c => c.Message, "you sure?"), StyleOverrideOptions.Append)
You can also use SetHtmlControlProperty
and SetLiteralControlProperty
to easily create a html element or a simple literal.
Deserialization on client
@Mylan719 has rewritten one of the most feared piece of code in our code base - the dotvvm.serialization.deserialize
that copies a JavaScript object into the view model and wraps everything with knockout observables. Number of bugs got fixed in it, if you have encountered a strange behavior especially with static commands, it should be gone.
Specifically, you can now copy object from one property to another using static commands {staticCommand: DataSet = FetchData(SelectedCategory); Metadata = DataSet.Metadata }
.
Binding may be specified without quotes
Bindings in DotHTML files may be specified without the quotes around them (as you may be used to from React). This is now valid syntax:
<Button Click={command: MyMethod()} Text={value: MyLabel} />
Just note that if you are also using Razor/MVC, don't get too much used to this, it behaves very strangely there.
Bugfixes
RouteLink
with binding inQuery-something
property now works as expected (#779)- Redirect now works as expected when
Dictionary<string, object>
is used as query. This fixes some issues withLocalizablePresenter
. (#777) - Error are propagated correctly (i.e.
dotvvm.events.error
is called) when network is unreachable (#770 #768)
DotVVM 2.4 Preview 2
DotVVM 2.4 Preview 2
Support presenter factories on route groups #753
If you have several routes that use different presenter that DotvvmPresenter, you can now easily specify the presenter for all routes in a route group.
config.RouteTable.AddGroup("LocalizedRoutes", null, "Views", content => {
content.Add("default", "", "default.dothtml");
content.Add("About", "about", "about.dothml");
}, LocalizablePresenter.BasedOnQuery("lang"));
DotVVM 2.4 Preview 1
Support for ASP.NET Core 3.0
We have handled the breaking change in Microsoft.AspNetCore.Authorization
between 2.2
and 3.0
, and tested the framework extensively on ASP.NET Core 3.0.
DotVVM is now fully suported (and tested) on:
- OWIN and .NET Framework 4.5.1
- ASP.NET Core 2.1 (LTS - Long-term Supported release)
- ASP.NET Core 3.0 (latest release)
Our plan is to always support the LTS releases and the last stable release of ASP.NET Core.
If you are still on ASP.NET Core 2.0, upgrade soon as the minimum supported version of ASP.NET Core will be changed to 2.1 in the future.
New MultiSelect
control
DotVVM now support basic MultiSelect
control. The API is basically the same as you know from ComboBox
, except you have a SelectedValues
property. Usage is like this:
<dot:MultiSelect SelectedValues="{value: SelectedValues}"
DataSource="{value: Values}"
SelectionChanged="{command: OnSelectionChanged()}"
ItemValueBinding="{value: _this}"
ItemTitleBinding="{value: _this}"
ItemTextBinding="{value: _this}" />
Default presenter can be specified on route groups
When creating a route group, you can now use overload DotvvmRouteTable.AddGroup(string groupName, string urlPrefix, string virtualPathPrefix, Action<DotvvmRouteTable> content, Func<IServiceProvider, IDotvvmPresenter> presenterFactory)
, which allows you to specify a default IDotvvmPresenter.
With this change, you can for example specify that the routes should respect locale in the route parameter "Lang" by LocalizablePresenter.BasedOnParameter("Lang")
:
routes.AddGroup("MyGroup", "", "", table => {
table.Add("{Lang}/Route1", "something", "something.dothtml");
}, LocalizablePresenter.BasedOnParameter("Lang"))
Note that the presenter don't compose, it's not a middleware. So this route will only accept the Lang2
query parameter and always ignore the Lang1
.
routes.AddGroup("MyGroup", "", "", table => {
table.Add("Route1", "something", "something.dothtml", LocalizablePresenter.BasedOnQuery("Lang2"));
}, LocalizablePresenter.BasedOnQuery("Lang1"))
(see #753)
4096 commits
We have passed the virtual line of having 4096 merged in master branch. It does not mean anything in practise, fortunately git will still work and nothing else can be affected. So we used the very important "anniversary" to at least fix some typos 61ee3fd
Methods invoked in sequence can be async
When you make a (static) command like this: DoAsync(); Do2Async()
, DotVVM automatically waits for both of these methods to finish. If you'd need to extract the resulting value of the Task<T>
s, you can use the Result
property - {staticCommand: Property = MyMethod().Result}
.
UpdateProgress can attach to particular concurrency queues (#720)
<dot:UpdateProgress
control has got properties IncludedQueues
and ExcludedQueues
which control where the update is triggered. For example, if you have a separate queue for background requests, you don't want to display any info about it:
<dot:UpdateHandler ExcludedQueues="refreshOneGrid, refreshSecondGrid:" />
ValidationErrorFactory supports local variables (#734)
When you create validation error paths using ValidationErrorFactory.CreateModelError
or ValidationErrorFactory.CreateValidationResult
from a Linq.Expression, you can also reference local variables and it will just propagate the resulting value from them. It's mostly useful for handling array indices:
var index = SomeIndex;
this.AddModelError(a => a.List[index].MyProperty, "It's wrong.");
TextBox UpdateTextAfterKeydown changed to UpdateTextOnInput
The UpdateTextAfterKeydown
property was marked as obsolete. It was using the keypress
event which didn't work on mobile devices and in other scenarios. The framework now uses oninput
event for the same purpose.
There is also a new event called TextInput
which triggers in this case. Be careful not to trigger postbacks which transmit huge viewmodels - we encourage you to use static command with this event.
Design-Time Error Checking in CheckBox, RadioButton and ComboBox
We have added error checking for various controls that contain combination of properties whose data-binding types must match. The controls didn't work properly and sometimes their behavior was unpredictable when the types were different.
<dot:CheckBox CheckedItems="{value: _parent.SelectedIds}" CheckedValue="{value: Id}" />
The framework now checks that CheckedValue
binding type is T
and SelectedIds
type is IEnumerable<T>
(or IEnumerable<Nullable<T>>
). Similar rules apply to RadioButton
and ComboBox
.
We recommend to use Diagnostics Status Page and check that all pages in your application use these controls correctly.
CSRF token is lazy loaded (experimental)
The CSRF token can be loaded after the page is displayed.
- When the config option CsrfTokenLazyLoading is enabled, CSRF token is not rendered by default and will be requested before the first postback. This removes one source of non-determinism and may allow easier caching of entire DotVVM pages.
- In any case, when the CSRF token or Session ID is invalid (for any reason), the server returns that as a JSON error message, the client automatically asks for a new token and retries the postback.
To enable this feature, you must enable it in DotvvmConfiguration.ExperimentalFeatures.LazyCsrfToken
:
config.ExperimentalFeatures.LazyCsrfToken.EnableForRoutes("AdminPage", "AnotherPage")
// or
config.ExperimentalFeatures.LazyCsrfToken.EnableForAllRoutes()
Allowed strange chars in attribute names (#727)
It should be now OK to use square []
and round ()
brackets in attribute names, for example <span [text]="..." />
. It may help when working with some client-side templating.
Improved performance of ValidationSummary (#734)
We have redesigned a bit how the client-side validation works. The errors are not stored in a knockout observable anymore, changes in validation errors can be observed using the validationErrorsChanged
event. If you have been using validationErrors
directly, you'll have to adjust it's usage as it's not ko.observable
anymore.
Debugging and diagnostics improvements
- Error page now has Binding tab which displays information about the binding that caused the exception (if the exception is related to some binding).
- Error page crashed when some object could not be serialized.
- #700 - In Debug mode, resources in the HTML are preceded by a comment that says the name, type and location type of the resource.
- #728 - Resource with primary location being local cannot have have fallbacks.
- Improved error handling in some edge cases (6ec553e, 6d9543b).
Other fixes
- #701 - Fixed missing condition on file age in DeleteOldFiles (community contribution - thanks to @ppech).
- #714 - Circular dependencies in resources are now detected
- #740 - The promise returned by a static command is now rejected, when error occurs.
- #721 - We now culture specific globalize.js resource in case you use
ToString
in a binding. - #732 - Fixed SetValue in nested markup control.
- #725 - LinkButton does not use
href="#"
. - #698 - Fixed server-rendered Repeater (and friend controls) when the DataContext is swapped entirely.
- #731 - Resolved FormatException that occurred under strange circumstances.
- #738 - Removed suppression of errors in style attribute unless value binding is rendered.
- #742 - GetValue does not end up in an infinite cycle when custom binding is used.
- #743 -
HandleAsImmutableObjectInDotvvmProperty
attribute added to indicate shared objects for server-side styles. Validation.Enabled
property was restricted to not allow value bindings.
DotVVM 2.3
New Features
- The
context.ReturnFile
method can now specify theContent-Disposition
header. Until now, the header was alwaysattachment
. - Added
context.LocalRedirect
method which checks whether the specified URL is local. We strongly recommend using this method on all places where the user can inject his own URL to redirect - e.g.Account/Login?returnUrl=something
GridViewDataSet
methods that apply sorting and paging operations onIQueryable
were made public to allow writing theLoadFromQueryableAsync
extension method. See #688.- Added infrastructure for rendering
script[type=html]
templates. This will be useful for control developers using the Knockout template binding, especially DotVVM Business Pack.
Fixes
- Fixed error in
IncludedInPage
property when the resource binding was used. - Validation errors collection was not cleared when some parts of the viewmodel were set to
null
or reinitialized with new objectS. The validator binding handlerupdate
method was not used at all. Validator.InvalidCssClass
functionality didn't work properly for multiple CSS classes and didn't remove all classes in some situations.- Fixed XSS vulnerability in registration of DotVVM polyfill resources.
Breaking changes
- CheckBox was rendering different HTML structure for the case when the text was empty. This structure did not include the
label
element, that is in most cases used as a base element for restyling of the checkbox design. Now, thelabel
element is rendered in both cases.
DotVVM 2.2
TL;DR; There are some new minor features. The most important point is Validation - EnforceClientFormat, which may break some existing code if it is using DateTime
or nullable numberic type in view model.
New features
Binding Cache
We have added caching interface IDotvvmCacheAdapter
that provides access to built-in caching mechanism on Asp.Net Core or OWIN that reflect memory usage on your server.
ValueBindingExpression.CreateThisBinding
is now cached, so it's invocation should be quite cheap.
When you want to create binding at runtime you can now use a helper method DotvvmBindingCacheHelper.CreateCachedBinding
that makes sure that the binding is not recreated every time. Creation of bindings is usually time-consuming, so it should not be done on every request. (more info in PRs #672 and #664)
By the way, we have also (hopefully) improved the error messages when something fails with binding. When an error page is displayed for a binding-related exception, there is a new tab Binding that shows some information about the binding (data context, type, ...). Let us know what you think about that and what could be improved.
Validation
ValidationErrorFactory.CreateValidationResult<T>(ValidationContext validationContext, ...)
Overload that does not require explicitDotvvmConfiguration
Session cookies are SameSite
This was sometimes the case before. It means that postbacks won't work in third-party iframe
s (so your application should be safe from clickjacking).
Fixes
Validation - EnforceClientFormat
This part is a fix and unfortunately a breaking change at the same time. In older versions, DotVVM did not validate that DateTime and numeric fields were valid on the client-side and sent null to the server in that case. It could be enabled by EnforceClientFormatAttribute
, but nobody really did. It is now by default enabled on nullable numeric types, DateTime, and DateTime?, so it enables validation in cases where it was disabled previously. While this has a potential to "fix" existing code as not validating the input is likely a bug, it may also break some code that relied on that behavior. Please make sure that all your views using nullable DateTime and numerics work as expected. (more info in PR #666)
For example, suppose you had a dot:TextBox
bound to a property of type int?
. The problem is that when you paste value like "asd"
, it will write a null value into the property because "asd"
is not a valid numeric value. The solution for this problem was applying EnforceClientFormatAttribute
to the property in your view model. Now, you don't have to do that anymore. If you use that attribute somewhere, you can safely remove it.
Repeater control initialization
We have change a bit how the Repeater initialization works. Controls with templates have to initialize the control tree before it is used by command invocation and HTML rendering and when this initialization is dependent on data from view model, it has to be done twice on postbacks - once before command invocation and then before rendering since the command may have changed the data. In older version Repeater have not done that in all cases, because it's quite time-consuming. Unfortunately, in some cases, it broke some code, so we are now re-initializing it two times, but only in case the data is actually changed. (more info in #653)
Unique id generation for nested trees
If you were creating controls at runtime, you may know that before adding more child controls into the newly create control has to be added to the control tree. The reason was, that the mechanism that generates unique ID (for control command and Postback.Update
) did not work correctly when entire subtree was added at once. From this version, this should work correctly, so you can initialize entire subtrees at once. (more info in #668)
dot:RouteLink
in Events.Click
container
It should now get precedence over the Events.Click
handler. (more info in #630)
DotvvmAuthenticationHelper.ApplyRedirectResponse
Fixed in DotVVM 2.2.0.2
When you installed Microsoft.Extensions.DependencyInjection
2.1.0 or higher in your application and used DotvvmAuthenticationHelper.ApplyRedirectResponse
, this method was throwing an exception with a message that ServiceProvider had been disposed.
netstandard assembly loading on .NET Framework 4.7.1+
Fixed in DotVVM 2.2.0.2
DotVVM View compilation on .NET471+ was not able to load netstandard assembly.
DotVVM 2.1
New features
- Improved server-side rendering for
Repeater
andGridView
controls - Enhancements in Server-Side Styles (for example adding postback handlers to controls)
ValidationErrorFactory.CreateValidationResult
now doesn't requireDotvvmConfiguration
- REST API client generator generates meaningful C# class name for the API client
Perf improvements
- Performance tweaks in
HtmlWriter
andDataItemContainer
Repeater
performance improved using memoization to prevent frequent rebuilding of control treeHtmlWriter
performance improvements- Control properties collection uses perfect hashing to improve performance
Bug fixes
- Fixed
IncludeInPage
rendering - Fixed
_index
variable issues in controls with server rendering - Fixed HTTP response on invalid HTTP method
- Client-side validation errors are cleared before a new object is validated
- Fixed dependency injection into markup controls
- Fixed array access JavaScript translation
- Fixed generating of unique IDs for
GridView
sort commands - Fixed number formatting for zero values
- Fixed
_api.RefreshOnChange(..., Prop1 + Prop2)
which allows watching for multiple properties - Fixed bug with resource bindings in markup controls
- Fixed serialization of control property values in markup controls
- REST API bindings - API URL can be parameterized from the code
- Fixed null assignments for complex types in static commands
DotVVM 2.0.3
New features
- Default ControlRegistrationStrategy now includes subfolders
- Prohibited hardcoded values on DataContext
EmailAddress
attribute now supports client-side validation
Bug fixes
- Fixed bug in dotvvm.events.unsubscribe
- Fixed number formatting bug with zero values
- Fixed data-binding issue of hard-coded values into markup controls
- Fixed invoking generic methods from static commands
- Fixed data context handling for some GridViewColumn properties
- Fixed null reference exception in detection of data context changes
- Fixed byte array serialization