DotVVM 4.1
Potentially breaking changes
While we try to keep "minor" releases free of major breaking changes, it's sometimes impossible to avoid. In general, you should not have problems updating to 4.1. If you encounter a breakage not on this list, please submit a bug report to this repository, or contact us on gitter.
- In general, we aim to be source-compatible, not binary-compatible. If you are using other DotVVM packages, make sure all are on 4.1 version; otherwise
MissingMethodException
s (or similar) might occur. - 4.0 had a bug that allowed using private members from binding. This is fixed in 4.1, so you will now get an error when a private member is used in binding expressions.
- 4.0 had a bug which treated
{ get; init; }
properties as if they had normal setter. DotVVM 4.1 will always clone the object before setting an init-only property. - We made the
ReflectionUtils.PrimitiveTypes
collection private. Please use theIsPrimitiveType
method. In case it doesn't fulfill your requirement, please contact us. We plan to add support for custom primitive types in the next release.
We recommend using the view compilation page at _dotvvm/diagnostics/compilation
after updating to check that all views still compile.
Record serialization (#1246 #1525)
DotVVM can (finally) correctly serialize and deserialize value types and records with constructor properties. F# records and single-case unions are also supported.
record UserInfo(string Name,
string Id,
string Email);
In general classes, the non-default constructor has to be marked with the constructor [JsonConstructor]
attribute. Without it, DotVVM will not automatically deserialize properties into constructor arguments, even when no other constructor is available (to avoid breaking existing code)
class C {
public string Name { get; }
[JsonConstructor]
public C(string name) {
this.Name = name;
}
}
HierarchyRepeater (#1206)
DotVVM now has a generic control for displaying hierarchies that support both client-side and server-side rendering. The following code will create a hierarchy of ul
/ li
tags from a collection of Roots
. The ItemWrapperTag (li
) only contains a template for a specific item, while LevelWrapperTag (ul
) also includes all child items.
<dot:HierarchyRepeater DataSource={value: Roots}
ItemChildrenBinding={value: Children}
LevelWrapperTagName=ul
ItemWrapperTagName=li >
{{value: Name}}
</dot:HierarchyRepeater>
Note that you can set any other attributes or classes on the wrapper tags using the Level
or Item
prefix, for example LevelClass-highlighted={value: Name == _root.HighlightedName}
.
AutoUI (#1293)
DotVVM Dynamic Data is a library that generates forms and grids automatically from your model classes. We have rewritten it using precompiled CompositeControl
s and server-side styles. This makes it much easier to extend and customize, and also eliminates performance issues the old DynamicData library had.
We renamed this new implementation as DotVVM AutoUI, as it's... an automatic UI generator, not data and not dynamic :)
The old DynamicData library still works as before, although we don't plan to develop it further.
Since there is a lot to cover, please refer to the dedicated page for more information. In short, this how the usage looks like:
<!-- create from with all the fields -->
<auto:Form DataContext="{value: EditedEmployee}" />
<!-- a table with automatic columns (we support inline editing too) -->
<dot:GridView DataSource="{value: Employees}">
<auto:GridViewColumns />
</dot:GridView>
<!-- basic form component based on data type and attributes. Includes validation -->
<auto:Editor Property="{value: Age}" />
Markup Declared Properties (#1231)
Properties of markup controls can now be defined directly in the control .dothtml
file:
@property string Name
<div class="name">
{{value: _control.Name}}
</div>
For each property, you can specify:
- A default value, for example
@property string Width = "100%"
@property string[] Classes = [ "something" ]
@property Func<int, int> GetNextId = (int i) => i + 1
- Markup options, for example
@property string Name, MarkupOptionsAttribute.Required=true
Note that @baseType
and @property
directives cannot be combined, as it could lead to ambiguities where the property is defined.
CompositeControl precompilation (#1261)
DotVVM 4.0 introduced Composite controls and made Server-Side Styles much more powerful.
DotVVM 4.1 builds on this foundation and introduces Composite control which is only evaluated once - when the page is being compiled.
This is very useful when the component needs to create and compile new bindings (like Auto UI) since that is a bit too slow to do on each request.
It also allows other server-side styles to match the generated content and customize it.
The usage is fairly simple:
[ControlMarkupOptions(Precompile = ControlPrecompilationMode.IfPossible)]
public class MyControl : CompositeControl
{
public DotvvmControl GetContents(
ValueOrBinding<string> myProperty,
string otherProperty
)
{
return ...;
}
}
This will try to create the control during page compilation, invoke the GetContents
method and replace the component with the generated control tree. The component instance won't even be created at runtime.
However, if otherProperty
contains a resource
binding, it's not possible to call GetContents
before the binding is evaluated. This is fine, the control will be evaluated at runtime normally. You might decide that for certain combinations of arguments, the precompilation is not possible and throw a SkipPrecompilationException
. Please try not to depend on cases where DotVVM automatically decides precompilation isn't possible, since we might want to add support for them in future versions. If you want to make sure the control never falls back on runtime evaluation, you can use the ControlPrecompilationMode.Always
setting.
A special mode is ControlPrecompilationMode.InServerSideStyles
which is used by AutoUI. This instructs DotVVM to build the control while server-side styles are running which allows other styles to modify the children. Normal precompiled controls are evaluated after styles are finished, in order to behave similarly to runtime controls which are also unaffected by styles.
JsComponent is stable now
DotVVM 4.0 included experimental support for integrating components written in JavaScript; as of DotVVM 4.1 we consider the React integration stable. To include a React component into a DotVVM view:
- Install the
dotvvm-jscomponent-react
npm package - Setup your favorite JS bundler (and optionally a typescript compiler) to produce ES module bundle (let's say it's called
scripts/mycomponents.js
) - Register the script for DotVVM:
config.Resources.RegisterScriptModuleFile("mycomponents-js", "script/mycomponents.js")
The module should export the components in the $controls
field
import { registerReactControl } from 'dotvvm-jscomponent-react';
import * as React from 'react';
function SampleComponent(props) {
return <span>{props.text}</span>
}
export default (context) => ({
$controls: {
SampleComponent: registerReactControl(SampleComponent),
}
})
Then you can import it in any DotVVM view or markup control using the @js
directive and use it with the <js:
tag prefix.
@js mycomponents-js
<js:SampleComponent text={value: Text} />
For more information, see the documentation page, our sample project or the sample we use as UI test.
We'd like to thank @lorencjan for thoroughly testing the dotvvm-jscomponent-react
package, many improvements have been made based on his suggestions.
We also have working Svelte integration. However, it's not published as a npm package at the moment - if you want to try it out, you can copy the integration function from our repository (yes the link correct, all the code really fits on one screen). If you'd like to try any other JS web framework, it should be quite easy to wire it into the DotVVM API. We'll definitely welcome any pull requests, but feel free to also submit an issue requesting it. If you can "only" help with testing, that's also very valuable.
Other smaller changes
- DotVVM now implements `IHeathCheck on ASP.NET Core. It checks whether all pages can be compiled. #1209
control.AddCssClass
andcontrol.AddCssStyle
extension methods now also supportValueOrBinding
as input. It will now also work when it's called multiple times with a binding. (#1274, #1354)- Control property can now be
IEnumerable<DotvvmControl>
orIEnumerable<IMyControl>
, previously it had to beList<DotvvmControl>
(#1325, #1355) BindingCompilationService.Cache.CreateValueBinding(string, DataContextStack)
: Helper method for creatingvalue
andstaticCommand
bindings (#1340)- Serialized configuration (
dotvvm_serialized_config.json.tmp
) contains more information, to make our VS Code extension work well. (#1352) control.GetDotvvmUniqueId
andcontrol.CreateClientId
allow specifying prefix and suffix (#1361)- Runtime warning for large viewmodels and long requests (#1371)
- New JavaScript API for modifying the client-side error collection (#1375)
dotvvm.validation.addErrors([{ errorMessage: "Test", propertyPath: "/X/Y/Z" }])
dotvvm.validation.removeErrors("/FirstName", "/LastName")
- Bitwise operators are supported in value bindings (for integers, booleans and enums) (#1378, #1404)
Validator.Value
now supports more complex expressions, for exampleMyDateProperty.ToBrowserLocalTime().ToString("yyyy")
will validateMyDateProperty
(#1385)- Controls can have a
PrimaryName
andAlternativeNames
, allowing for backwards compatible renames (#1388) - Server-side styles allow removing controls, for example
styles.Register<Button>().Remove()
removes all buttons from all pages (#1397) - Property groups can be used in MarkupControls (#1441)
- Compile time warning for uppercase attributes (it's probably a mistyped property) (#1443)
- React JsComponents get
setProps
function to allow writing values back (#1466) DateOnly
andTimeOnly
types are supported<dot:CheckBox
is by default set into the intermediate mode when Value is null. It can now be disabled usingDisableIndeterminate
, the checkbox will be unchecked when value is null (#1492)- We have added Security.md file, please follow the instructions if you have found a (suspected) vulnerability in DotVVM or related products
- New JS translations - methods supported in
value
andstaticCommand
bindings
Notable bugfixes
- Fixed packaging of
DotVVM.CommandLine
, fixed the CLI when project path contains whitespace. (#1350, #1351) - Fixed parsing of expressions like
A=!A
(#1374) - Encrypted values are serialized using the same settings as they are deserialized, allowing usage of more complex objects (#1391)
- Fixed number of bugs on .NET Framework, so we now run unit tests on both dotnet 6 and net471 to avoid them.
- Fixed parsing of
<![CDATA[
, easy way to escape bindings and html characters for large text - Fix resetting of half written inputs bound to
DateTime
or number (#1451) - Reworked client-side date parsing function (few times 🙂, #1450, #1503)
- Page compilation now fails when hardcoded value is written into property of type
IBinding
(instead of crashing at runtime, #1464) - Hot reload is only used in debug mode (#1468)
- Fixed issue with not attaching validation errors when
propertyPaths
could not be resolved (#1500) - Fixed building URL when query parameters contain null or empty string (#1502)
- Fixed refreshing triggers in REST API bindings (#1513)
- Fixed REST API bindings in SPA apps (#1523)
- Fixed evaluation of async commands with multiple calls when exception occurs (#1520)
- Calling private members from bindings is not allowed (#1522, the bug was introduced in 4.0, sorry if this breaks your code)
- On command, don't reset value of properties which aren't sent from server. This fixes
Direction.ClientToServerInPostbackPath | Direction.ServerToClientFirstRequest
(#1536)