Releases: riganti/dotvvm
DotVVM 5.0.0-preview01 release
Major changes
- Migration to System.Text.Json
- More extensible GridViewDataSet
- the refactoring should be mostly compatible, if you didn't write your own DataPager and encounter issues, please get in touch with us
- it is now possible to use GridView and DataPager which load data using
staticCommands - it is now possible to use token-based paging instead of just page index
- it is now possible to use custom sorting options which limit what columns can be used for sorting
- DataContext and DataSource properties support resource binding
- it makes it possible to show server-rendered collections without also sending all of the data in JSON, and without including any knockout data-bind attributes in the HTML
We'll have more polished release notes with the 5.0.0 stable version
List of merged PRs
- Data pager extensibility improvements in #1819
- Refactoring of GridViewDataSet in #1548
- Fix near page indexes crashing on invalid page number in #1847
- Initialized service provider in validation context. in #1869
- Binding translation issue in PostBackHandler properties in #1878
- Fix resource bindings in GridViewColumn.FormatString in #1879
- Fixed ambiguous namespace resolution and matching non-public types in #1877
- Fix ko.observable handling in Linq translations in #1870
- Use System.Text.Json as a backend for view model serialization in #1799
- Fix leaking of original object from ko.observableArray in #1893
- Export the JS StateManager instance in #1894
- Fix excessive allocations in EmbeddedResourceFileLoader in #1888
- Remove the obsolete context.IsPostback setter in #1899
- Enable UseDotvvmSerializationForStaticCommandArguments by default in #1898
- Fix control prefixes in error page "Control Hierarchy" section in #1901
- Bug in JS translator when using Where and using lambda in commands in #1903
- MultiSelect issue with updating observable array fixed in #1910
- Basic support for DataContext={resource: ...} in #1392
- Special-case parsing of <script> and <style> elements, similarly to HTML in #1900
- Bump .NET Core dependency to net8.0 (and net9.0 in aspnetcorelatest) in #1917
- Add option to disable DotVVM serialization for specific types in #1916
- Disallow assigning to init-only properties in bindings in #1909
Full Changelog: v4.3.0...v5.0.0-preview01
DotVVM 4.3.6 bugfix release
DotVVM 4.3.5 bugfix release
- Fix leaking of original object from ko.observableArray when using methods like
.push, ... (see #1893 for more details) - Expose
dotvvm.rootStateManagerAPI, most importantly making it possible to force immediate refresh knockout observable values (this allows us to fix some bugs in BusinessPack)
DotVVM 4.3.4 bugfix release
DotVVM 4.3.3 bugfix release
- PostBack Handlers
- Fix references to _parent (and higher) view models in the postback handler properties
- GridView Columns
- Fix
resourcebinding in the FormatString property
- Fix
Sec-Fetch-Destvalidation- Include info about issues with site prefetching
DotVVM 4.3.2 bugfix release
DotVVM 4.3.1 bugfix release
- Validation
- ValidationContext (used in IValidatableObject) has an initialized IServiceProvider (#1869)
- Analyzers
- DotvvmCapabilityProperty
DotVVM 4.3
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.stateobject 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
@propertydirectives define a property with the same name, an error is issued. - Controls registered using
AutoDiscoverControlsnow use relative file paths instead of absolute paths in theSrcproperty (#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.ReloadMarkupFilesoption. - 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.FirstDictionary.GetValueOrDefaultTimeOnly.Hour,Minute,Second,Millisecond,FromDateTimeDateOnly.Year,Month,Date,FromDateTimeDateTime.Now,UtcNow,Today
GridViewColumn.Visiblenow accepts aresourcebinding (#1826)- Added methods for compiling
commandandresourcebindings from string toBindingCompilationService.Cache(#1839) - Client-side DotVVM logging may be configured using the
dotvvm.logging.setLoggerfunction. 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
HtmlWriterthanks for the vectorizedIndexOfAnyimplementation (#1851) InlineScriptResourcecan now produce<script type=modulewhenmoduleparameter is specified.- Prevent double postbacks after redirect in Deny or Queue
PostBack.Concurrencymode 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
AutoDiscoverControlsnow use relative file paths (#1817) - Remove
deferattribute from<script type=moduleelement 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
CopyPropertymethod to work with inherited properties containing bindings (#1850)
Thanks to @tomasherceg, @Mylan719, @mirecad, @exyi for contributing to this release
DotVVM 4.2
Potential breaking changes
DotVVM 4.2 should generally be source compatible with the previous 4.1 version. We did not preserve binary compatibility, so please make sure all other DotVVM packages are at 4.2 version (especially if you see a MissingMethodException or similar error). Please let us know if we forgot to update some of our packages. We also had to change the behavior in ways which could in theory break something
- The type hashes (the client-side type metadata id) might be different. You might need to adjust if you have it hardcoded somewhere. (see #1614, should only affect generic types)
- HtmlGenericControl and RadioButton now attempts to render both the server-side value and client-side binding regardless of RenderSettings.Mode. If you relied on the value not being pre-rendered on the server, please explicitly use
_page.EvaluatingOnServer ? null : OriginalExpression. To render value server-side only, switch to aresourcebinding. - Using a non-DotvvmProperty defined on a markup control is now a compile-time error (in value bindings). It used to only fail client-side
- DotVVM does not reload dothtml files when run in
Productionenvironment (whenDotvvmConfiguration.Debug=false). JsComponentis always initialized asynchronously (see #1684)- View Modules are always initialized after dotvvm is initialized
- Operator precedence of
&&and||now behaves the same as in C# - Unopened closing tag used to close all currently open elements -- for example in
<a></b>thebtag closed theatag. This glitch caused all sorts of problems, so we changed it to not close any elements. RadioButton.Checkedis deprecated, please useCheckedValueandCheckedItemproperties (the property never worked, but now it might fail compile-time if used incorrectly)
staticCommand validation
Server-side validation now works in staticCommand methods. The validation has to be enabled using [AllowStaticCommand(StaticCommandValidation.Manual)] or [AllowStaticCommand(StaticCommandValidation.Automatic)] attribute. In the Automatic case, all arguments will be recursively validated using DataAnnotations attributes and IValidatableObject.Validate will be called. In both cases, additional validation errors can be returned using the StaticCommandModelState class:
[AllowStaticCommand(StaticCommandValidation.Manual)]
public string MyMethod(MyModel model)
{
var modelState = new StaticCommandModelState();
modelState.AddArgumentError(() => model.Property, "Property is invalid");
modelState.FailOnInvalidModelState();
}Enabling the validation will make the staticCommand invocation clear all validation errors currently being shown client-side. Note that client-side validation isn't currently implemented, so all invocation will round-trip to the server.
See related forum post for more examples.
Custom primitive types
In order to better support typed IDs, DotVVM now has support for custom primitive types. These types are always represented as a string client-side, which makes them allowed in places only for primitive types - notably SelectedValue property on selector components, but also in route parameters, and html attributes.
The custom primitive type must have ToString() and static TryParse(string, out T) methods. It must also implement the IDotvvmPrimitiveType interface. It's only a marker interface, since ToString method present on all types, and TryParse method is static and we can't use interface static methods due to support for the old framework. The type can be a class, a struct or a record.
A simple typed ID type could look like the following:
public struct OrderId: IDotvvmPrimitiveType
{
public int Value { get; }
public OrderId(int value)
{
this.Value = value;
}
public override string ToString() => Value.ToString();
public static bool TryParse(string value, out OrderId result)
{
if (int.TryParse(value, out var resultValue))
{
result = new OrderId(resultValue);
return true;
}
result = default;
return false;
}
}WebForms adapters
We have made a new package which helps in the process of migrating Web Forms apps to the new .NET using DotVVM - DotVVM.Adapters.WebForms. It currently contains HybridRouteLink control and RedirectToRouteHybrid extension method.
- The
<webforms:HybridRouteLink>control has the same functionality as theRouteLinkcontrol, but it falls back to Web Forms routes when a requested DotVVM route doesn't exist (which means that the page hasn't been migrated yet). - The
RedirectToRouteHybridextension method of theIDotvvmRequestContextalso falls back to the Web Forms route in case the DotVVM route doesn't exist.
The package also works on .NET Core, where these fallbacks are disabled (because of the absence of System.Web). This allows to keep using the API even after the migration is finished.
state, patchState, setState, updateState in JS View Modules
We have added the state property and the following methods to the global dotvvm object, viewmodel knockout observables and JS module context (DotvvmModuleContext)
state- returns the current value of the view modelsetState(newValue)- replaces the current valuepatchState(newValues)- replaces only the specified properties, for examplepatchState({ UserName: "new-user" })updateState(currentValue => computeNewValue(currentValue))- applies the specified function onto the current view model
See simplified view model API in JS Modules on forum.dotvvm.com for more details and some context.
Knockout deferred updates (experimental feature)
DotVVM uses knockout.js to immediately synchronize the view model into the HTML DOM. Knockout essentially does this by subscribing to an update event on each view model variable which is used in the binding. When any value inside the view model is changed, all bindings using the value immediately get a notification and update the bound DOM element.
This normally works well, but if the binding uses very many different variables it can get equally many notification if large part of the view model gets changed. For example, you can have a binding which enumerates an array by counting number of certain elements in an array ({value: MyArray.Count(a => a.IsSpecial)}). Each array element is a separate viewmodel value, so the binding with get up to MyArray.Length update notifications, each time evaluating the binding and updating the DOM element. This mean we have got O(n^2) worst case complexity for updating the view model, which can be really slow (in some cases).
Knockout has got an ko.options.deferUpdates = true option, which makes the updates asynchronous and deduplicates the notifications. Updating all array elements will then lead to just one DOM update (with a slight delay). It was always possible to enable this option, in 4.2 we made it easier to enable and fixed a few bugs in DotVVM which occurred when delayed updates were enabled. The feature is still experimental, since we didn't thoroughly test it with all our components. You can enable/disable it for certain pages, if you encounter issues.
config.ExperimentalFeatures.KnockoutDeferUpdates.Enable().ExcludeRoute("SomePageThatOtherwiseBreaks");
Metrics
We instrumented DotVVM with System.Diagnostics.Metrics. All implemented metrics are listed in the DotvvmMetrics.cs file. We'd like to point out some of the important or interesting metrics:
dotvvm_viewmodel_size_byteshistogram - Size of the returned viewmodel JSON in bytes.- Labels
route=RouteNameandrequest_type=Navigate/SpaNavigate/Command/StaticCommand
- Labels
dotvvm_request_duration_seconds- Time it took to stringify the resulting JSON view model.- Labels
route,request_typeanddothtml_file - You can use ASP.NET Core statistics about request duration, this metric makes it possible to split the measurement by DotVVM route name.
- Labels
dotvvm_viewmodel_serialization_secondshistogram - Time it took to serialize view model to JSON objects.- Labels
routeandrequest_type
- Labels
dotvvm_control_lifecycle_secondshistogram - Time it took to process a request on the specific route- Labels
routeandlifecycle_type=PreInit/Init/Load/PreRender/PreRenderComplete
- Labels
dotvvm_command_invocation_seconds- Time it took to invoke a specific command method. Compared torequest_duration_secondsthis only includes the time spent in the command method, and is labeled by the executed binding (command)- Labels
commandandresult=Ok/Exception/UnhandledException
- Labels
dotvvm_staticcommand_invocation_seconds- Similar tocommand_invocation_seconds, but for staticCommand invocations- Labels
commandandresult=Ok/Exception/UnhandledException
- Labels
dotvvm_viewmodel_validation_errors_totalhistogram - Number view model validation errors returned to the client.- Labels
routeandrequest_type
- Labels
dotvvm_uploaded_file_bytes- Total size of user-uploaded filesdotvvm_returned_file_bytes- Total size of returned files. Measured when the file is returned, not when downloaded by the client
If you are using Server-side viewmodel cache you might be also ...
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
MissingMethodExceptions (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.PrimitiveTypescollection private. Please use theIsPrimitiveTypemethod. 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 CompositeControls 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-reactnpm 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.AddCssClassandcontrol.AddCssStyleextension methods now also supportValueOrBindingas 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.Creat...