ASP.Net MVC: Gebruik web.config in Domain/MVC Controller

Pagina: 1
Acties:

Onderwerpen

Vraag


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
Doel
Mails verzenden vanuit een ASP.NET MVC 5 web application: als gebruikers zich inschrijven voor een activiteit automatisch een mail zenden.

De basics
Op zich is het verzenden van een mail niet moeilijk: gebruik maken van de classes SmtpClient en MailMessage uit de namespace System.Net.Mail.

Idee
Om dit netjes af te handelen, wil ik graag de instellingen voor de SMTP-client uitlezen uit web.config, daar een SmtpClient-object mee instantiëren en die gebruiken in een MVC Controller of de Domain Controller. Om het helemaal netjes te maken (versta: performantie) wil ik die SMTP Client maar 1 x instellen (waardoor de instellingen uit web.config maar 1 x ingelezen moeten worden).

Wat is er?
Ik heb aan oplossing uitgewerkt die parallel loopt met hoe Auth0 wordt geïmplementeerd: in Startup.Configuration(IAppBuilder app) roep ik de ConfigureMail-methode op om daar OWIN interface IAppBuilder als parameter aan door te geven:
C#:
1
2
3
4
5
6
7
8
public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            ConfigureMail(app);
        }
    }


Op deze manier wordt de web.config slechts 1x uitgelezen. Zouden de gegevens daarin veranderen, dan wordt AppPool automatisch gerecycled en die gegevens spontaan opnieuw ingelezen.

Die ConfigureMail-methode is als volgt gedefinieerd:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public partial class Startup
{
    private static string mailServer = ConfigurationManager.AppSettings["mail:SmtpServer"];
    private static string mailPort = ConfigurationManager.AppSettings["mail:SmtpPort"];
    private static string mailUser = ConfigurationManager.AppSettings["mail:User"];
    private static string mailPassword = ConfigurationManager.AppSettings["mail:Password"];
    private static string mailSenderName = ConfigurationManager.AppSettings["mail:SenderName"];

    public void ConfigureMail(IAppBuilder app)
    {
        // Create a mailClient that can be used in the app
        int mailPortNumber;
        if (!int.TryParse(mailPort, out mailPortNumber))
        {
            mailPortNumber = 587; // default TLS value
        }
        SmtpClient smtpClient = new SmtpClient(mailServer, mailPortNumber);
        smtpClient.UseDefaultCredentials = false;
        smtpClient.Credentials = new System.Net.NetworkCredential(mailUser, mailPassword);
        smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
        smtpClient.EnableSsl = true;

        // Add the SMTP-client to the app, so it can be used in MVC/Domain Controller --> CORRECT????
        app.Properties.Add("smtpClient", smtpClient);
    }
}


Het relevante gedeelte van web.config ziet er als volgt uit:
XML:
1
2
3
4
5
6
7
  <appSettings>
    <add key="mail:SmtpServer" value="smtp.office365.com" />
    <add key="mail:SmtpPort" value="587" />
    <add key="mail:User" value="mailaccount" />
    <add key="mail:Password" value="password-mailaccount" />
    <add key="mail:SenderName" value="sendername" />
  </appSettings>


Waar loopt het mis?
Op het feit dat ik geen idee heb hoe ik vanuit een MVC Controller of de Domain Controller aan die ingestelde SMTP Client geraak, ook niet na verscheidene uren googelen (allicht gebruik ik niet de juiste term). Voor .NET Core lijkt het wat makkelijker te vinden, maar het gebruikte framework is .NET Framework v4.6.1 (niet ideaal, ik weet het, maar omwille van beschikbaarheid op web hosting).

Wat verwacht ik van jullie?
  1. is mijn redenering om het zo aan te pakken hoegenaamd wel de juiste?
  2. hoe raak ik dan aan dat object?
Wie-o-wie kan me op weg zetten?
THX!!!

[ Voor 5% gewijzigd door edeboeck op 07-03-2020 16:38 . Reden: Gedeelte van web.config toegevoegd ]

Beste antwoord (via edeboeck op 08-03-2020 19:23)


  • Saeverix
  • Registratie: Maart 2002
  • Laatst online: 15-05 15:20
Een aantal opmerkingen:

• SmtpClient is als obsolete gemarkeerd door Microsoft. Ze adviseren zelf om een libary als MailKit te gebruiken: https://github.com/dotnet...lob/master/docs/DE0005.md, https://docs.microsoft.co...=netframework-4.8#remarks en https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official/
• SmtpClient is een IDisposable je kan het daarom in een using statement gebruiken: https://docs.microsoft.co.../keywords/using-statement
• Smtp configuratie is als het goed is allemaal in de Web.config te doen: https://docs.microsoft.co...s?view=netframework-4.6.1 en https://stackoverflow.com/a/31356582

Chookity-pok

Alle reacties


Acties:
  • +1 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 19:42

Haan

dotnetter

