Sub-Komponenten einzeln referenzieren

Fünf Pakete sind aus einer bestehenden Komponente herausgetrennt: FMH.Komponente.Basis.Validierung, FMH.Komponente.FileUpload.Validierung, FMH.Komponente.Kompetenzen.Validierung, FMH.Komponente.RichText.Validierung und FMH.Komponente.Infrastruktur.Schnittstellen. Diese Seite sagt, was sie enthalten, wann der einzelne Bezug sich lohnt und was dabei fehlt.

Warum überhaupt getrennt

Ein Projekt, das nur Modelle mit Validierungs-Attributen hält, brauchte bisher die ganze Basis, und damit V8, WebOptimizer, Serilog und WebSecurity. Die Attribute selbst sind aber reine Klassen ohne Views und ohne Static Web Assets. Sie liegen deshalb neu in einem eigenen Paket, das mit dem Framework auskommt.

Wer die Hauptkomponente referenziert, merkt nichts davon. Sie verweist auf ihre Sub-Komponente, und die Typen haben ihren Namespace behalten: Kein using ist anzupassen.

Was in welchem Paket liegt

Sub-Komponente enthält bleibt in der Hauptkomponente
Basis.Validierung die Attribute (DatumBereich, Email, Ganzzahl, NoHtml, Nummer, RequiredIf, RequiredIfContains, CheckboxRequired, UniqueId, dazu die Marker wie AdditionalMetadata und HelpText), der AdditionalMetadataProvider, die Meldungstexte in ValidierungResources, die Template-Namen UiDisplay.Basis und UiEditor.Basis, die Metadaten-Schlüssel UiMetadata.Basis die Adapter für die Prüfung im Browser (wwwroot/js/validation/…), die Templates, AddFmhWidgetOptions()
FileUpload.Validierung DocumentUploadRequired, DocumentUploadRequiredIf, MaxUploadableFiles, MaxFilesDto, die Modelle DokumentListeViewModel und DokumentEintrag, der Meldungstext in FileUploadValidierungResources, die Template-Namen UiEditor.FileUpload, die Metadaten-Schlüssel UiMetadata.FileUpload die EditorTemplates DokumentListe und IFormFile, das Skript der Ablagefläche, DokumentViewModel
Kompetenzen.Validierung die Modelle der LikertSkala (LikertSkalaGroupModel, LikertSkalaModel, die Typen unter LikertSkala.Daten) und der FrageAntwort (FrageAntwortViewModel, Rolle, AntwortTyp usw.), deren Texte in KompetenzenValidierungResources, die Template-Namen UiEditor.Kompetenzen die Builder LikertSkalaBuilder und LikertSkalaGroupBuilder samt LikertSkalaColumnCollection, die Fabrikmethoden, die EditorTemplates, die Texte der Templates in KompetenzenResources
RichText.Validierung die Template-Namen UiEditor.RichText das EditorTemplate Richtext, Quill, das Skript des Editors
Infrastruktur.Schnittstellen IScssStyleProvider, IProviderDiscovery, IAssemblyProvider, IFmhRequiredAttribute, IFmhDocumentRequiredAttribute, DictionaryErweiterungen.Replace IJavaScriptProvider, IModuleScriptProvider, IActionButtonSource, IBuilder und alle Implementierungen

Infrastruktur.Schnittstellen und RichText.Validierung sind die einzigen FMH-Pakete ohne jede Abhängigkeit, nicht einmal mit einem Framework-Verweis. Genau deshalb können die Validierungs-Pakete der Basis und des Uploads Infrastruktur.Schnittstellen als einzigen Verweis führen.

Wann sich der einzelne Bezug lohnt

Wenn ein Projekt Modelle hält und serverseitig prüft, aber nichts rendert: ein Dienste- oder Vertragsprojekt, eine Bibliothek mit ViewModels, ein Hintergrunddienst, der dieselben Regeln anwendet. Eine Bibliothek mit ViewModels kann das Template dabei trotzdem wählen, die Namen wie [UIHint(UiEditor.Basis.Checkbox)] liegen im Validierungs-Paket der jeweiligen Komponente.

<ItemGroup>
  <PackageReference Include="FMH.Komponente.Basis.Validierung" Version="..." />
</ItemGroup>

Was dabei fehlt:

  • Die Prüfung im Browser. Die unaufdringlichen Adapter liegen in FMH.Komponente.Basis. Ohne sie prüft nur der Server, die Meldung erscheint also erst nach dem Absenden. (Für die Upload-Attribute spielt das keine Rolle, zu ihnen gibt es ohnehin keinen Adapter.)

  • Die Templates. Html.EditorFor rendert dann das ASP.NET-Standardfeld ohne FMH-Gerüst, also auch ohne die Plätze für Meldung und Hilfetext.

  • AddFmhWidgetOptions(). Diese Methode liegt in der Basis und trägt den Metadaten-Anbieter ein. Ohne sie bleiben [AdditionalMetadata] und die Marker-Attribute wirkungslos; der Anbieter ist dann selbst zu registrieren:

    builder.Services.AddControllersWithViews(options =>
    {
        options.ModelMetadataDetailsProviders.Add(new AdditionalMetadataProvider());
    });
    

Eine Anwendung mit Oberfläche nimmt also weiterhin die Hauptkomponente. Der einzelne Bezug ist für die Projekte gedacht, die daneben liegen.

Was beim Umstieg anzupassen ist

Nur die Texte, und nur, wenn die Anwendung sie selbst liest:

Alt Neu
_FmhWebMvc.ValidationEmail, …ValidationInt, …ValidationDecimal, …ValidationHtml, …ValidationDateTimeRange ValidierungResources.<derselbe Name>, Namespace FMH.Komponente.Basis.Resources
FileUploadResources.Document_Required FileUploadValidierungResources.Document_Required, Namespace unverändert
KompetenzenResources.FrageAntwort_* (ausser …AntwortFD, …AntwortFFD), …ExternalAssessment, …SelfAssessment KompetenzenValidierungResources.<derselbe Name>, Namespace unverändert

Die Ressourcenklasse des Uploads heisst bewusst nicht ebenfalls ValidierungResources: Beide lägen sonst gleichnamig in zwei Namespaces, und ein Projekt mit beiden using-Zeilen bekäme CS0104, «mehrdeutiger Verweis».

Dazu kommt der Punkt, der für alle gilt, auch für Projekte, die nichts umstellen: Der Umbau ist quellkompatibel, aber nicht binärkompatibel. Alle FMH-Pakete gemeinsam heben und einmal vollständig neu bauen, siehe Pakete im Überblick.