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)