Je hebt een oplossing gekozen die ik zelf nog niet eerder heb gezien. Of dat erg is laat ik verder in het midden ;)
Er zijn talloze manier om dit aan te pakken. Een oplossing die een beetje aansluit op wat je nu aan het doen bent is Dependency Injection gaan implementeren (sowieso handig om te doen). Je registreert dan eenmalig je smtp client en deze kan je vervolgens overal opvragen waar nodig (simpel gezegd)

Kater? Eerst water, de rest komt later


Acties:
  • Beste antwoord
  • +2 Henk 'm!

  • Saeverix
  • Registratie: Maart 2002
  • Laatst online: 15-05 15:20
Een aantal opmerkingen:

• SmtpClient is als obsolete gemarkeerd door Microsoft. Ze adviseren zelf om een libary als MailKit te gebruiken: https://github.com/dotnet...lob/master/docs/DE0005.md, https://docs.microsoft.co...=netframework-4.8#remarks en https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official/
• SmtpClient is een IDisposable je kan het daarom in een using statement gebruiken: https://docs.microsoft.co.../keywords/using-statement
• Smtp configuratie is als het goed is allemaal in de Web.config te doen: https://docs.microsoft.co...s?view=netframework-4.6.1 en https://stackoverflow.com/a/31356582

Chookity-pok


Acties:
  • +2 Henk 'm!

  • Xudonax
  • Registratie: November 2010
  • Laatst online: 01:54
Je kunt ook de standaard ASP.NET manier gebruiken en dit in de <system.net> configuratie plaatsen, zoals @Saeverix ook al aangeeft. Je krijgt dan zoiets in je Web.config:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
<configuration>
 <system.net>
        <mailSettings>
            <smtp from="yourmail@gmail.com">
                <network host="smtp.gmail.com" 
                 port="587" 
                 userName="yourmail@gmail.com" 
                 password="yourpassword" 
                 enableSsl="true"/>
            </smtp>
        </mailSettings>
</system.net>
</configuration>

Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
Haan schreef op zaterdag 7 maart 2020 @ 15:34:
Je hebt een oplossing gekozen die ik zelf nog niet eerder heb gezien. Of dat erg is laat ik verder in het midden ;)
Er zijn talloze manier om dit aan te pakken. Een oplossing die een beetje aansluit op wat je nu aan het doen bent is Dependency Injection gaan implementeren (sowieso handig om te doen). Je registreert dan eenmalig je smtp client en deze kan je vervolgens overal opvragen waar nodig (simpel gezegd)
Ik wil dat gerust mee in het midden laten :+ Ben inderdaad op een dependency injection-achtige manier aan het werk, maar daar zit ik dus met het probleem hoe ik die kan gaan accessen... wil me er wel in verdiepen, maar vraag me af of ik de boel niet nodeloos ingewikkeld maak dan. :?
Saeverix schreef op zaterdag 7 maart 2020 @ 15:37:
Een aantal opmerkingen:

• SmtpClient is als obsolete gemarkeerd door Microsoft. Ze adviseren zelf om een libary als MailKit te gebruiken: https://github.com/dotnet...lob/master/docs/DE0005.md, https://docs.microsoft.co...=netframework-4.8#remarks en https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official/
Wow, loop al bijna 3 jaar achter :X Bedankt, dat wist ik nog niet!
Saeverix schreef op zaterdag 7 maart 2020 @ 15:37:• SmtpClient is een IDisposable je kan het daarom in een using statement gebruiken: https://docs.microsoft.co.../keywords/using-statement
Ik ken het using-statement, maar vraag me af waarom je dat hier aanhaalt... mis ik iets voor mijn concrete situatie?
Xudonax schreef op zaterdag 7 maart 2020 @ 15:38:
Je kunt ook de standaard ASP.NET manier gebruiken en dit in de <system.net> configuratie plaatsen, zoals @Saeverix ook al aangeeft. Je krijgt dan zoiets in je Web.config:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
<configuration>
 <system.net>
        <mailSettings>
            <smtp from="yourmail@gmail.com">
                <network host="smtp.gmail.com" 
                 port="587" 
                 userName="yourmail@gmail.com" 
                 password="yourpassword" 
                 enableSsl="true"/>
            </smtp>
        </mailSettings>
</system.net>
</configuration>
Ik had die info wel degelijk in mijn web.config staan, maar op meer primitieve manier (in appSettings de keys apart toevoegen). Dit brengt me tot de volgende vraag: als ik een SmtpClient- (of bij voorkeur "MailKit-object" - ik moet dat nog grondig lezen)object instantieer, gebruikt die dan automatisch de settings uit mailSettings (ik zou verwachten van wel).
Als het antwoord op die vraag "ja" luidt, komt dan volgens mij de sleutelvraag voor mijn probleem: wordt dat telkens opnieuw uit web.config uitgelezen (wat me niet ideaal lijkt - het gaat om een 2000-tal unieke inschrijvingen op korte termijn waarbij men die inschrijving nog kan aanpassen) of gaat hij die gegevens ergens cachen?

