Skip to content

Releases: riganti/dotvvm

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

DotVVM 2.0.2

02 Sep 12:13
Compare
Choose a tag to compare

New features

  • Support of Microsoft.Extensions.DependencyInjection v2.0
  • Guid operations can be used in value bindings - for example GuidProp != Guid.Empty ? GuidProp.ToString() : ''
  • Added SuppressPostBackHandler which can disable command on a particular control
  • Improved translation of arguments in postback handlers
  • Routes in Route Groups can have empty virtual path
  • Script resources preloading

Bug fixes

  • Error page is displayed in debug mode on error from static commands
  • Fixed disabling of postbacks for LinkButton control in some browsers
  • Fixed issue with view compilation on .NET 4.5.2 and newer
  • Fixed serialization of negative long numbers
  • Fixed rendering of ContentTemplate inside GridView columns
  • Fixed resolving properties from inner classes in resource binding
  • Fixed bug with using ITemplate in markup controls

DotVVM 2.0.0

12 Aug 17:31
Compare
Choose a tag to compare

Main new features

  • REST API Bindings - DotVVM allows interacting with REST APIs directly from the DOTHTML views
  • Static Command Services - is a feature which allows injecting of a C# class in the page using @service directive and calling its methods using Static Command Binding.
  • PostBack Concurrency Modes
  • _collection Context Variable
  • New Binding System - mostly internal change but really huge.
  • Postback Handlers infrastructure rewritten

Upgrading from DotVVM 1.0 to DotVVM 2.0

See migration guidelines: https://www.dotvvm.com/docs/tutorials/how-to-start-upgrade-to-2-0/2.0

To review all changes, please see preview releases of DotVVM 2.0.

DotVVM 2.0.0-preview02-final

15 Mar 00:31
Compare
Choose a tag to compare
Pre-release

Breaking changes

DotVVM Registration

Signature of registration methods was changed. The reason is to be able safely execute registration of dotvvm services in compiler.
We introduced new interface called IDotvvmServiceConfigurator. This interface includes method void ConfigureServices(IDotvvmServiceCollection services). This method should includes all registrations of services needed for runtime of dotvvm. This part of code is called from compiler really often.

Warning: Avoid to init Entity Framework, calling API, sending emails and similar actions. Method void ConfigureServices(IDotvvmServiceCollection services) is meant only for registration of DotVVM

OWIN

The parameter IDotvvmOptions options was removed from signature of app.UseDotVVM() method. This functionality was moved to IDotvvmServiceConfigurator. You can simply implement IDotvvmServiceConfigurator interface on your DotvvmStartup.cs or you can create another class. If your DotvvmStartup implements this interface then a generic parameter TDotvvmStartup from app.UseDotVVM<TDotvvmStartup>() internally casts the DotvvmStartup as IDotvvmServiceConfigurator.

We introduced new overload app.UseDotVVM<TDotvvmStartup, TDotvvmServiceConfigurator>() in case you want to implement IDotvvmServiceConfigurator to separated class.

AspNet Core

The same change as for OWIN was made on function IServiceCollection AddDotVVM<TServiceConfigurator>.
The IDotvvmOptions options parameter was removed and replaced by generic type that expects implementation of IDotvvmServiceConfigurator.

DotvvmConfiguration

Debug property can be modified only in IDotvvmStartup and registration method app.UseDotVVM(). When you try to modify Debug property after initialization it throws exception.

Resources

Removed jQuery resource

In an effort to make DotVVM less depended we have removed jQuery resource. If you need it simply add jquery to you project and register in DotVVM configuration config.Resources.Register("jquery", new ScriptResource() { ... }.

Routes

Method config.RouteTable.Add() contained parameter type of Func<IDotvvmPresenter> . This signature of the parameter was change to Func<IServiceProvider, IDotvvmPresenter>. Now we provide an instance of IServiceProvider in factory method.

Some of Javascript API changes

  • dotvvm.postBackHandlers was renamed to dotvvm.postbackHandlers

DotVVM 2.0.0-beta01

23 Jan 11:52
Compare
Choose a tag to compare
DotVVM 2.0.0-beta01 Pre-release
Pre-release

Binding Properties

see Binding System Refactoring #341

  • Better Javascript translator
  • In the ViewModelSerializationMap it's possible to rename properties for client-side and JavascriptTranslator will translate it correctly, use Bind(Name = "MyName") attribute
  • Null checks in binding were previously done by try ... catch, which also caught exception inside called functions. Now it is done by real checks, so inner exceptions are propagated correctly
  • Binding can be transferred from one control to another in different data context and they will still evaluate and translate to JS correctly
    • This means that you can use inherited properties to transfer dependencies into your markup control even though they are deeply nested
    • You can even use MarkupControls recursively, just make sure they are server-rendered
  • Super cool extensibility
    • Extension parameters like _collection, _index and _api are just a tip of the icebergs ;)
  • Bindings have ResultType property accessible at runtime
  • Controls have DataContextType property accessible at runtime
  • Command Binding IDs are "more" unique and less readable

Function Arguments in Bindings

All bindings now have an implicit conversion to a delegate - essentialy, when the expected type is a delegate, the binding is wrapped in lambda. In Javascript it's represented as a function. And when the delegate contains any parameters, these get registered as additional symbols to the parser. For example to set (a) => a + 1 into a property of type Func<int, int> you can use {value: arg + 1}

