Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
HTML Mails Format
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 115

Themenstarter:

HTML Mails Format

beantworten | zitieren | melden

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!
private Nachricht | Beiträge des Benutzers
david.m
myCSharp.de - Member



Dabei seit:
Beiträge: 130

beantworten | zitieren | melden

Schau Dir mal folgenden Thread an Dokument mit C# und HTML
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3.764
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Ich erstelle die Mailvorlagen mit einem HTML Editor.

Da gibt es viele Fertige.

Grüße Bernd
Attachments
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.851

beantworten | zitieren | melden

Zitat von Kriz
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
private Nachricht | Beiträge des Benutzers