De sleutelvraag zou natuurlijk ook kunnen zijn: schat ik de impact van dat uitlezen niet te zwaar in? :+

Ik lees me alvast in in de links, al bedankt voor jullie feedback!

Acties:
  • +1 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 07-05 20:56
edeboeck schreef op zaterdag 7 maart 2020 @ 16:33:
Ik ken het using-statement, maar vraag me af waarom je dat hier aanhaalt... mis ik iets voor mijn concrete situatie?
Single-instantiation is een beetje gevaarlijk als consumerende classes de instance kunnen disposen.
Je kunt dan beter een factory in je dependency injection container registeren; die factory injecteren in elk van je consumerende classes; en dan daarmee een client aanmaken die gereserveerd is voor gebruik door elke individuele consumerende class.

Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Laatst online: 17:17

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

edeboeck schreef op zaterdag 7 maart 2020 @ 16:33:
[...]
De sleutelvraag zou natuurlijk ook kunnen zijn: schat ik de impact van dat uitlezen niet te zwaar in? :+
Het korte antwoord? Ja
Het lange antwoord? Meten == weten. Voor een site waar 2000 registraties (=/= emails) verwacht worden (ik neem aan over een langere periode) is het totaal verwaarloosbaar; pas als je er 2000 per seconde ofzo wil gaan versturen dan wordt het wellicht interessant. Heb je het over 2000 per uur, dag of week: waar heb je het dan over?

[ Voor 33% gewijzigd door RobIII op 07-03-2020 17:08 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
RobIII schreef op zaterdag 7 maart 2020 @ 17:05:
[...]
Het korte antwoord? Ja
Het lange antwoord? Meten == weten
Helaas heb ik op dit moment niet de tijd om het uitvoerig te gaan testen... daarom al bedankt voor het korte antwoord!
R4gnax schreef op zaterdag 7 maart 2020 @ 16:43:
[...]
Single-instantiation is een beetje gevaarlijk als consumerende classes de instance kunnen disposen.
Je kunt dan beter een factory in je dependency injection container registeren; die factory injecteren in elk van je consumerende classes; en dan daarmee een client aanmaken die gereserveerd is voor gebruik door elke individuele consumerende class.
Ok, ik "vreesde" hier al een beetje voor... spijtig genoeg niet de tijd om het uit te werken op de manier dat ik het écht graag wil doen.

[ Voor 50% gewijzigd door edeboeck op 07-03-2020 17:08 . Reden: Reactie op R4gnax toegevoegd ]


Acties:
  • +1 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

edeboeck schreef op zaterdag 7 maart 2020 @ 15:10:
Doel
Mails verzenden vanuit een ASP.NET MVC 5 web application: als gebruikers zich inschrijven voor een activiteit automatisch een mail zenden.

De basics
Op zich is het verzenden van een mail niet moeilijk: gebruik maken van de classes SmtpClient en MailMessage uit de namespace System.Net.Mail.

Idee
Om dit netjes af te handelen, wil ik graag de instellingen voor de SMTP-client uitlezen uit web.config, daar een SmtpClient-object mee instantiëren en die gebruiken in een MVC Controller of de Domain Controller. Om het helemaal netjes te maken (versta: performantie) wil ik die SMTP Client maar 1 x instellen (waardoor de instellingen uit web.config maar 1 x ingelezen moeten worden).

Wat is er?
Ik heb aan oplossing uitgewerkt die parallel loopt met hoe Auth0 wordt geïmplementeerd: in Startup.Configuration(IAppBuilder app) roep ik de ConfigureMail-methode op om daar OWIN interface IAppBuilder als parameter aan door te geven:
C#:
1
2
3
4
5
6
7
8
public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            ConfigureMail(app);
        }
    }


Op deze manier wordt de web.config slechts 1x uitgelezen. Zouden de gegevens daarin veranderen, dan wordt AppPool automatisch gerecycled en die gegevens spontaan opnieuw ingelezen.

Die ConfigureMail-methode is als volgt gedefinieerd:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public partial class Startup
{
    private static string mailServer = ConfigurationManager.AppSettings["mail:SmtpServer"];
    private static string mailPort = ConfigurationManager.AppSettings["mail:SmtpPort"];
    private static string mailUser = ConfigurationManager.AppSettings["mail:User"];
    private static string mailPassword = ConfigurationManager.AppSettings["mail:Password"];
    private static string mailSenderName = ConfigurationManager.AppSettings["mail:SenderName"];

    public void ConfigureMail(IAppBuilder app)
    {
        // Create a mailClient that can be used in the app
        int mailPortNumber;
        if (!int.TryParse(mailPort, out mailPortNumber))
        {
            mailPortNumber = 587; // default TLS value
        }
        SmtpClient smtpClient = new SmtpClient(mailServer, mailPortNumber);
        smtpClient.UseDefaultCredentials = false;
        smtpClient.Credentials = new System.Net.NetworkCredential(mailUser, mailPassword);
        smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
        smtpClient.EnableSsl = true;

        // Add the SMTP-client to the app, so it can be used in MVC/Domain Controller --> CORRECT????
        app.Properties.Add("smtpClient", smtpClient);
    }
}


