Verhaltensänderung bei Relationsdefinitionen (Targets) und Api.Relation

Wurden diese Methoden genutzt enthielt die Ergebnismenge (im Defaultverhalten) nur aktive Datensätze. Nun werden auch die inaktiven in die Liste eingeschlossen. Ist dies nicht gewünscht, muss die Methode entsprechend ergänzt werden.

RelatedChildren.Where(ff => ff.IsActive).Count()

Falls die Api.Relation direkt genutzt wurde, muss der Parameter entryActiveState entsprechend belegt werden.

Reduktion der Nuget-Pakete in Projekten

Die BA-Nugets bringen ihre Laufzeitabhängigkeiten nun selbst mit. Es ist daher nicht mehr erforderlich oder empfohlen, alle zur Laufzeit benötigten Nuget-Pakete in allen Projekten zu installieren. Davon profitiert die Geschwindigkeit von Kompilieren und IntelliSense.

Typischerweise können alle Nugets bis auf diese entfernt werden:

  • BA.* – die BusinessApp-Module
  • Standard-Nugets für Asp.NET MVC-Anwendungen
    • Microsoft.AspNet.Mvc
    • Microsoft.AspNet.Mvc.de
    • Microsoft.AspNet.Razor
    • Microsoft.AspNet.Razor.de
    • Microsoft.AspNet.WebPages
    • Microsoft.AspNet.WebPages.de
    • Microsoft.Web.Infrastructure
  • Unterstützung für TypeScript im Projekt
    • Microsoft.TypeScript.MSBuild
  • JSON Serialisierung
    • Newtonsoft.Json
  • DIInit
    • Ninject
  • Server-Log Funktionen
    • NLog
  • Eigene MVC Views im Projekt
    • RazorGenerator.MsBuild

Folgende Nuget Pakete können zusätzlich wegen Abhängigkeiten zu weiteren BA oder BA.CRM Modulen nicht deinstalierbar sein

  • BuildWebCompiler
  • CsvHelper
  • Microsoft.AspNet.WebApi.Client
  • Microsoft.AspNet.WebApi.Core
  • Microsoft.Exchange.WebServices
  • RestSharp
  • System.ValueTuple

Weitere Nuget-Pakete werden nur dann benötigt, wenn die Programmierung im Projekt explizit darauf zugreift, bespielsweise wenn eigene Logik für Microsoft-Exchange Synchronisation implementiert wurde.

Nacharbeiten

Projektdatei: System.Web.Optimization

Bei der Entfernung des Nugets System.Web.Optimization wird die Referenz auf diese DLL aus dem Projekt entfernt. Diese DLL wird zukünftig von Business App zur Verfügung gestellt. Dazu muss die Referenz in die Projektdatei eingefügt werden. (Pfad ggf. an BA-Version anpassen)

<Reference Include="System.Web.Optimization, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
  <HintPath>..\packages\BA.Core.8.0.0\lib\System.Web.Optimization.dll</HintPath>
</Reference>

Projektdatei: Independentsoft.Msg

Falls vorhanden, Referenz auf Independentsoft.Msg entfernen.

web.config: Hinzufügen BundleTransformer

In web.config den Abschnitt für bundleTransformer vor </configSections> wieder eintragen oder die Änderung per git revert zurücknehmen:

<sectionGroup name="bundleTransformer">
  <section name="core" type="BundleTransformer.Core.Configuration.CoreSettings, BundleTransformer.Core" />
  <section name="nuglify" type="BundleTransformer.NUglify.Configuration.NUglifySettings, BundleTransformer.NUglify" />
</sectionGroup>

web.config: Ändern System.Diagnostics

Beim Eintrag die Version auf 6.0.0.1 ändern.

<dependentAssembly>
  <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
</dependentAssembly>

web.config: Ändern Microsoft.Identity.Client

Beim Eintrag die Version auf 4.54.1.0 ändern.

<dependentAssembly>
  <assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.54.1.0" newVersion="4.54.1.0" />
</dependentAssembly>

web.config: Hinzufügen Azure.Core

Eintrag hinzufügen