To use the parameters with staticCommand you can set the commandArgs symbolic parameter (the same way you'd do with command binding)

REST API

DotVVM allows interacting with REST APIs directly from the DOTHTML views. You can fill GridView, Repeater and other controls with data from the REST API, and use Button or other controls to call REST API methods as a response to user action. It is also possible to refresh data that have already been loaded (in the GridView for example) based on a change of a particular viewmodel property, or explicitly.
See: https://www.dotvvm.com/docs/tutorials/basics-rest-api-bindings/2.0

Model state helpers

You can just viewModel.AddModelError(v => v.MyObject.PartOfTheForm.Property3, "It's invalid") instead of creating JS evaluatable string path

Controls improvements

  • ComboBox.ItemValueBinding and ItemTextBinding - use them instead of ValueMember and DisplayMember
  • TextBox.ValueType is obsolete, it's infered from result type of Text property

string.Format in value bindings

string.Format method is correctly translated to Javascript. You can also use [primitive type].ToString("Format") method - this one is also two-way, so it's possible to use it instead of FormatString property on TextBox.

Route Groups

see #363

you can register routes in groups with specified path and id prefixed to prevent repetitive literals and help with visual code orientation:

routes.AddGroup(name: "Admin", prefix: "admin", virtualPath: "Views/Administration", content: adminRoutes =>
{
    // adminRoutes is of type RouteTable
    adminRoutes.Add("Users", "users", "Users.dothtml"); // name = Admin_Users, path = "admin/users", virtualPath = "Views/Administration/Users.dothtml"
    adminRoutes.Add("Articles", "articles", "Articles.dothtml");
});

Dependency Injection into controls

It works in two modes:

  • Simple/intuitive/automatic/hipster mode - when the control does not have a parameterless constructor, it is initialized from the default IServiceProvider. It is used mainly for infrastructure controls that need to get some dotvvm service, for non-control DotvvmBindableObjects that need or on Asp.NET Core projects that use the default DependencyInjection properly.
  • Explicit/enterprise mode - when the control is marked by [RequireDependencyInjection] it is created using resolver registered in the default IServiceProvider. You can use it if you want services from your separate container or need some weird injection features, like property injection

Dependency Injection into dothtml views

You can require a service using @service directive. It is mainly useful for Asp.Net Core ILocalizer interface and for calling static commands. The service usage can't be translated to Javascript, so usage in value binding will throw an exception.

@service myService = IMyService<string>

{{resource: myService.SomeProperty}}

{{command: myService.DoSomething()}}

Markup controls packed into dlls

Markup file loaded supports embedded://...assembly name/...name of the resource syntax for referencing embedded resources from view or markup control registration. It should allow you to pack dotcontrol files into the dll and distrube them in a library. The files are referenced as the original source code and have to be compiled in the target project, so you can apply compile-time styles to them.

IncludeInPage property

Just a wrapper for knockout if binding handler.

FormControls.Enabled property

proposed in #296, PR #433

Added a FormControls.Enabled attached property which disables controls inside that are not explicitly enabled.
Controls affected

  • in DotVVM - Button (ButtonBase), CheckBox (CheckableControlBase), ComboBox (SelectorBase), DataPager, LinkButton (ButtonBase), ListBox (SelectorBase), RadioButton (CheckableControlBase), TextBox
  • in Bootstrap - Button, CheckBox, DataPager, RadioButton, TextBoxGroup
  • in Business pack - Button, Calendar, CheckBox, CheckBoxList, ColorPicker, ComboBox, DataPager, DateTimePicker, DateTimeRangerPicker, DropDownList, MultiSelect, NumericUpDown, RadioButton, RadioButtonList, RangeCalendar, RangeSlider, Rating, Slider, TextBox

Example

<div FormControls.Enabled="{value: false}">
    <dot:Button Text="I am disabled" />
    <dot:Button Text="I am enabled" Enabled="{value: true}" />
</div>

dot:BodyResourceLinks and dot:HeadResourceLinks

When you use one of these controls in page, the resources will be render in location that is defined by the control. Only the first control on the page is activated to prevent accidential multiple times included scripts.

LocalizablePresenter

It's a utility for easy localization based on query string or route parameters. It just sets the Threads
current culture.

// based on query string parameter lang, `myPage?lang=cs-CZ` will be in czech culture
config.RouteTable.Add("myRoute", "myPage", "myPage.dothtml", presenterFactory: LocalizablePresenter.BasedOnQuery("lang"));

// based on parameter lang, `cs-CZ/myPage` will be in czech culture
config.RouteTable.Add("myRoute", "{lang}/myPage", "myPage.dothtml", presenterFactory: LocalizablePresenter.BasedOnParameter("lang"));

By default, it redirects to a default culture when a invalid code is specified, you can disable that using redirectWhenNotFound parameter.

see #513

Custom constuctor for serializer

On a IViewModelSerializationMapper, you can set your own method to create a new instance of the viewmodel.

mapper.Map(m => {
	// create from Asp.Net DI
	m.AllowDependencyInjection();
	// custom constructor
	m.SetConstructor(serviceProvider => SomehowCreateViewModel(serviceProvider))l
});

Ben.Demystify for the error page

By default, the error page uses Ben.Demystify library to show nicer stack traces.

Implemented CSS style bindable

Added Style-* property group that generates the style knockout binding. I'm not sure what type should I use for the property group, currently there is object.

Usage example:

<div Style-color="{value: Color}" Style-display="{value: Condition ? 'none' : 'inline-block'}"/>
<div style="background-color: green;" Style-width="{value: Width + 'px'}"/>

see #572

DotVVM 1.1.8

25 Dec 16:58
Compare
Choose a tag to compare

Fixes

  • Validation errors are cleared before SPA navigation starts
  • ViewModel and dependencies are disposed in finally block.
  • Fixed route url parser with optional parameter at start of url