Het relevante gedeelte van web.config ziet er als volgt uit:
XML:
1
2
3
4
5
6
7
  <appSettings>
    <add key="mail:SmtpServer" value="smtp.office365.com" />
    <add key="mail:SmtpPort" value="587" />
    <add key="mail:User" value="mailaccount" />
    <add key="mail:Password" value="password-mailaccount" />
    <add key="mail:SenderName" value="sendername" />
  </appSettings>


Waar loopt het mis?
Op het feit dat ik geen idee heb hoe ik vanuit een MVC Controller of de Domain Controller aan die ingestelde SMTP Client geraak, ook niet na verscheidene uren googelen (allicht gebruik ik niet de juiste term). Voor .NET Core lijkt het wat makkelijker te vinden, maar het gebruikte framework is .NET Framework v4.6.1 (niet ideaal, ik weet het, maar omwille van beschikbaarheid op web hosting).

Wat verwacht ik van jullie?
  1. is mijn redenering om het zo aan te pakken hoegenaamd wel de juiste?
  2. hoe raak ik dan aan dat object?
Wie-o-wie kan me op weg zetten?
THX!!!
Dit voelt aan als twee verschillende "systemen". Aangezien de mailclient het netwerk weer op gaat zou ik dit niet in je MVC applicatie doen, dat er een delay in de mail zit is ook niet echt een probleem aangezien mail per definitie "asynchroon" is.

Ik zou een los stuk logica/programmatuur schrijven waarbij de email afhandeling helemaal los staat van je MVC applicatie. Een kleine executable die een tabel uitleest met te versturen mails bijvoorbeeld. Of de mails naar disk serializen en deze door een watcher laten mailen etc. etc. Deze mailer kan dan de hoofdapplicatie verwittigen dat de mails zijn verstuurd enz.

Jas de mailer in een aparte docker container en je Micro Service'd jezelf all the way to the bank.

Less alienation, more cooperation.


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
Sandor_Clegane schreef op zondag 8 maart 2020 @ 13:04:
[...]


Dit voelt aan als twee verschillende "systemen". Aangezien de mailclient het netwerk weer op gaat zou ik dit niet in je MVC applicatie doen, dat er een delay in de mail zit is ook niet echt een probleem aangezien mail per definitie "asynchroon" is.

Ik zou een los stuk logica/programmatuur schrijven waarbij de email afhandeling helemaal los staat van je MVC applicatie. Een kleine executable die een tabel uitleest met te versturen mails bijvoorbeeld. Of de mails naar disk serializen en deze door een watcher laten mailen etc. etc. Deze mailer kan dan de hoofdapplicatie verwittigen dat de mails zijn verstuurd enz.

Jas de mailer in een aparte docker container en je Micro Service'd jezelf all the way to the bank.
Fijne gedachtegang, helaas heb ik niet de tijd (noch de Docker-kennis) om dat uit te voeren.
RobIII schreef op zaterdag 7 maart 2020 @ 17:05:
[...]

Het korte antwoord? Ja
Het lange antwoord? Meten == weten. Voor een site waar 2000 registraties (=/= emails) verwacht worden (ik neem aan over een langere periode) is het totaal verwaarloosbaar; pas als je er 2000 per seconde ofzo wil gaan versturen dan wordt het wellicht interessant. Heb je het over 2000 per uur, dag of week: waar heb je het dan over?
Sorry @RobIII , had jouw edit waarin je meer duidelijkheid over het aantal vraagt, nog niet gezien. Die 2000 registraties zijn inderdaad het totale aantal en de gelijktijdige belasting zou moeten meevallen: aangezien we nauwelijks budget hebben, hebben we besloten om de inschrijvingen te spreiden: eerste week ongeveer 430, volgende week een kleine 1300, laatste 3 dagen 300. De impact van het veranderen van inschrijvingen (als deelnemers inschrijvingen op elkaar gaan afstemmen) waardoor er extra mails verzonden worden, kunnen we momenteel nog niet inschatten. De mails worden verzonden via Office365 dus via die dedicated mailbox kan ik het mailverkeer wel een beetje opvolgen.

