Laden...

HTML Mails Format

Erstellt von Kriz vor 2 Jahren Letzter Beitrag vor 2 Jahren 338 Views
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 2 Jahren
HTML Mails Format

Moin,

in einigen Asp.NET Projekten (Sowohl MVC, als auch API) versende ich Mails, am liebsten HTML formatiert.

Gibt es einen schönen Weg HTML formatierte EMails zu erstellen?
Mein aktuelles Vorgehen:

  1. HTML Template mit VS Code erstellen
  2. das HTML File als string in mein C# File kopieren
  3. per string.Replace() die Platzhalter ausfüllen

Was mich daran stört, ist der teils ellenlange HTML-string. Man kann ihn einfach schlecht lesen.
Wenn ich eine Kleinigkeit an der Mail ändern will suche ich mich teils blöd, oder muss dann erst wieder umständlich in VS Code editieren, kopieren, usw.
Schön wäre es ja, wenn ich mit Razor arbeiten könnte.

Welche Ansätze verfolgt ihr denn so?
An die Admins, bei Mails vom Forum steht in der Signatur "Made with ASP.Net", bezieht sich das aufs Forum, oder hab ich da bei Asp.Net eine Möglichkeit übersehen Mails zu erstellen?

Danke schonmal!

D
152 Beiträge seit 2013
vor 2 Jahren

Schau Dir mal folgenden Thread an Dokument mit C# und HTML

3.825 Beiträge seit 2006
vor 2 Jahren

Ich erstelle die Mailvorlagen mit einem HTML Editor.

Da gibt es viele Fertige.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

16.835 Beiträge seit 2008
vor 2 Jahren

Welche Ansätze verfolgt ihr denn so?
An die Admins, bei Mails vom Forum steht in der Signatur "Made with ASP.Net", bezieht sich das aufs Forum, oder hab ich da bei Asp.Net eine Möglichkeit übersehen Mails zu erstellen?

Beides.

Sowohl das Forum wie auch die Mails werden mit Hilfe von ASP.NET Core generiert. ASP.NET Core ist nur eine Framework aus vielen Bestandteilen.
Du bekommst nirgends die Vorgabe "Hier, das hier ist für E-Mails" - sondern Du kannst Dir einfach ein Baustein nehmen - zB Razor Render - und damit machen, was Du willst.
Man kann auch ASP.NET Core als Framework verwenden um Windows Services zu machen, die nachher Files überwachen. Razor (bzw. MVC) ist nur eine Middleware, die austauschbar ist.
Beim Forum eben die Views als Razor, bei den E-Mails die MailView selbst als Razor.

Dazu haben wir zwei Projekte:

  • MyCSharp.Portal.Notifications.EMail.WebApp - damit Testen wir die E-Mails
  • MyCSharp.Portal.Notifications.EMail - damit generieren wir die E-Mails (hier liegen auch die Views drin)
    Beide Projekte sind ASP.NET Core Projekte bzw haben eine Reference:

<Project Sdk="Microsoft.NET.Sdk.Razor">

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <Nullable>enable</Nullable>
        <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
    </PropertyGroup>

    <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
    </ItemGroup>

Durch die Reference auf Microsoft.AspNetCore.App kannst Du Dir einen Render Context erstellen, mit dem Du dann einfach eine Page rendern kannst.


public class RazorViewRenderProvider : IRazorViewRenderProvider
{
    private readonly IRazorViewEngine _viewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IServiceProvider _serviceProvider;

    public RazorViewRenderProvider(
        IRazorViewEngine viewEngine,
        ITempDataProvider tempDataProvider,
        IServiceProvider serviceProvider)
    {
        _viewEngine = viewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
    }

    public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
    {
        ActionContext actionContext = GetActionContext();
        IView view = FindView(actionContext, viewName);

        using StringWriter output = new();
        ViewContext viewContext = new(
            actionContext,
            view,
            new ViewDataDictionary<TModel>(
                metadataProvider: new EmptyModelMetadataProvider(),
                modelState: new ModelStateDictionary())
            {
                Model = model
            },
            new TempDataDictionary(
                actionContext.HttpContext,
                _tempDataProvider),
            output,
            new HtmlHelperOptions());

        await view.RenderAsync(viewContext).ConfigureAwaitFalse();

        return output.ToString();
    }

    private IView FindView(ActionContext actionContext, string viewName)
    {
        ViewEngineResult vrByPath = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
        if (vrByPath.Success)
        {
            return vrByPath.View;
        }

        ViewEngineResult vrByContext = _viewEngine.FindView(actionContext, viewName, isMainPage: true);
        if (vrByContext.Success)
        {
            return vrByContext.View;
        }

        IEnumerable<string> searchedLocations = vrByPath.SearchedLocations.Concat(vrByContext.SearchedLocations);
        string errorMessage = string.Join(
            Environment.NewLine,
            new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations)); ;

        throw new InvalidOperationException(errorMessage);
    }

    private ActionContext GetActionContext()
    {
        DefaultHttpContext httpContext = new() { RequestServices = _serviceProvider };
        return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
    }
}

Rendern geht dann einfach via


    public Task<string> Render<T>(T model) where T : MailModel
        => _renderProvider.RenderViewToStringAsync($"~/Views/{model.GetType().Name}.cshtml", model);

Unser model heisst dann einfach wie die View.

Ich mach das prinzipiell so in vielen Projekten, wo der Kunde kein MailJet, SendGrid... verwenden will.
Ansonsten würde ich immer solche Anbieter bevorzugen.

https://github.com/sebastienros/fluid ist auch ein sehr gutes Projekt und ist von den Ressourcen auch effizienter als die Razor Render Variante.
Ich spiel schon mit dem Gedanken auf Fluid umzubauen 😁