Skip to content

Releases: riganti/dotvvm

DotVVM 3.0

03 Apr 12:54
Compare
Choose a tag to compare

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

#908

Fixed bug in static commands with multiple server calls

#910

Progress in our effort to use non-nullable reference types

#912

Fixed URL-encoding problems in RouteLink parameters

#922

Customizable active and disabled CSS classes in DataPager

#923

Fixed issue with async command execution

#933

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

#957

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

#905

  • Objects in the viewmodel now always have the $type property which contains unique ID of the concrete type. When object without the $typeannotation 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 or dotvvmserialization.serialize methods in the client-side DotVVM, consider replacing them with the new state manager API (state property,setState and patchState functions on the observables). You can also assign plain JS objects to the viewmodel observables — they will be coerced automatically. We plan to remove the serialize 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 the isSpaNavigationError flag, and we have added a new event spaNavigationFailed that is fired in case of SPA navigation failure (network error, exception on page load etc.)
  • afterPostback — we have removed redirectPromise and handled parameters
  • spaNavigating — the newUrl parameter was re...
Read more

DotVVM 2.5

31 Oct 19:50
Compare
Choose a tag to compare

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 on DefaultSettings
  • #877 - Control developers now may create attached property groups (e. g. <element MyExtensions.SomeGroup-SomeKey="something" />)
  • #896 - The AddDotVVM and UseDotVVM methods now allow passing a custom instance of the DotvvmStartup 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

23 Aug 20:14
Compare
Choose a tag to compare
DotVVM 2.5 Preview 2 Pre-release
Pre-release

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

(#841 and #846)

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 property HideWhenValid 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 to ResourceManager 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. by SignData, the child cannot use None on any of its members. Also, if you use EncryptData, the child object cannot use just SignData.
  • #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 like class-* or Param-*) 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 use ConcurrentDictionary-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 without async/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

28 Dec 14:41
Compare
Choose a tag to compare

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(...);
});

#747

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 enums.

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.

#757

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.

#737

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 }.

#772

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 in Query-something property now works as expected (#779)
  • Redirect now works as expected when Dictionary<string, object> is used as query. This fixes some issues with LocalizablePresenter. (#777)
  • Error are propagated correctly (i.e. dotvvm.events.error is called) when network is unreachable (#770 #768)

DotVVM 2.4 Preview 2

28 Dec 14:40
Compare
Choose a tag to compare
DotVVM 2.4 Preview 2 Pre-release
Pre-release

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

18 Sep 10:32
36aad6f
Compare
Choose a tag to compare
DotVVM 2.4 Preview 1 Pre-release
Pre-release

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

21 Jun 19:43
Compare
Choose a tag to compare

New Features

  • The context.ReturnFile method can now specify the Content-Disposition header. Until now, the header was always attachment.
  • 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 on IQueryable were made public to allow writing the LoadFromQueryableAsync 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 handler update 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, the label element is rendered in both cases.

DotVVM 2.2

13 Apr 13:01
Compare
Choose a tag to compare

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 explicit DotvvmConfiguration

Session cookies are SameSite

This was sometimes the case before. It means that postbacks won't work in third-party iframes (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

28 Jan 18:14
Compare
Choose a tag to compare

New features

  • Improved server-side rendering for Repeater and GridView controls
  • Enhancements in Server-Side Styles (for example adding postback handlers to controls)
  • ValidationErrorFactory.CreateValidationResult now doesn't require DotvvmConfiguration
  • REST API client generator generates meaningful C# class name for the API client

Perf improvements

  • Performance tweaks in HtmlWriter and DataItemContainer
  • Repeater performance improved using memoization to prevent frequent rebuilding of control tree
  • HtmlWriter 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

21 Dec 19:25
Compare
Choose a tag to compare

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