Voor het geval iemand ooit hetzelfde probleem tegenkomt, post ik hier de opbouw van mijn oplossing:
  1. SMTP-client instellen in web.config zoals @Saeverix en @Xudonax aangaven:
    XML:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <configuration>
     <system.net>
            <mailSettings>
                <smtp from="yourmail@gmail.com">
                    <network host="smtp.gmail.com" 
                     port="587" 
                     userName="yourmail@gmail.com" 
                     password="yourpassword" 
                     enableSsl="true"/>
                </smtp>
            </mailSettings>
    </system.net>
    </configuration>
    Belangrijke kanttekening daarbij: wachtwoorden waarin een ampersand of dubbele quote voorkomt in een XML-file stoppen is niet zo'n goed idee (zelfs niet als je aan HTML-encoding gaat doen - al is de kans groot dat ik daar door de vermoeidheid een fout gemaakt heb).
  2. Mails verzenden met behulp van MailKit, aangezien Microsoft dat zelf aanraadt als vervanger voor System.Net.Mail.SmtpClient (opnieuw dank aan @Saeverix )
  3. De mailfunctie(s) heb ik gedefinieerd in mijn DomainController. @RobIII gaf al aan dat de performance hit van het uitlezen uit web.config niet groot is. Het leek me dus geen issue meer, maar omdat mijn DomainController toch al een Singleton was, heb ik ervoor gekozen om in de constructor de gegevens uit web.config uitgelezen worden... het lijkt me namelijk ook geen kwaad te kunnen om het uitlezen tot 1 keer te beperken. :+
  4. De MVC Controllers hebben telkens een DomainController-instance via dewelke de mailfunctie wordt opgeroepen.
Bedankt allemaal voor de zinvolle input! Spijtig genoeg heb ik niet de tijd om al jullie suggesties eens uit te proberen (o, wat zou het fijn zijn als die tijd er wél zou zijn!).
Aangezien ik alle tips van @Saeverix toepas in mijn oplossing, markeer ik zijn oplossing als antwoord.