<dependentAssembly>
  <assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-1.35.0.0" newVersion="1.35.0.0" />
</dependentAssembly>

web.config: Aktualisierung WebGrease

<dependentAssembly>
  <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>

Compilierfehler

Falls Compilierfehler wegen fehlender Namespaces auftreten:
Zuerst prüfen ob es nicht vielleicht nur verwaiste using-Direktiven sind => entfernen (geht mit Ctrl-R-G).
Ggf. ein zu viel entferntes Nuget wieder installieren, wenn der Projekt-Code dieses explizit benötigt.

Umorganisation Bundle Transformer

In der web.config den Bereich bundleTransformer austauschen

<bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    <core>
      <css defaultMinifier="NUglifyCssMinifier">
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
        </translators>
        <postProcessors>
          <add name="UrlRewritingCssPostProcessor" type="BundleTransformer.Core.PostProcessors.UrlRewritingCssPostProcessor, BundleTransformer.Core" useInDebugMode="false" />
        </postProcessors>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
          <add name="NUglifyCssMinifier" type="BundleTransformer.NUglify.Minifiers.NUglifyCssMinifier, BundleTransformer.NUglify" />
        </minifiers>
        <fileExtensions>
          <add fileExtension=".css" assetTypeCode="Css" />
        </fileExtensions>
      </css>
      <js defaultMinifier="NUglifyJsMinifier">
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
        </translators>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
          <add name="NUglifyJsMinifier" type="BundleTransformer.NUglify.Minifiers.NUglifyJsMinifier, BundleTransformer.NUglify" />
        </minifiers>
        <fileExtensions>
          <add fileExtension=".js" assetTypeCode="JavaScript" />
        </fileExtensions>
      </js>
    </core>
    <nuglify>
      <css allowEmbeddedAspNetBlocks="false" blocksStartOnSameLine="NewLine" ignoreAllErrors="false" ignoreErrorList="" indentSize="4" indentType="Space" lineBreakThreshold="2147482647" outputMode="SingleLine" preprocessorDefineList="" termSemicolons="false" colorNames="Hex" commentMode="Important" decodeEscapes="true" fixIE8Fonts="true" minifyExpressions="true" removeEmptyBlocks="true" severity="0" />
      <js allowEmbeddedAspNetBlocks="false" blocksStartOnSameLine="NewLine" ignoreAllErrors="false" ignoreErrorList="" indentSize="4" indentType="Space" lineBreakThreshold="2147482647" outputMode="SingleLine" preprocessorDefineList="" termSemicolons="false" alwaysEscapeNonAscii="false" amdSupport="false" collapseToLiteral="true" constStatementsMozilla="false" debugLookupList="Debug,$Debug,WAssert,Msn.Debug,Web.Debug" errorIfNotInlineSafe="false" evalLiteralExpressions="true" evalTreatment="MakeImmediateSafe" ignoreConditionalCompilation="false" ignorePreprocessorDefines="false" inlineSafeStrings="true" knownGlobalNamesList="" localRenaming="CrunchAll" macSafariQuirks="true" manualRenamesProperties="true" noAutoRenameList="$super" preserveFunctionNames="false" preserveImportantComments="true" quoteObjectLiteralProperties="false" removeFunctionExpressionNames="true" removeUnneededCode="true" renamePairs="" reorderScopeDeclarations="false" scriptVersion="EcmaScript6" strictMode="false" stripDebugStatements="true" severity="0" />
    </nuglify>
  </bundleTransformer>

RenderingUtils.SetHelpText, .SetRequired, .GetRealHelpTextPosition [bei Compilerfehler]

Die Methoden benötigen zusätzliche Informationen, um bei Teilmasken für Basistabellen dennoch die Eigenschaften des aktuellen konkreten Datensatzes (z.B. abweichende Hilfetexte oder Validatoren) zu berücksichtigen.

SetHelpText, SetRequired

Für die Methoden gibt es jetzt zusätzlich eine Implementierung in den Basisklassen der Renderer, die alle Kontextinformationen automatisch beschafft.

Vorher:

