IGridDataProvider erweitert [Compilerfehler]

IGridDataProvider hat eine neue Methode GetQuery erhalten. Diese liefert die Abfrage inklusive aller Filter aber ohne das Select der Daten für die Spalten. In der Regel also Abfragen auf konkrete Datentabellen. Beispiel IQueryable<OrmCRMCompany> oder IQueryable<OrmBABase>. Bei Ansichten die keine Datensätze anzeigen die entsprechenden anderen Datentypen.

Attachment Handling

Der Umgang mit Dateianhänge wurde angepasst. Genaueres im Unterkapitel Attachment Handling

Überarbeitung des FormHandlings

Aus technischen Gründen, musste das FormHandling komplett überarbeitet werden. Daher müssen eigene Renderer und eigene Dialoge angepasst werden.

Folgende Nugets können deinstalliert werden

Von Business App werden folgende Nugets nicht mehr beötigt und können, wenn im Projekt keine Abhängigkeit vorhanden ist, deinstalliert werden.

  • Elasticsearch.Net
  • NEST

ConfigurationBase.DynamicallyGenerated jetzt automatisch

Das Property wird jetzt von BA.Core automatisch ermittelt und muss und kann nicht mehr zugewiesen werden.

=> In dynamischen Konfiguratione die Zeile

configuration.DynamicallyGenerated = true;

entfernen. Der Compiler weist im Zweifel auf den Fehler hin.

ConfigurationBase-Events jetzt alle protected

Folgende Events waren früher public:

protected virtual void BeforeSave() { }
protected virtual void AfterCacheRefresh() { }
protected virtual void AfterSave() { }

Falls die Methoden in projekteigenen Konfigurationen überschrieben wurden, müssen sie auf protected geändert werden. Der Compiler weist im Zweifel auf den Fehler hin.

IDataConfiguration geändert in IEntityConfigurationSpecifier

Das Interface IDataConfiguration wurde ersetzt durch IEntityConfigurationSpecifier.

Compilerfehler beim Zugriff auf config.GetDataSource()

  • Ersetzen durch config.OrmDataSource

Falls man es öfter hat, führ eine globale Ersetzung von .GetDataSource() durch .OrmDataSource zum Ziel.

Eigene Konfigurations-Klassen, die das Interface implementiert haben

  • Interface durch das neue ersetzen.
  • Die Methode GetDataSource() umbenennen in GetOrmEntityConfigurationGuid().
  • Die Methdoen GetListOfFieldsUsed() und GetListOfRelationDefinitionsUsed() ersatzlos entfernen.

Die Eigenschaft ControlBase.HasErrors existiert nicht mehr.

Alle Zuweisungen des Feldes sind ersatzlos zu entfernen.

Ebenfalls entfernt wurden HasDesignErrors und DesignErrorTooltipMessage.

Änderungen an CDPOrmFieldsProperties

Bei der Auswahl von Datenfeldern wird typischerweise CDPOrmFieldsProperties eingesetzt. Nun gibt es jetzt Datenspalten die nicht beschreibbar sind und Datenspalten die in Masken im Normalfall nicht beschrieben werden sollen. Technisch aber beschreibbar sind. In diesem Zusammenhang wurde der Datenprovider überarbeitet.

Read-Only-Spalten [immer prüfen]

Die Auswahl von Datenspalten muss jetzt sauber differenzieren, ob auch nur lesbare Spalten gewünscht sind oder nicht. Dies geschieht über den Parameter includeReadOnly:

  • ReadOnly (default) – Es werden alle Spalten zur Auswahl angeboten, berechnete und normal bearbeitbare.
    Diese Auswahl sollte verwendet werden, wenn die gewählte Spalte gelesen werden soll. Dann funktionieren auch automatisch die neuen, berechneten Spalten.
  • None – Es werden nur Spalten angeboten, die auch in Masken pflegbar sind.
    Diese Auswahl ist empfohlen, wenn eine Spalte zum Schreiben/Befüllen gewählt werden soll.
  • NoUIWrite – Es werden auch Spalten angeboten, die zwar technisch schreibbar sind, aber nicht für die Änderung durch Endbenutzer vorgesehen sind, weil sie z.B. automatisch zugewiesen werden wie AttachmentState. Diese Auswahl wird z.B. für die Workflow-Akion ChangeFieldAction verwendet.