[ Voor 16% gewijzigd door edeboeck op 08-03-2020 19:23 . Reden: Reactie op Edit van RobIII ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Laatst online: 17:17

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

edeboeck schreef op zondag 8 maart 2020 @ 19:12:
Die 2000 registraties zijn inderdaad het totale aantal en de gelijktijdige belasting zou moeten meevallen: aangezien we nauwelijks budget hebben, hebben we besloten om de inschrijvingen te spreiden: eerste week ongeveer 430, volgende week een kleine 1300, laatste 3 dagen 300.
Dus "peak" doe je 1300 p/week, dat is ~185 per dag, dat is 23 p/u (als ik even van 9:00 tot 17:00 tel en dus niet over 24 uur kijk) en dat komt neer op 1 registratie iedere ~2 a 3 minuten. De 'optimalisatie' waar het over ging ('uitlezen van de web.config') spaart je hooguit (fracties van) een milliseconde... waar heb je 't dan nog over? Als je dan toch je tijd beter/efficiënter wil gebruiken ("niet de tijd om het uitvoerig te gaan testen", "niet de tijd om het uit te werken", "niet de tijd om al jullie suggesties eens uit te proberen") dan begin eens met op te houden aan premature optimization te doen ;) Zélfs al duurde 't uitlezen van de web.config 100ms of een seconde, dan nog was er niets aan de hand (behalve dat je bezoeker misschien iets langer moet wachten tot de 'dank u!'-pagina getoond wordt; wat natuurlijk een ander verhaal is...

[ Voor 14% gewijzigd door RobIII op 08-03-2020 19:33 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 07-05 20:56
edeboeck schreef op zondag 8 maart 2020 @ 19:12:

Belangrijke kanttekening daarbij: wachtwoorden waarin een ampersand of dubbele quote voorkomt in een XML-file stoppen is niet zo'n goed idee (zelfs niet als je aan HTML-encoding gaat doen - al is de kans groot dat ik daar door de vermoeidheid een fout gemaakt heb).[/li]
Wachtwoorden in een XML config file steken is geen goed idee - full stop. Je zou naar een key-vault oplossing moeten kijken voor dat soort zaken, of op z'n minst deze uit een file moeten uitlezen wat enkel op je webserver (goed afgeschermd) staat. Build servers; source-control repositories; etc. zouden dat wachtwoord niet te zien moeten krijgen.
De mailfunctie(s) heb ik gedefinieerd in mijn DomainController. @RobIII gaf al aan dat de performance hit van het uitlezen uit web.config niet groot is. Het leek me dus geen issue meer, maar omdat mijn DomainController toch al een Singleton was, heb ik ervoor gekozen om in de constructor de gegevens uit web.config uitgelezen worden... het lijkt me namelijk ook geen kwaad te kunnen om het uitlezen tot 1 keer te beperken.
Dat is een beetje de poor-man's versie van middels DI een factory injecteren en de factory de configuratie eenmalig uit laten lezen, en kopietjes ervan mee geven aan elke mail client instance die zo'n factory zou produceren. Had je al een DI oplossing in gebruik gehad, dan was dat een hele makkelijke weg geweest om dit zeer kleine stukje optimalisatie mee in te voegen.
Bedankt allemaal voor de zinvolle input! Spijtig genoeg heb ik niet de tijd om al jullie suggesties eens uit te proberen (o, wat zou het fijn zijn als die tijd er wél zou zijn!).
In dat geval is de meest zinvolle input wellicht nog niet gegeven:

ik weet niet wat je exacte arbeidssituatie is, maar als je niet de tijd kunt nemen om dit soort zaken goed op te bouwen, dan is het belangrijkste waarschijnlijk nog wel dat je aan de bel trekt bij de verantwoordelijke personen binnen je development team. Want dan klopt je urenbudgetering voor dit werk niet; klopt de verwachtte vereiste kennis niet; of is de feature in z'n algemeenheid gewoon grof onderschat in complexiteit en aantal bewegende delen.

Of het exact omgekeerde: je maakt het zelf te moeilijk.
Wat eigenlijk is wat net door RobIII ook gepost is:
RobIII schreef op zondag 8 maart 2020 @ 19:27:
begin eens met op te houden aan premature optimization te doen ;)

[ Voor 8% gewijzigd door R4gnax op 08-03-2020 19:34 ]


Acties:
  • 0 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

Je hoeft het niet perse in een container te draaien, een tweede executable werkt ook prima.

Less alienation, more cooperation.


Acties:
  • 0 Henk 'm!

  • Saeverix
  • Registratie: Maart 2002
  • Laatst online: 15-05 15:20
edeboeck schreef op zondag 8 maart 2020 @ 19:12:
[...]
Bedankt allemaal voor de zinvolle input! Spijtig genoeg heb ik niet de tijd om al jullie suggesties eens uit te proberen (o, wat zou het fijn zijn als die tijd er wél zou zijn!).
Aangezien ik alle tips van @Saeverix toepas in mijn oplossing, markeer ik zijn oplossing als antwoord.
Mooi dat het gelukt is. Blijf vooral experimenteren met hoe je de implementatie nog mooier/beter kan maken.
R4gnax schreef op zondag 8 maart 2020 @ 19:31:
Wachtwoorden in een XML config file steken is geen goed idee - full stop. Je zou naar een key-vault oplossing moeten kijken voor dat soort zaken, of op z'n minst deze uit een file moeten uitlezen wat enkel op je webserver (goed afgeschermd) staat. Build servers; source-control repositories; etc. zouden dat wachtwoord niet te zien moeten krijgen.
Naar mijn mening moet je dit iets anders formuleren. Waar jij op doelt is dat je geen wachtwoorden in het gebruikte Version Control systeem moet zetten. Wachtwoorden in een (XML) config file is in principe niets mis mee, als je maar zorgt dat het op de webserver afgeschermd is voor buiten en dat het niet in je Version Control komt.

Een veelgebruikte oplossing daarvoor is de zogenaamde Web.config Transform files. Die bestanden zet je op de webserver of in de Azure AD configuratie en worden bij release op de webserver in de Web.config van het project "gemerged". Die bestanden komen idealiter niet in Version Control.
Indien het releasen van het project al via Azure gebeurt dan kun je inderdaad beter direct voor een Key Vault oplossing gaan.

[ Voor 17% gewijzigd door Saeverix op 08-03-2020 20:02 ]

Chookity-pok


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
RobIII schreef op zondag 8 maart 2020 @ 19:27:
[...]

Dus "peak" doe je 1300 p/week, dat is ~185 per dag, dat is 23 p/u (als ik even van 9:00 tot 17:00 tel en dus niet over 24 uur kijk) en dat komt neer op 1 registratie iedere ~2 a 3 minuten. De 'optimalisatie' waar het over ging ('uitlezen van de web.config') spaart je hooguit (fracties van) een milliseconde... waar heb je 't dan nog over? Als je dan toch je tijd beter/efficiënter wil gebruiken ("niet de tijd om het uitvoerig te gaan testen", "niet de tijd om het uit te werken", "niet de tijd om al jullie suggesties eens uit te proberen") dan begin eens met op te houden aan premature optimization te doen ;) Zélfs al duurde 't uitlezen van de web.config 100ms of een seconde, dan nog was er niets aan de hand (behalve dat je bezoeker misschien iets langer moet wachten tot de 'dank u!'-pagina getoond wordt; wat natuurlijk een ander verhaal is...
Bedankt voor het uitrekenen, maar je vermoedde allicht zelf wel dat het in de realiteit nooit zo mooi gespreid is ;) Omdat de inschrijvingen starten op een bepaald, op voorhand meegedeeld tijdstip, verwachten we een "golf" (het zou me niet verbazen, moesten we meer dan 50% van de personen ingeschreven hebben binnen het eerste uur). Los daarvan heb je gelijk wat mijn "premature optimization"-aandoening betreft :X ... die was in dit geval nog aangewakkerd omdat de vorige server voor onze projectjes zo extreem traag was (daarom hebben we voor deze toepassing een aparte - goedkope - hosting).

Om wat duiding te geven n.a.v. de opmerkingen van @R4gnax : deze oplossing zal inderdaad geen schoonheidswedstrijd winnen. Echter vind ik het project als dusdanig wel de moeite waard... ik verklaar me nader:
ik geef softwareontwikkeling op een secundaire school (in België, weet niet of die benaming in NL ook gebruikt wordt) waar ik voor mijn laatstejaars (leerlingen van 17-18 jaar) graag realistische projecten gebruik. In dit geval heb ik me een "beetje" mispakt: onze LO-leerkrachten gebruikten in het verleden Smartschool voor inschrijvingen voor de sportdag (de leerlingen hebben keuze uit ruim aanbod)... echter gaf dit voor hen naderhand enorm veel werk bij het opstellen van de lijsten. Omdat ik mijn leerlingen de basis van C# bijbreng en we ook ASP.NET MVC gebruiken, leek het me een fijn idee om hen dat te laten uitwerken. Helaas zijn sommige zaken voor hen te moeilijk om op te lossen binnen de voorziene tijd, maar mag ik anderzijds ook geen geavanceerde oplossingen gebruiken die misschien interessanter zouden zijn. En uiteraard doen zij er véél langer over dan wanneer ik dat alleen zou doen.
Los daarvan moet ik eerlijk toegeven dat ik zelf bepaalde kennis ook ontbreek om het volledig zoals het hoort op te lossen (ben intussen al heel wat jaren weg uit de privé en hoezeer ik toch wat probeer bij te blijven, moet ik eerlijk toegeven dat dat zeker niet lukt zoals ik het graag zou hebben - er is sprake van om leerkrachten ook af en toe stage in bedrijven te laten lopen, maar momenteel is daar nog geen omkadering voor).
Weet niet hoe het met de budgetten van de scholen in NL gesteld is, maar hier in België - of toch het gedeelte waar ik werk - moeten we roeien met de riemen die we hebben (en die zijn veel te kort voor de noden die er zijn).
Sandor_Clegane schreef op zondag 8 maart 2020 @ 19:48:
Je hoeft het niet perse in een container te draaien, een tweede executable werkt ook prima.
Het zou inderdaad netter zijn om dat meer te scheiden (ik pikte in op Docker omdat ik daar al heel lang wat tijd voor zou willen maken).
Saeverix schreef op zondag 8 maart 2020 @ 20:00:
[...]
Mooi dat het gelukt is. Blijf vooral experimenteren met hoe je de implementatie nog mooier/beter kan maken.
Doe ik zeker: ik zou met de leerlingen van volgend jaar een upgrade willen maken (aiaia, als dat maar goedkomt :+ )
Saeverix schreef op zondag 8 maart 2020 @ 20:00:
[...]
Naar mijn mening moet je dit iets anders formuleren. Waar jij op doelt is dat je geen wachtwoorden in het gebruikte Version Control systeem moet zetten. Wachtwoorden in een (XML) config file is in principe niets mis mee, als je maar zorgt dat het op de webserver afgeschermd is voor buiten en dat het niet in je Version Control komt.

Een veelgebruikte oplossing daarvoor is de zogenaamde Web.config Transform files. Die bestanden zet je op de webserver of in de Azure AD configuratie en worden bij release op de webserver in de Web.config van het project "gemerged". Die bestanden komen idealiter niet in Version Control.
Indien het releasen van het project al via Azure gebeurt dan kun je inderdaad beter direct voor een Key Vault oplossing gaan.
We maken inderdaad gebruik van Web.config transformaties (en web.config staat netjes afgeschermd).
Bij Azure was ik niet zo benauwd geweest naar performantie ;)
Ik ben het met jullie eens dat die info best niet in Version Control staat... mag ik even vragen hoe jullie de betrokken files dan uitwisselen/up-to-date houden tussen verschillende developers? Via aparte weg de bestanden kopiëren of zijn er intelligentere manieren?

Bedankt alleszins voor de kritische en zinvolle feedback!

[ Voor 22% gewijzigd door edeboeck op 08-03-2020 20:09 . Reden: Reacties op Sandor_Clegane en Psyrael ]


Acties:
  • +1 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 07-05 20:56
edeboeck schreef op zondag 8 maart 2020 @ 20:01:

ik geef softwareontwikkeling op een secundaire school (in België, weet niet of die benaming in NL ook gebruikt wordt) waar ik voor mijn laatstejaars (leerlingen van 17-18 jaar) graag realistische projecten gebruik. In dit geval heb ik me een "beetje" mispak
Duidelijk. Dan kan ik heel makkelijk begrijpen waar de constraints vandaan komen. :)
edeboeck schreef op zondag 8 maart 2020 @ 20:01:
Ik ben het met jullie eens dat die info best niet in Version Control staat... mag ik even vragen hoe jullie de betrokken files dan uitwisselen/up-to-date houden tussen verschillende developers? Via aparte weg de bestanden kopiëren of zijn er intelligentere manieren?
Werken met gescheiden credentials voor development en live omgevingen is sowieso je primaire verdediging hier. Developers zouden op hun eigen workstations nooit de credentials voor de live omgeving moeten gebruiken. En zouden -- ook wettelijk gezien; privacy GDPR; etc. -- nooit met 'echte' persoonsgegevens uit een live omgeving bezig moeten gaan.