RenderingUtils.SetRequired(control, mvcxItem);
RenderingUtils.SetHelpText(control, mvcxItem);

Neu:

SetRequired(mvcxItem);
SetHelpText(mvcxItem);

Nur bei Renderern, die mehrere Controls selbst Rendern muss man die Methoden aus RenderingUtils mglw. weiterhin benutzen, falls die Eigenschaften für ein anderes Control als das aktuell im Fokus des Renderers befindliche gesetzt werden soll.

In dem Fall muss der zusätzliche Parameter attributes mit den CustomAttributes des Properties, auf das sich das gerade gerenderte Control bezieht, versorgt werden. Das bekommt man in Renderern über PreparedProperty.CustomAttributes.

GetRealHelpTextPosition

Hier muss der zusätzliche Parameter immer wie o.g. versorgt werden.

Ausbau von ClientActionGridMassOperationBase.SomethingMustBeSelected

Da der Mechnismus für die Massenoperation alle Datensätze zu verarbeiten, auch wenn nichts Selektiert ist eine Weile nicht mehr funktioniert, wurde die Option entfernt.

GetFormAttributesForControl entfernt [bei Compilerfehler]

Die Methode RenderingUtils.GetFormAttributesForControl existiert nicht mehr. Statt dessen ist DevExFormModel.AdditionalAttributes jetzt eine Datenstruktur, aus der die gewünschten Informationen direkt entnommen werden können.

Das engste Äquivalent zu RenderingUtils.GetFormAttributesForControl(formModel.AdditionalAttributes, control) ist formModel.AdditionalAttributes.Get(control.Id). Das liefert allerdings statt Dictionary<AttributeEnum, bool> bei dem alle Werte true sind ein IDictionary<AttributeEnum, AdditionalFormAttributes>, also mit dem konkreten Attribut als Wert. ContainsKey funktioniert darauf genauso. Allerdings kann Get null liefern, wenn es für das Control keine Attribute gibt.

Die üblichen Abfragen, ob für ein Control ein bestimmtest Attribut existiert, gehen aber wesentlich einfacher:

Alt:

Dictionary<AttributeEnum, bool> attributes = RenderingUtils.GetFormAttributesForControl(formModel.AdditionalAttributes, control);
if (attributes.ContainsKey(AttributeEnum.SkipIfNotEmpty))
    ...

Neu:

