window.lintrk('track', { conversion_id: 7289866 });
ASP.NET Core separate Assembly

Mehrsprachigkeit in ASP.NET Core in separater Assembly

Maurice Jungmann | Softwareentwickler | 22.10.2020

ASP.NET Core

ASP.NET Core als Basis

Der Artikel „Mehrsprachigkeit in ASP.NET Core, der für diesen Blog als Grundlage dient, befasst sich mit der Implementierung von Mehrsprachigkeit in einer ASP.NET Core Anwendung. In diesem Artikel soll die Implementierung in einer separaten Assembly aufgezeigt werden.

Im vorangegangen Beispiel befinden sich die Ressourcendateien in der gleichen Assembly, wie die Web-Anwendung. Bei größeren Projekten ist es jedoch hilfreich, die Ressourcen in eine separate Assembly auszulagern.

 

Projektaufteilung

Zunächst wird das vorhanden Projekt aus dem Artikel „Mehrsprachigkeit in ASP.NET Core“ in 3 Projekte aufgeteilt: Web, Models und Resourcen.

Das aktuelle Projekt erhält die Benennung Mehrsprachigkeit.Web.

Die beiden neuen Projekte somit Mehrsprachigkeit.Models und Mehrsprachigkeit.Resources.

Der Models Ordner wird in das neue Projekt Mehrsprachigkeit.Models und der Resources Ordner in das Projekt Mehrspachigkeit.Resources verschoben. Für jede Resource legen wir eine gleichnamige Public Klasse an. Bereits beim Entwurf einer Anwendung sollte demnach gut überlegt sein, inwiefern einheitliche oder verschiedene Ressourcendateien eingepflegt werden sollen. Die Ressource Contact wurde in Models umbenannt und auf die oberste Ebene im Ressourcenordner verschoben.

 

Klassendefinition

Anschließend wird im Projekt „Resources“ folgende Klasse hinzugefügt:

public class LocService<T>
{
    private readonly IStringLocalizer _localizer;

    public LocService(IStringLocalizerFactory factory)
    {
        Type type = typeof(T);
        var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);

        var myRelativePath = String.Join(".", type.Namespace.Split('.').Skip(2));
        if (myRelativePath.Length > 0)
            myRelativePath += ".";

        _localizer = factory.Create(myRelativePath + type.Name, assemblyName.Name);
    }

    public LocalizedString GetLocalizedHtmlString(string key)
    {
        if (_localizer != null)
            return _localizer[key];
        else
            return new LocalizedString(key, key);
    }

}

 

Diese Klasse wird im Controller und in der View verwendet, um anschließend die richtige Assembly und die richtige Ressource auszuwählen.

 

ConfigureServices

Wird mit der Methode ConfigureServices aus der Klasse Startup.cs  gearbeitet, so müssen folgende Änderungen getätigt werden, damit die Ressourcen ebenfalls in der anderen Assembly gefunden werden können.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<LocService<Mehrsprachigkeit.Resources.Resources.Views.Home.Index>>();
    services.AddSingleton<LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController>>();

    services.AddControllersWithViews();
    services.AddLocalization();
    services.AddMvc()
    .AddViewLocalization()
    .AddDataAnnotationsLocalization(options =>
    {
        options.DataAnnotationLocalizerProvider = (type, factory) =>
        {
            var assemblyName = new AssemblyName(
                typeof(Mehrsprachigkeit.Resources.Resources.Models)
                .GetTypeInfo().Assembly.FullName);
            return factory.Create("Resources.Models", assemblyName.Name);
        };
    });

    services.Configure<RequestLocalizationOptions>(opts =>
    {
        var supportedCultures = new List<CultureInfo> {
        new CultureInfo("de-DE"),
        new CultureInfo("en-GB"),
        };

        opts.DefaultRequestCulture = new RequestCulture("de-DE");
        opts.SupportedCultures = supportedCultures;
        opts.SupportedUICultures = supportedCultures;
    });
}

 

Nun fügt man die LocService Klasse per Dependency Injection im HomeController und in der Index View hinzu und ändert den Aufruf der StringLocalizer Klasse mit der neuen Methode GetLocalizedHtmlString.

public class HomeController : Controller
{
    private readonly LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController> _localizer;
    public HomeController(LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController> localizer)
    {
        _localizer = localizer;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _localizer.GetLocalizedHtmlString("Hallo Welt vom Controller");
        return View();
    }
}
@using Microsoft.AspNetCore.Mvc.Localization
@model Mehrsprachigkeit.Models.Models.Contact

@inject  Mehrsprachigkeit.Resources.LocService<Mehrsprachigkeit.Resources.Resources.Views.Home.Index> AccountLocalizer

<h1>@ViewData["Title"]</h1>
<h3 class="text-danger">@AccountLocalizer.GetLocalizedHtmlString("Hallo Welt von der View")</h3>

@Html.LabelFor(c => c.Firstname)
@Html.LabelFor(c => c.Lastname)

 

Nun wurden die Ressourcen erfolgreich in eine andere Assembly verschoben und der Aufruf der Lokalisierung so angepasst, dass die Ressourcen in der anderen Assembly gefunden werden können.

Das Ergebnis

 

Die Mehrsprachigkeit in einem Projekt ohne verschiedene Assemblys ist recht einfach zu realisieren.

Sobald die Ressourcen jedoch in einer separaten Assembly programmiert werden sollen, weist dies eine deutlich höhere Komplexität auf. Wichtig ist hierbei, direkt zu Beginn strategisch zu entscheiden, ob für jedes DataModel eine eigene Ressource angelegt werden soll oder ob man eine einheitliche Ressource dafür verwendet. Letzteres ist definitiv einfacher umzusetzen und in diesem Blog Artikel angewendet worden.

Expertentipp: Ohne eine zusätzliche Klasse LocService wird eine separate Assembly vermutlich nicht umsetzbar sein.

Maurice Jungmann| Softwareentwickler | 20.08.2020

 

 

Sie suchen einen Software Anbieter?
Sprechen Sie uns an