(Als je je klas een realistisch project wilt laten doen, dan is dat een mooi aandachtspuntje om er even uit te lichten. Want het gaat in het bedrijfsleven wel zoooo------- vaak fout op dat vlak. :+)


Wil je daarnaast toch ook nog distributie van de development credentials stricter afregelen en heb je geen direct geintegreerde keyvault beschikbaar om het naadloos in te richten, dan kun je overwegen een vervangend semi-handmatig proces in te richten.

Wat wij bijv. wel eens gedaan hebben is password-vault software gebruiken en een file maken met daarin de credentials voor de development versie van alle services waar een bepaald project uit opgebouwd is. Deze kan veilig(er) gedistribueerd worden via interne mail of kan via een network share toegankelijk gemaakt worden en individuele developers hebben maar één wachtwoord nodig om de andere credentials op te zoeken en in te vullen in een set config transforms die enkel lokaal bestaan en niet ingechecked worden.

(Hoewel je dat laatste moeilijk 100% af kunt dwingen, kun je wel een stok achter de deur houden wanneer het per ongeluk eens mis zou gaan. Praktisch elke moderne source control oplossing heeft daarvoor wel een blacklist optie. Git heeft bijv. het .gitignore file.)

[ Voor 3% gewijzigd door R4gnax op 08-03-2020 20:45 ]


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 20:20

