Skip to content

DotVVM 4.3

Compare
Choose a tag to compare
@exyi exyi released this 14 Sep 10:57
· 155 commits to main since this release
b6cc7e8

DotVVM 4.3 includes two new built-in controls — ModalDialog and AddTemplateDecorator; a major upgrade of the routing system — route localization; better system for warnings; a dozen of new JS translations; and a number of bug fixes and performance improvements, such as the postback request compression.

Potential breaking changes

First, we present to you the bad news. Although we try to limit the number of breakages in minor versions, it if often impossible to fix serious glitches without changing the behavior of some components:

  • Client-side dotvvm.state object is now frozen. Its modification will throw an exception when in JS strict mode (#1782). Previously, the modification was silently ignored.
  • Newtonsoft.Json was updated to 13.0.3
  • Removed a redundant Microsoft.CodeAnalysis.CSharp dependency from DotVVM.AspNetCore. You might need to explicitly add it back if your application needs the package.
  • If two @property directives define a property with the same name, an error is issued.
  • Controls registered using AutoDiscoverControls now use relative file paths instead of absolute paths in the Src property (#1817)

If you encounter any other regressions, please let us know, as they would most likely be accidental.

dot:ModalDialog - wrapper for the HTML <dialog> element (#1776)

DotVVM now includes a dot:ModalDialog control which wraps the new native HTML <dialog> element. It does not replace the dialogs in Bootstrap or BusinessPack, as it isn't styled.

<dot:ModalDialog Open={value: ShowDialog} CloseOnBackdropClick>
    content
</dot:ModalDialog>

dot:ModalDialog only supports the modal version of <dialog>, as the non-modal version is accessible through basic HTML with a bidning in the open attribute - <dialog open={value: ShowInlineDialog}>

New dot:AddTemplateDecorator control (#1760)

dot:AddTemplateDecorator is a new decorator which can prepend or append content to the decorated element. For example, you might use it to add an additional row to each entry in a grid view. In the following snippet, we use this to add a separate row for a description field, which is otherwise too long to fit into a table column.

<dot:GridView DataSource={value: MyTable}>
    <RowDecorators>
        <dot:AddTemplateDecorator>
            <AfterTemplate>
                <tr> <td colspan="8">{{value: Description}}</td> </tr>
            </AfterTemplate>
        </dot:AddTemplateDecorator>
    </RowDecorators>
    <Columns>
        ...
    </Columns>
</dot:GridView>

Localizable routes (#1824, #1840)

DotVVM now has a mechanism for localizing the route URLs. First, you need to apply a middleware which sets the correct CurrentCulture based on url prefix or the Accept-Language header.

Based on CurrentCulture, DotVVM will decide to which language should the route URL match. By default, DotVVM does not consider alternative languages. You can reconfigure it to accept alternative URL languages or to redirect to the "correct" language variant.

In the following example, we register a localized route and configure DotVVM to redirect if the route language does not match the selected language. If we take requested culture from Accept-Language or a cookie, we probably want to redirect users to the URL language of their preference:

config.RouteTable.Add("MyLocalizableRoute", "localizable-route", "Views/LocalizableRoute.dothtml",
    localizedUrls: [
            new("cs", "lokalizovana-routa"),
            new("de", "lokalisierte-route"),
    ]);
// redirect to a matching language based on CultureInfo.CurrentCulture
config.RouteTable.AddPartialMatchHandler(new CanonicalRedirectPartialMatchRouteHandler());

Related to route localization, we have added the dot:AlternateCultureLinks control which automatically generates <link rel=alternate> elements pointing to the alternative language variants.

Warnings

The Compilation Status Page normally available at _dotvvm/diagnostics/compilation now lists the warnings and errors of all compiled views. We strongly recommend you to examine the compilation page after upgrading, as it might uncover many mistakes in the application. Thanks to these warnings, we have fixed tens of small UI glitches on one of our systems, which were caused by wrong usage of some DotVVM properties. (related forum post, #1762)

The Control usage validation API now allows controls to emit custom warnings (#1751). For instance, you might want the user about a potential issue, such as specifying a redundant property:

[ControlUsageValidator]
public static IEnumerable<ControlUsageError> ValidateUsage(ResolvedControl control)
{
    if (control.Properties.ContainsKey(LabelProperty) && control.Properties.ContainsKey(SomeTemplateProperty))
    {
        var propertyNode = control.GetValue(LabelProperty).DothtmlNode;
        yield return new ControlUsageError("Label is ignored when SomeTemplate is also specified.", DiagnosticSeverity.Warning, propertyNode);
    }
}

POST compression (#1766)

DotVVM 4.3 will use gzip to compress the command and staticCommand request bodies. As the requests are in JSON, the performance gain is quite significant if you aren't on gigabit Ethernet.

However, accepting compressed requests carries a risk of exposing the web server to "compression bomb" DOS attacks. To limit the potential impact, DotVVM now limits the maximum (uncompressed) postback size to 128 MiB, and the limit may be configured in config.Runtime.MaxPostbackSizeBytes (it doesn't affect file upload). Postback compression may also be disabled using the config.Runtime.CompressPostbacks option.

Note that request compression is only enabled in Production environment, because browsers are currently unable to display the uncompressed JSON in devtools.

Other improvements

  • Markup file recompilation can be enabled in Production mode using the DotvvmConfiguration.Runtime.ReloadMarkupFiles option.
  • Changed operation name in DotVVM.Tracing.ApplicationInsights to the current route URL template (#1807, thanks to @mirecad)
  • JS translations now avoid throwing exception even when the .NET equivalent does throw.
  • New JS translations
    • IEnumerable.Last, IEnumerable.First
    • Dictionary.GetValueOrDefault
    • TimeOnly.Hour, Minute, Second, Millisecond, FromDateTime
    • DateOnly.Year, Month, Date, FromDateTime
    • DateTime.Now, UtcNow, Today
  • GridViewColumn.Visible now accepts a resource binding (#1826)
  • Added methods for compiling command and resource bindings from string to BindingCompilationService.Cache (#1839)
  • Client-side DotVVM logging may be configured using the dotvvm.logging.setLogger function. Note that the exact wording of log messages is not stable and may even differ in Development and Production environments.
  • Performance improvements, mainly HTML encoding in HtmlWriter thanks for the vectorized IndexOfAny implementation (#1851)
  • InlineScriptResource can now produce <script type=module when module parameter is specified.
  • Prevent double postbacks after redirect in Deny or Queue PostBack.Concurrency mode by pretending that the redirect takes 5 seconds. Before those 5s pass, the page most likely unloads and the user does not get the chance to submit the duplicate postback (#1853)
  • Improved error messages (#1731, #1748, #1763, #1772, #1804, #1806)

Bugs/glitches fixed

  • The client-side ViewModel is now restored on back/forward navigation (fixed in Chrome) and not restored on page reload (fixed in Firefox) (#1848)
  • DotVVM.AspNetCore does not depend on Microsoft.CodeAnalysis.CSharp (#1743)
  • Lambda argument type inference works for custom delegates (#1752)
  • The "Force recompile all" button in the Compilation Status Page now actually forces rebuild of all pages (#1759)
  • Fixed overload resolution of generic methods with default arguments (#1761)
  • Fixed support for client-side property names which are not valid JS identifiers (#1790)
  • Client-side validation is now correctly performed on typed objects inside a untyped object (#1803)
  • (#1816)
  • Controls registered using AutoDiscoverControls now use relative file paths (#1817)
  • Remove defer attribute from <script type=module element as it is redundant and invalid HTML
  • Limit the number of queued Tasks when doing pre-compilation to avoid stalling the ThreadPool (#1843)
  • Fixed the CopyProperty method to work with inherited properties containing bindings (#1850)

Thanks to @tomasherceg, @Mylan719, @mirecad, @exyi for contributing to this release