Datentypeinschränkung [nur bei Compilerfehler bearbeiten]

Die Optionen TypesToShow und TypesNotToShow haben jetzt den Datentyp IReadOnlyCollection<EnumDataTypes>. Dem sollte i.a. ein Array von EnumDataTypes[] zugewiesen werden.
Die Auswahl ist jetzt unabhängig von den verwendeten Controls in der Entity-Konfiguration und analog zu CDPCommonFieldsProperties.TypesToShow.

Die Werte sind im allgemeinen wie folgt zu ersetzen. (Einige der Ersetzungen sind bereits Arrays, andere brauchen noch ein new[].)

  • OrmTextField -> EnumDataTypes.String
  • OrmTextFieldBase -> EnumDataTypes.TextTypes
  • OrmNumericFieldBase<> -> EnumDataTypes.NumberTypes
  • OrmTextFieldBase, @OrmNumericFieldBase<> -> EnumDataTypes.TextNumberTypes@
  • OrmDecimalField -> EnumDataTypes.Decimal
  • OrmDateTimeField -> EnumDataTypes.DateTime
  • OrmHTMLField -> EnumDataTypes.HTML
  • OrmAttachmentsField -> EnumDataTypes.Attachments
  • OrmEnumFieldBase -> EnumDataTypes.EnumTypes
  • OrmEnumField -> ReferenceEnumTypes
  • OrmSubRecordField -> EnumDataTypes.SubRecords

Wenn TypesToShow direkt in einem Attribut angegeben wird, müssen statt dessen die EnumDataSource.XXXGuid Werte verwendet werden:

[CDPOrmFieldsProperties(typesToShow: new[] { EnumDataTypes.SubRecordsGuid })]

Eigene Steuerelemente für Masken

WIe im vorherigen Abschnitt erläutert wurde der Datenprovider CDPOrmFieldsProperties überarbeitet. Typischerweise erweitern Steuerlemente für Masken DataControlBase, welche eine virtuelle Methode GetTypesOfOrmFieldName zur Beeinflussung der Feldauswahl zur Verfügung stellt. Deren Signatur hat sich nach den identischen Konzept wie im vorherigen Abschnitt erläutert umgestellt.

protected override IReadOnlyCollection<EnumDataTypes> GetTypesOfOrmFieldName()

Konfigurations-Datenprovider mit DataSources Filter [Compiler-Fehler oder Exception]

Wenn eigene Controls Eigenschaften haben, die fremde Konfigurationen (z.B. Masken) auswählen und einen DataSource-Filter nutzen, dann ist folgendes zu beachten:

  • Die Enum-Werte lauten jetzt
    MatchAnyTypeOrAscendant und MatchAnyTypeExcact -> MatchSubSet
    MatchAllTypesOrAscendants -> MatchSuperSet
  • Zudem ist die Auswahl einer Match-Option jetzt obligatorisch, sobald ein DataSource-Filter verwendet wird. Andernfalls kommt eine ArgumentException zu Laufzeit. Das ist aber selten, weil die alte StandardOption MatchAnyTypeExcact nicht korrekt mit Basisdatentypen umgehen konnte und deshalb kaum verwendbar war.
  • Wenn nur Konfigurationen mit exakt übereinstimmenden Datentypen ausgewählt werden sollen, steht zusätzlich die Option MatchExact zur Verfügung.

Projektcodemigration: AttributesCache R.I.P [nur bei Compilerfehler]

Die Klasse AttributesCache existiert nicht mehr. Statt dessen wird eine .NET Collection verwendet. Alle Methoden der Klasse stehen jetzt als kompatible Extensions zur Verfügung.

  • Alle Vorkommen von AttributesCache durch IReadOnlyCollection ersetzen.
  • Falls das Field AttributesCache.Attributes verwendet wurde, “.Attributes” entfernen. Die .NET Collection ist bereits die Liste der Attribute.

Änderungen in den Nugets, um eigene MVC-Views zu implementieren