edeboeck

mie noow noooothing ...

Topicstarter
R4gnax schreef op zondag 8 maart 2020 @ 20:43:
[...]


Duidelijk. Dan kan ik heel makkelijk begrijpen waar de constraints vandaan komen. :)


[...]


Werken met gescheiden credentials voor development en live omgevingen is sowieso je primaire verdediging hier. Developers zouden op hun eigen workstations nooit de credentials voor de live omgeving moeten gebruiken. En zouden -- ook wettelijk gezien; privacy GDPR; etc. -- nooit met 'echte' persoonsgegevens uit een live omgeving bezig moeten gaan.

( Als je je klas een realistisch project wilt laten doen; dat is een mooi aandachtspuntje om er uit te lichten. Want dat gaat in het bedrijfsleven wel zoooo------- vaak fout. :+ )


Wil je daarnaast toch ook nog distributie van de development credentials stricter afregelen en heb je geen direct geintegreerde keyvault beschikbaar om het naadloos in te richten, dan kun je overwegen een vervangend semi-handmatig proces in te richten.

Wat wij bijv. wel eens gedaan hebben is password-vault software gebruiken en een file maken met daarin de credentials voor de development versie van alle services waar een bepaald project uit opgebouwd is. Deze kan veilig(er) gedistribueerd worden via interne mail of kan via een network share toegankelijk gemaakt worden en individuele developers hebben maar één wachtwoord nodig om de andere credentials op te zoeken en in te vullen in een set config transforms die enkel lokaal bestaan en niet ingechecked worden.

(Hoewel je dat laatste moeilijk 100% af kunt dwingen, kun je wel een stok achter de deur houden wanneer het per ongeluk eens mis zou gaan. Praktisch elke moderne source control oplossing heeft daarvoor wel een blacklist optie. Git heeft bijv. het .gitignore file.)
Ok, duidelijk en goed idee met die semi-handmatige procedure (bedankt voor t mooie voorbeeld trouwens!). We gebruiken nu al .gitignore, dus dat is goede optie om extra verdedigingslinie in te bouwen.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Laatst online: 17:17

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

edeboeck schreef op zondag 8 maart 2020 @ 20:01:
[...]
het zou me niet verbazen, moesten we meer dan 50% van de personen ingeschreven hebben binnen het eerste uur
Zelfs als alle 2000 in het eerste uur kwamen had je maar iedere ~2 seconden een registratie (average dan). Het wordt pas interessant als je er 2000 per minuut of per seconde probeert te doen ;) En dan zit je bottleneck écht niet daar ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +3 Henk 'm!

  • Saeverix
  • Registratie: Maart 2002
  • Laatst online: 15-05 15:20
edeboeck schreef op zondag 8 maart 2020 @ 20:01:
[...]
We maken inderdaad gebruik van Web.config transformaties (en web.config staat netjes afgeschermd).
Bij Azure was ik niet zo benauwd geweest naar performantie ;)
Ik ben het met jullie eens dat die info best niet in Version Control staat... mag ik even vragen hoe jullie de betrokken files dan uitwisselen/up-to-date houden tussen verschillende developers? Via aparte weg de bestanden kopiëren of zijn er intelligentere manieren?

Bedankt alleszins voor de kritische en zinvolle feedback!
Zoals al eerder aangegeven moeten die bestanden/instellingen alleen staan op bijvoorbeeld de Productieserver of CI Server (indien je geautomatiseerd releases doet).

In het geval van een mailserver zoals in dit topic, zijn er handige tools beschikbaar zoals smtp4dev en Papercut. Dat zijn lokale mailservers die op je eigen PC draaien en alle verzonden mail opvangen in de applicatie. Je moet de mailserver in de Web.config dan instellen op localhost. Op die manier kun je volledige mailfuncties in je software testen zonder daadwerkelijk ook echt een mail te versturen. https://github.com/rnwood/smtp4dev en https://github.com/ChangemakerStudios/Papercut

Chookity-pok

Pagina: 1