Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/Upgrading to CSLA 11.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,47 @@ If you are upgrading from a version of CSLA prior to 10, you should review the [

CSLA 11 supports .NET 10 and .NET 11, and continues to support .NET Framework 4.6.2 and later. CSLA 11 no longer targets .NET 8 or .NET 9.

On .NET 11, Android apps that use `Csla.Maui` require Android API level 24 or later, because .NET 11 for Android requires it. The `net10.0-android` target still supports API level 21.

## Source Generators Bundled in the Csla Package

The CSLA source generators now ship inside the `Csla` NuGet package and run automatically in any C# project that references `Csla` ([#4359](https://github.com/MarimerLLC/csla/issues/4359), [#4925](https://github.com/MarimerLLC/csla/pull/4925)).

### Remove the retired generator package

The `Csla.Generator.AutoImplementProperties.CSharp` package is retired. Referencing it alongside `Csla` 11 would run the generators twice, so the build fails with `CSLABUILD001` while the reference remains. Remove its `PackageReference`, and its `PackageVersion` entry if you use central package management:

```xml
<!-- Remove -->
<PackageReference Include="Csla.Generator.AutoImplementProperties.CSharp" Version="10.*" />
```

The `[CslaImplementProperties]`, `[CslaImplementPropertiesInterface<T>]` and `[CslaIgnoreProperty]` attributes are now part of `Csla.dll`, in the same `Csla` namespace, so code that uses them doesn't change.

### Make business classes `partial`

For each `partial` class that declares data portal operation methods, the generator adds code that lets the data portal call those methods directly instead of using reflection. This also means IDEs, analyzers and the trimmer see private operation methods as used.

Classes that aren't `partial` still work through reflection, but the new `CSLA0024` analyzer reports a warning for each class (or containing type) with operation methods that isn't `partial`. If your projects treat warnings as errors, the build fails until you fix them. The analyzer's code fix adds the `partial` modifier to the class and its containing types. See [CSLA0024](analyzers/CSLA0024-TypeWithOperationsShouldBePartialAnalyzer.md).

```csharp
[Serializable]
public partial class Customer : BusinessBase<Customer>
{
[Fetch]
private void Fetch(int id)
{
// ...
}
}
```

Because the data portal now calls operation methods through generated code, stack traces from operation methods go through generated `IDataPortalOperations` members, not reflection.

### Strongly typed data portal extension methods

You can mark a class (or an assembly) with `[DataPortalExtensions]` to generate strongly typed extension methods on `IDataPortal<T>` and `IChildDataPortal<T>`. See the [release notes](../releasenotes.md) for details. This is opt-in. Once you use it, the `CSLA0025` analyzer warns when code calls the untyped `params object[]` data portal methods for that type when a generated method could be used instead. See [CSLA0025](analyzers/CSLA0025-UseGeneratedDataPortalExtensionAnalyzer.md).

## Legacy Data Portal Operation Method Names Removed

In earlier versions, if the data portal couldn't find a method with an operation attribute (such as `[Fetch]`), it fell back to looking for a method by name (such as `DataPortal_Fetch` or `Child_Update`). This fallback was controlled by the `DataPortalOptions.UseLegacyOperationMethods` option.
Expand Down Expand Up @@ -130,6 +171,30 @@ private void Fetch([Inject] IChildDataPortal<LineItem> childPortal, [Inject] ILi
}
```

## Async Authorization Rules in View Models and `IsSavable`

Async authorization rules (`IAuthorizationRuleAsync`) are now supported in view models and in `IsSavable` ([#4707](https://github.com/MarimerLLC/csla/issues/4707), [#4947](https://github.com/MarimerLLC/csla/issues/4947), [#4948](https://github.com/MarimerLLC/csla/pull/4948)). Synchronous rules behave as before. If you use async rules, these behavior changes affect your UI code.

### View models

* The XAML `ViewModelBase` and `ObjectStatus`, and the Blazor `ViewModel`, evaluate authorization rules with `HasPermissionAsync`.
* With async rules, the permission-based properties (such as `CanCreateObject` and `CanEditObject`, and in XAML `CanCreate`, `CanDelete`, `CanAddNew` and `CanRemove`) start out `false` and update when the rules complete, raising `PropertyChanged`.
* The Blazor `ViewModel.RefreshAsync` waits for the object-level permissions, and the `Can*Object` getters no longer throw for async rules.

### `IsSavable`

`IsSavable` on `BusinessBase`, `BusinessListBase` and `BusinessBindingListBase` checks the per-type `CreateObject`, `EditObject` or `DeleteObject` rule:

* A rule that completes synchronously (a sync rule, or an async rule that doesn't await) is evaluated on every read, as before.
* A rule that is still running marks the object busy, and `IsSavable` returns `false`. Reading `IsSavable` can therefore raise `BusyChanged`.
* When the rule completes, the result is cached for that action (new, existing or deleted) and user. The object is marked idle, and `PropertyChanged` is raised for `IsSavable`. The result is re-evaluated when the action or the user changes, but not when other properties change.
* If the rule fails, `IsSavable` is `false` and `UnhandledAsyncException` is raised.
* Calling `Save` while the check is still running throws, the same as saving an object with running async business rules. Wait for the object to become idle first (for example with `WaitForIdle`). The XAML view model and the Blazor `SaveAsync` already wait for it.

### `HasPermission` with async rules

The synchronous `BusinessRules.HasPermission` now accepts an async rule if its task has already completed. If the rule is still running, `HasPermission` throws an `InvalidOperationException` that tells you to use `HasPermissionAsync`. Previously any async rule threw `ArgumentOutOfRangeException`.

## Transaction settings resolved at runtime and `ITransactionScopeFactory`

Transaction settings from `TransactionalAttribute` are now resolved when the transaction is created, not when the attribute is constructed ([#4780](https://github.com/MarimerLLC/csla/issues/4780)). Previously the attribute copied the defaults from `DataOptions` into itself. Because CSLA caches the attribute, later configuration changes were ignored.
Expand Down
12 changes: 10 additions & 2 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,20 @@ The data portal no longer finds operation methods by name (`DataPortal_Fetch`, `

* [#4359](https://github.com/MarimerLLC/csla/issues/4359) Call data portal operation methods explicitly instead of through reflection, using source generators bundled in the `Csla` package ([#4925](https://github.com/MarimerLLC/csla/pull/4925))
* [#4828](https://github.com/MarimerLLC/csla/issues/4828) Remove the data portal's fallback of finding operation methods by name; only methods with an operation attribute are invoked ([#4943](https://github.com/MarimerLLC/csla/pull/4943))
* [#4780](https://github.com/MarimerLLC/csla/issues/4780) Resolve transaction settings when the transaction is created, and add `ITransactionScopeFactory` to control how the data portal creates `TransactionScope` instances ([#4949](https://github.com/MarimerLLC/csla/pull/4949))

**Authorization**

* [#4707](https://github.com/MarimerLLC/csla/issues/4707) XAML and Blazor view models support async authorization rules, and `HasPermission` reports a still-running async rule with an `InvalidOperationException` that points to `HasPermissionAsync` ([#4948](https://github.com/MarimerLLC/csla/pull/4948))
* [#4947](https://github.com/MarimerLLC/csla/issues/4947) `IsSavable` supports async per-type authorization rules: the object is busy while the rule runs, and the result is cached per action and user ([#4948](https://github.com/MarimerLLC/csla/pull/4948))

**Bug Fixes**

* [#4891](https://github.com/MarimerLLC/csla/issues/4891) Remove the unusable parameterless constructor of `LazySingleton<T>` ([#4944](https://github.com/MarimerLLC/csla/pull/4944))

**Collections**

* [#4848](https://github.com/MarimerLLC/csla/issues/4848) Editable lists enforce `AllowNew` and `AllowRemove`: adding or removing items when the matching property is `false` throws `NotSupportedException`
* [#4848](https://github.com/MarimerLLC/csla/issues/4848) Editable lists enforce `AllowNew` and `AllowRemove`: adding or removing items when the matching property is `false` throws `NotSupportedException` ([#4945](https://github.com/MarimerLLC/csla/pull/4945))

**Build and Release**

Expand All @@ -89,13 +95,15 @@ The data portal no longer finds operation methods by name (`DataPortal_Fetch`, `

* CSLA 11 no longer targets .NET 8 or .NET 9. Applications must target .NET 10 or later (or continue to use .NET Framework 4.6.2 through 4.8, or a `netstandard2.0`-compatible runtime).
* On .NET 11, Android apps using `Csla.Maui` require Android API level 24 or later, because .NET 11 for Android requires it. The `net10.0-android` target still supports API level 21.
* The `Csla.Generator.AutoImplementProperties.CSharp` package is retired because its generators are now included in the `Csla` package. Remove any `PackageReference` (and `PackageVersion`) for it; a build error (`CSLABUILD001`) is reported while the reference remains.
* The `Csla.Generator.AutoImplementProperties.CSharp` package is retired because its generators are now included in the `Csla` package. Remove any `PackageReference` (and `PackageVersion`) for it; a build error (`CSLABUILD001`) is reported while the reference remains. Business classes with data portal operation methods should be `partial`; the new `CSLA0024` analyzer warns for classes that aren't. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md#source-generators-bundled-in-the-csla-package).
* The data portal no longer finds operation methods by name. Only methods with an operation attribute (such as `[Fetch]`, `[Update]`, or `[UpdateChild]`) are invoked, and the `DataPortalOptions.UseLegacyOperationMethods` option is removed. Add the matching attribute to any `DataPortal_XYZ` or `Child_XYZ` method that doesn't have one. The `CSLA0014` analyzer is now a warning and its code fix adds the attribute for you. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md) ([#4828](https://github.com/MarimerLLC/csla/issues/4828)).
* The default `Child_Create()` methods on `BusinessBase`, `BusinessListBase`, and `BusinessBindingListBase` are now marked with `[CreateChild]`, so a child with no create method of its own still gets its business rules checked.
* The private "not supported" `DataPortal_XYZ` methods on `CommandBase`, `ReadOnlyBase`, and the read-only, name/value, and dynamic list base classes are removed. Unsupported operations now fail with the data portal's normal "method not found" error.
* Creating a child of an `[ObjectFactory]` type no longer looks for a method named `Child_Create`. It calls the business class's `[CreateChild]` method.
* The parameterless constructor of `LazySingleton<T>` is removed, and `LazySingleton<T>` no longer implements `IUseApplicationContext`. Pass a factory delegate to `LazySingleton(Func<T>)`, or use `System.Lazy<T>`. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md) ([#4891](https://github.com/MarimerLLC/csla/issues/4891)).
* `BusinessListBase`, `BusinessBindingListBase`, `DynamicListBase` and `DynamicBindingListBase` throw `NotSupportedException` when items are added while `AllowNew` is `false`, or removed while `AllowRemove` is `false`. `AllowRemove` now defaults to `true` for `BusinessListBase` and `DynamicListBase`. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md#allownew-and-allowremove-are-enforced).
* With async authorization rules, view model permission properties (such as `CanCreateObject`) start out `false` and update when the rules complete. Reading `IsSavable` while an async `CreateObject`, `EditObject` or `DeleteObject` rule is running marks the object busy and returns `false`, and calling `Save` before the rule completes throws. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md#async-authorization-rules-in-view-models-and-issavable) ([#4707](https://github.com/MarimerLLC/csla/issues/4707), [#4947](https://github.com/MarimerLLC/csla/issues/4947)).
* `TransactionalAttribute` no longer copies defaults from `DataOptions`: `TimeoutInSeconds` is now `int?` and `AsyncFlowOption` is now `TransactionScopeAsyncFlowOption?`, and the `TransactionalDataPortal` constructor takes an `ITransactionScopeFactory` and `TransactionScopeFactoryContext`. The `DataOptions` transaction defaults are now per-instance instead of static. See [Upgrading to CSLA 11](docs/Upgrading%20to%20CSLA%2011.md#transaction-settings-resolved-at-runtime-and-itransactionscopefactory) ([#4780](https://github.com/MarimerLLC/csla/issues/4780)).

### Supported Platforms

Expand Down
Loading