if (formModel.AdditionalAttributes.Contains(control.Id, AttributeEnum.SkipIfNotEmpty)
    ...

Statt der Abfrage auf AttributeEnum.ReadOnly sollte unbedingt die Funktion IsControlEditable verwendet werden, weil andernfalls nicht alle Read-Only-Ursachen berücksichtigt werden.

Alt:

Dictionary<AttributeEnum, bool> attributes = RenderingUtils.GetFormAttributesForControl(formModel.AdditionalAttributes, control);
if (attributes.ContainsKey(AttributeEnum.ReadOnly))
    ...

Neu:

if (!IsControlEditable(control))
    ...

Datenstruktur von AdditionalAttributes [bei Compilerfehler]

Falls in Renderen o.ä. direkt auf formModel.AdditionalAttributes zugegriffen wird, sollte die neue Datenstruktur mit ihren Funktionen sinnvoll genutzt werden. Im Besonderen sollten Schleifen über die Attribute vermieden werden, auch LINQ-Schleifen wie .Where oder .@Any@. Beispiel:

Alt:

if (!formModel.AdditionalAttributes.Any(ff => ff.ControlGuid == control.Id && ff.Attribute == AttributeEnum.ReadOnly))
    formModel.AdditionalAttributes.Add(new AdditionalFormAttributes(control.ControlInternalName, control.Id, AttributeEnum.ReadOnly, control.GetType()));

Neu:

formModel.AdditionalAttributes.TryAdd(new AdditionalFormAttributes(control, AttributeEnum.ReadOnly));

Verändertes Interface IControlDataProvider [bei Compilerfehler]

Die Methode IControlDataProvider.GetByKey wurde ersetzt durch GetByKeys, um mehrere Schlüssel auf einmal abzufragen. Das ist vor allem für
Mehrfachselektionscontrols aus Performancegründen erforderlich.

Der eigene Datenprovider kann statt IControlDataProvider zu implementieren, von der Basisklasse SimpleCDPBase erben. Zusätzlich

  • Das Property Properties entfernen. Das ist bereits in der Basisklasse enthalten.
  • Die Implementierungen der Methoden GetRows und GertByKey mit override deklarieren.

Falls es für den eigenen Datenprovider aus Gründen der Performance Sinn macht, kann man auch die Implementierung auf dem Interface IControlDataProvider belassen und die eigene GetByKey Implementierung auf GetByKeys umstellen.

Umbau EnumControlBase.DataProviderProperties [bei Compilerfehler]

Bei Maskensteuerelementen für Auswahllisten wurde der Getter von DataProviderProperties auf private gesetzt. Für das Auslesen steht nun eine virtuelle Methode GetDataProviderProperties() zur Verfügung, die jeweils einen Klon erstellt. Wurden eigene Steuerelemente auf Basis von EnumControlBase implementiert oder bestehende erweitert kann eine Änderung notwendig sein (siehe).

Falls ein eigener Renderer implementiert wurde, der lediglich den Datenprovider geändert hat, ist dies nicht mehr notwendig. Man kann nun die GetDataProviderProperties() dazu überschreiben.

Obsolete Klasse OperationFromActionOverSelectedRecordsIgniter entfernt [bei Compilerfehler]

Die seid längerem obsolete Klasse OperationFromActionOverSelectedRecordsIgniter wurde entfernt. Siehe

Eigene DataProviderProperties Klassen

Die Properties-Klassen der DataProvider dürfen keine Referenzen auf veränderliche Datentypen enthalten..

List<String> PropertyName; // FALSCH!
GuidSet DataSources; // FALSCH!
IReadOnlyCollection<string> PropertyName; // richtig!
IReadOnlyCollection<Guid> DataSources; // richtig!
EnumLanguagesAll Language; // OK, Enum-Instanzen dürfen ohnehin nicht geändert werden.

Andernfalls kommt es bei der Implementierung von DataProvider-Modifier-Methoden zu schwer zu findenden Fehlern mit undefiniertem Verhalten, weil Änderungen an den Listen sich dauerhaft auf Masken aller Benutzer auswirken. Die Modifier-Implementierungen dürfen nur die Listen als Ganzes durch neue Listen mit anderem Inhalt ersetzen.

DataProviderProperties Attribute (bei Compilerfehler)

Die Properties-Klassen wurden bzgl. obiger Bedingung systematisch umgestellt. Vereinzelt kann es bei Attributen direkt an Properties dadurch zu Compilerfehlern kommen, wenn anstelle der Konstruktorargumente die Properties direkt zugewiesen wurden. Das muss ggf. angepasst werden.
Beispiel:

// Fehler
[CDPOrmEntitiesProperties(TypesToShow = new[] { typeof(OrmActivityBase) })]
// neu
[CDPOrmEntitiesProperties(typesToShow: new[] { typeof(OrmActivityBase) })]

Validierung bei eigenen Dialogen

Die Validator-Attribute werden nicht mehr automatisch validiert. Siehe dazu das entsprechende Kapitel

Änderungen am Widget Framework

  • Methode GetProvidedParameterJsonString umbennant: GetAllProvidedParameterJsonString. Die liefert nun eine Liste von Parametern (nicht mehr einzelne Parameter) in einem JSON formatierten String,
  • WidgetStates “ContentBlocked” und “ContentError” existieren nicht mehr,
  • Die Methode SetWidgetState bekommt nicht mehr den Parameter blockWidgetIfNotLoaded,
  • Widget Parameter GridViewConfigWidgetParameter umbenannt: GridViewOrCalendarConfigWidgetParameter,
  • ParameterJsonString in DataWidgetControllerBase ist jetzt eine Liste von Parametern,
  • Methode in Widget.ts SetWidgetState bekommt nicht mehr den Parameter blockWidgetIfNotLoaded,
  • WidgetStates “ContentError” und “ContentBlocked” existieren nicht mehr,