Möchte man in einem Projekt mit MVC-Views (also .cshtml) arbeiten, braucht man RazorGenerator.MsBuild als Nuget.
Ansonsten bekommt man diese Fehlermeldung

"die Ansicht ... oder die entsprechende Gestaltungsvorlage wurde nicht gefunden, oder keines der Ansichtsmodule unterstützt die durchsuchten Speicherorte. die folgenden Speicherorte wurden durchsucht: ..."

Kann über den Nuget Package Manager deinstalliert bzw installiert werden.

OrmBase.ModelState existiert nicht mehr [bei Compilerfehler]

ModelState ist eine Eigenschaft einer Maske nicht eines Datensatzes. Eventuelle Validierungsfehler (z.B. in OnBeforeValidation) müssen in OrmBase.ValidationResults geschrieben werden. Von dort werden sie automatisch in den ModelState der Maske übertragen.

Die Syntax ist:

orm.ValidationResults.Add(new BAValidationResult(new ValidationContext(...), ...));

Klasse BAValidationBase existiert nicht mehr [bei Compilerfehler]

Klassen, die davon geerbt haben, sollten jetzt direkt von ValidationAttribute erben und dessen Methode IsValid(object value, ValidationContext validationContext) überschreiben. Diese liefert statt einem boolean ein ValidationResult.

Für die Implementierung wird entweder die Hilfsmethode ValidationAttributeHelper.CreateValidationResult empfohlen, die den passenden Ergebnistyp aus der Boolean-Bedingung erzeugt, oder new BAValidationResult(validationContext, ...) im Fehlerfall.

HtmlToPlainText, PlainTextToHtml, CleanHtml, HtmlEquals umgezogen [optional]

Die Funktionen sind von Api.Text nach APi.Html umgezogen. Die alten Funktionen sind obsolet, funktionieren aber noch.

ORM-Event OnRelationsCreated

Dieses Event wurde aufgrund eines Fehlers vor Release 7.0 auch bei Aktualisierungsgruppen in Masken aufgerufen. Das ist jetzt nicht mehr der Fall.
Falls sich Implementierungen auf dieses Verhalten verlassen haben, um z.B. auf aktuelle Benutzereingaben in der Maske zu reagieren, müssen sie angepasst werden und zusätzlich OnUIRefreshing implementieren. Dieses wird bei Aktualisierungsgruppen aufgerufen.

LoadFromCache: createIfNotExists entfernt [bei Compilerfehler]

Falls der optionale Parameter createIfNotExists von ormbabase.LoadFromCache in Projektcode verwendet wurde, muss dieser beim Aufruf entfernt werden.

web.config

Die Nugets “BundleTransformer.Core” und “BundleTransformer.NUglify”, deren Installation automatisch folgende Einträge in der web.config-Datenbank vornimmt:

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

Die Konfiguration dieser Pakete erfolgt ebenfalls in der web.config Datei, direkt im Bereich <configuration>. Sollte durch die Installation der Nuget-Pakete eine Standardkonfiguration hinzugefügt worden sein, ist diese zu löschen.

Folgende Konfiguration muss in der web.config-Datei hinzugefügt werden, damit die Optimierung reibungsfrei durchgeführt werden kann:

<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"/>
				<add fileExtension=".css?BA"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.Appointment"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.Dashboard"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.FollowUp"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.Report"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.Activity"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Contact"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Activity"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Opportunity"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.FollowUp"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Project"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Appointment"
				     assetTypeCode="Css"/>
				<add fileExtension=".css?BA.CRM.Marketing"
				     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"/>
				<add fileExtension=".js?BA"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Event"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Appointment"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Dashboard"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.FollowUp"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Report"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Contact"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Activity"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.Correspondence"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.BusinessMail"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Contact"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Activity"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Correspondence"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Opportunity"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.FollowUp"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Project"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Appointment"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Evalanche"
				     assetTypeCode="JavaScript"/>
				<add fileExtension=".js?BA.CRM.Marketing"
				     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>

Fügt ein Service-Projekt eigene JavaScript- und/oder CSS-Bundles hinzu, so müssen an dieser Stelle die “fileExtensions” entsprechend hinzugefügt werden (.css?<assembly-name> oder .js?<assembly-name>).