Notification system

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I would like to implement a mail notification system



Notification.cs



public abstract class Notification

private IEmailSender emailSender;

public string To get;

public virtual string Subject get;

public virtual string Template get;

public virtual object Model get;

public Notification(IEmailSender emailSender, string to, object model)

this.emailSender = emailSender;
this.To = to;
this.Model = model;


public virtual async Task SendAsync()

var engine = new RazorLightEngineBuilder()
.UseFilesystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();

string message = await engine.CompileRenderAsync(this.Template, this.Model);

await emailSender.SendEmailAsync(To, Subject, message);




RegisterConfirmationNotification.cs



public class RegisterConfirmationNotification : Notification

public RegisterConfirmationNotification(IEmailSender emailSender, string to, object model)
: base(emailSender, to, model)




public override string Subject => "Account Confirmation";

public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



AccountController.cs



var notification = new RegisterConfirmationNotification (emailSender, model.Email, new RegisterConfirmationViewModel FirstName = "John" );
await notification.SendAsync();


My problem is that I have the impression to mix a lot of things that should not be mixed.
My class is responsible for compiling the Razor template but also sending the mail.



How could we separate things?







share|improve this question





















  • Is this an ordinary program or maybe an asp.net-core web-service?
    – t3chb0t
    Apr 8 at 9:05










  • asp.net-core mvc with asp.net-core Identity 2.0
    – Qwerty
    Apr 8 at 9:07






  • 1




    In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
    – t3chb0t
    Apr 8 at 9:11










  • The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
    – Qwerty
    Apr 8 at 9:17
















up vote
3
down vote

favorite












I would like to implement a mail notification system



Notification.cs



public abstract class Notification

private IEmailSender emailSender;

public string To get;

public virtual string Subject get;

public virtual string Template get;

public virtual object Model get;

public Notification(IEmailSender emailSender, string to, object model)

this.emailSender = emailSender;
this.To = to;
this.Model = model;


public virtual async Task SendAsync()

var engine = new RazorLightEngineBuilder()
.UseFilesystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();

string message = await engine.CompileRenderAsync(this.Template, this.Model);

await emailSender.SendEmailAsync(To, Subject, message);




RegisterConfirmationNotification.cs



public class RegisterConfirmationNotification : Notification

public RegisterConfirmationNotification(IEmailSender emailSender, string to, object model)
: base(emailSender, to, model)




public override string Subject => "Account Confirmation";

public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



AccountController.cs



var notification = new RegisterConfirmationNotification (emailSender, model.Email, new RegisterConfirmationViewModel FirstName = "John" );
await notification.SendAsync();


My problem is that I have the impression to mix a lot of things that should not be mixed.
My class is responsible for compiling the Razor template but also sending the mail.



How could we separate things?







share|improve this question





















  • Is this an ordinary program or maybe an asp.net-core web-service?
    – t3chb0t
    Apr 8 at 9:05










  • asp.net-core mvc with asp.net-core Identity 2.0
    – Qwerty
    Apr 8 at 9:07






  • 1




    In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
    – t3chb0t
    Apr 8 at 9:11










  • The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
    – Qwerty
    Apr 8 at 9:17












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I would like to implement a mail notification system



Notification.cs



public abstract class Notification

private IEmailSender emailSender;

public string To get;

public virtual string Subject get;

public virtual string Template get;

public virtual object Model get;

public Notification(IEmailSender emailSender, string to, object model)

this.emailSender = emailSender;
this.To = to;
this.Model = model;


public virtual async Task SendAsync()

var engine = new RazorLightEngineBuilder()
.UseFilesystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();

string message = await engine.CompileRenderAsync(this.Template, this.Model);

await emailSender.SendEmailAsync(To, Subject, message);




RegisterConfirmationNotification.cs



public class RegisterConfirmationNotification : Notification

public RegisterConfirmationNotification(IEmailSender emailSender, string to, object model)
: base(emailSender, to, model)




public override string Subject => "Account Confirmation";

public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



AccountController.cs



var notification = new RegisterConfirmationNotification (emailSender, model.Email, new RegisterConfirmationViewModel FirstName = "John" );
await notification.SendAsync();


My problem is that I have the impression to mix a lot of things that should not be mixed.
My class is responsible for compiling the Razor template but also sending the mail.



How could we separate things?







share|improve this question













I would like to implement a mail notification system



Notification.cs



public abstract class Notification

private IEmailSender emailSender;

public string To get;

public virtual string Subject get;

public virtual string Template get;

public virtual object Model get;

public Notification(IEmailSender emailSender, string to, object model)

this.emailSender = emailSender;
this.To = to;
this.Model = model;


public virtual async Task SendAsync()

var engine = new RazorLightEngineBuilder()
.UseFilesystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();

string message = await engine.CompileRenderAsync(this.Template, this.Model);

await emailSender.SendEmailAsync(To, Subject, message);




RegisterConfirmationNotification.cs



public class RegisterConfirmationNotification : Notification

public RegisterConfirmationNotification(IEmailSender emailSender, string to, object model)
: base(emailSender, to, model)




public override string Subject => "Account Confirmation";

public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



AccountController.cs



var notification = new RegisterConfirmationNotification (emailSender, model.Email, new RegisterConfirmationViewModel FirstName = "John" );
await notification.SendAsync();


My problem is that I have the impression to mix a lot of things that should not be mixed.
My class is responsible for compiling the Razor template but also sending the mail.



How could we separate things?









share|improve this question












share|improve this question




share|improve this question








edited Apr 19 at 6:30
























asked Apr 8 at 9:03









Qwerty

236




236











  • Is this an ordinary program or maybe an asp.net-core web-service?
    – t3chb0t
    Apr 8 at 9:05










  • asp.net-core mvc with asp.net-core Identity 2.0
    – Qwerty
    Apr 8 at 9:07






  • 1




    In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
    – t3chb0t
    Apr 8 at 9:11










  • The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
    – Qwerty
    Apr 8 at 9:17
















  • Is this an ordinary program or maybe an asp.net-core web-service?
    – t3chb0t
    Apr 8 at 9:05










  • asp.net-core mvc with asp.net-core Identity 2.0
    – Qwerty
    Apr 8 at 9:07






  • 1




    In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
    – t3chb0t
    Apr 8 at 9:11










  • The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
    – Qwerty
    Apr 8 at 9:17















Is this an ordinary program or maybe an asp.net-core web-service?
– t3chb0t
Apr 8 at 9:05




Is this an ordinary program or maybe an asp.net-core web-service?
– t3chb0t
Apr 8 at 9:05












asp.net-core mvc with asp.net-core Identity 2.0
– Qwerty
Apr 8 at 9:07




asp.net-core mvc with asp.net-core Identity 2.0
– Qwerty
Apr 8 at 9:07




1




1




In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
– t3chb0t
Apr 8 at 9:11




In case you are not aware of that... you don't need any external packages for that. All you need is to implement a custom middleware that intercepts the view returned as a response that you can send via email. Maybe my question that solves the same thing helps you Middleware for sending PartialViews via email. Your controller would just return a PartialView instead of a full one, e.g. TestController.cs
– t3chb0t
Apr 8 at 9:11












The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
– Qwerty
Apr 8 at 9:17




The notification is sent in the Register method in AccountController. There are operations that are performed before and after in this method
– Qwerty
Apr 8 at 9:17










1 Answer
1






active

oldest

votes

















up vote
7
down vote



accepted










As you have already suspected, your code is trying to do too much. Consider separating functionality out into their own distinct concerns. (SRP/SoC -Single Responsibility Principle / Separation of Concerns)



Your abstract Notification acts more like a base model and should be refactor to reflect that



public abstract class Notification 

public string To get;

public abstract string Subject get;

public abstract string Template get;

public virtual object Model get;

public Notification(string to, object model)
this.To = to;
this.Model = model;




The class is now responsible solely for storing the data to be sent.



This would mean that the RegisterConfirmationNotification class definition would now look like



public class RegisterConfirmationNotification : Notification 
public RegisterConfirmationNotification(string to, object model)
: base(to, model)



public override string Subject => "Account Confirmation";

public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



SendAsync should be refactored into its own service abstraction and implementation and also follow explicit dependency principle by accepting a Notification argument directly



public interface INotificationService 
Task SendAsync(Notification notification);



The implementation can be as simple as the following



public class NotoficationService : INotificationService 
private readonly IEmailSender emailSender;

public NotoficationService(IEmailSender emailSender)
this.emailSender = emailSender;


public async Task SendAsync(Notification notification)
var engine = new RazorLightEngineBuilder()
.UseFilesystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();

string message = await engine.CompileRenderAsync(notification.Template, notification.Model);

await emailSender.SendEmailAsync(notification.To, notification.Subject, message);




Even the compilation of the razor template can be extracted out into its own service in order for this code to be more SOLID. I'll leave that choice up to you to implement.



Finally, the AccountController would now explicitly depend on the INotificationService in order to be able to send notifications. The Notification derived model can be then passed to the service and the message sent.



public class AccountController : Controller 
private readonly INotificationService notificationService;

public AccountController(INotificationService notificationService)
this.notificationService = notificationService;


//...

[HttpPost]
public async Task<IActionResult> Register([FromBody]MyModel model)
//...

var notificationModel = new RegisterConfirmationViewModel FirstName = "Jacques" ;
var notification = new RegisterConfirmationNotification (model.Email, notificationModel);
await notificationService.SendAsync(notification);

//...

return View();








share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191523%2fnotification-system%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    7
    down vote



    accepted










    As you have already suspected, your code is trying to do too much. Consider separating functionality out into their own distinct concerns. (SRP/SoC -Single Responsibility Principle / Separation of Concerns)



    Your abstract Notification acts more like a base model and should be refactor to reflect that



    public abstract class Notification 

    public string To get;

    public abstract string Subject get;

    public abstract string Template get;

    public virtual object Model get;

    public Notification(string to, object model)
    this.To = to;
    this.Model = model;




    The class is now responsible solely for storing the data to be sent.



    This would mean that the RegisterConfirmationNotification class definition would now look like



    public class RegisterConfirmationNotification : Notification 
    public RegisterConfirmationNotification(string to, object model)
    : base(to, model)



    public override string Subject => "Account Confirmation";

    public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



    SendAsync should be refactored into its own service abstraction and implementation and also follow explicit dependency principle by accepting a Notification argument directly



    public interface INotificationService 
    Task SendAsync(Notification notification);



    The implementation can be as simple as the following



    public class NotoficationService : INotificationService 
    private readonly IEmailSender emailSender;

    public NotoficationService(IEmailSender emailSender)
    this.emailSender = emailSender;


    public async Task SendAsync(Notification notification)
    var engine = new RazorLightEngineBuilder()
    .UseFilesystemProject(Directory.GetCurrentDirectory())
    .UseMemoryCachingProvider()
    .Build();

    string message = await engine.CompileRenderAsync(notification.Template, notification.Model);

    await emailSender.SendEmailAsync(notification.To, notification.Subject, message);




    Even the compilation of the razor template can be extracted out into its own service in order for this code to be more SOLID. I'll leave that choice up to you to implement.



    Finally, the AccountController would now explicitly depend on the INotificationService in order to be able to send notifications. The Notification derived model can be then passed to the service and the message sent.



    public class AccountController : Controller 
    private readonly INotificationService notificationService;

    public AccountController(INotificationService notificationService)
    this.notificationService = notificationService;


    //...

    [HttpPost]
    public async Task<IActionResult> Register([FromBody]MyModel model)
    //...

    var notificationModel = new RegisterConfirmationViewModel FirstName = "Jacques" ;
    var notification = new RegisterConfirmationNotification (model.Email, notificationModel);
    await notificationService.SendAsync(notification);

    //...

    return View();








    share|improve this answer

























      up vote
      7
      down vote



      accepted










      As you have already suspected, your code is trying to do too much. Consider separating functionality out into their own distinct concerns. (SRP/SoC -Single Responsibility Principle / Separation of Concerns)



      Your abstract Notification acts more like a base model and should be refactor to reflect that



      public abstract class Notification 

      public string To get;

      public abstract string Subject get;

      public abstract string Template get;

      public virtual object Model get;

      public Notification(string to, object model)
      this.To = to;
      this.Model = model;




      The class is now responsible solely for storing the data to be sent.



      This would mean that the RegisterConfirmationNotification class definition would now look like



      public class RegisterConfirmationNotification : Notification 
      public RegisterConfirmationNotification(string to, object model)
      : base(to, model)



      public override string Subject => "Account Confirmation";

      public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



      SendAsync should be refactored into its own service abstraction and implementation and also follow explicit dependency principle by accepting a Notification argument directly



      public interface INotificationService 
      Task SendAsync(Notification notification);



      The implementation can be as simple as the following



      public class NotoficationService : INotificationService 
      private readonly IEmailSender emailSender;

      public NotoficationService(IEmailSender emailSender)
      this.emailSender = emailSender;


      public async Task SendAsync(Notification notification)
      var engine = new RazorLightEngineBuilder()
      .UseFilesystemProject(Directory.GetCurrentDirectory())
      .UseMemoryCachingProvider()
      .Build();

      string message = await engine.CompileRenderAsync(notification.Template, notification.Model);

      await emailSender.SendEmailAsync(notification.To, notification.Subject, message);




      Even the compilation of the razor template can be extracted out into its own service in order for this code to be more SOLID. I'll leave that choice up to you to implement.



      Finally, the AccountController would now explicitly depend on the INotificationService in order to be able to send notifications. The Notification derived model can be then passed to the service and the message sent.



      public class AccountController : Controller 
      private readonly INotificationService notificationService;

      public AccountController(INotificationService notificationService)
      this.notificationService = notificationService;


      //...

      [HttpPost]
      public async Task<IActionResult> Register([FromBody]MyModel model)
      //...

      var notificationModel = new RegisterConfirmationViewModel FirstName = "Jacques" ;
      var notification = new RegisterConfirmationNotification (model.Email, notificationModel);
      await notificationService.SendAsync(notification);

      //...

      return View();








      share|improve this answer























        up vote
        7
        down vote



        accepted







        up vote
        7
        down vote



        accepted






        As you have already suspected, your code is trying to do too much. Consider separating functionality out into their own distinct concerns. (SRP/SoC -Single Responsibility Principle / Separation of Concerns)



        Your abstract Notification acts more like a base model and should be refactor to reflect that



        public abstract class Notification 

        public string To get;

        public abstract string Subject get;

        public abstract string Template get;

        public virtual object Model get;

        public Notification(string to, object model)
        this.To = to;
        this.Model = model;




        The class is now responsible solely for storing the data to be sent.



        This would mean that the RegisterConfirmationNotification class definition would now look like



        public class RegisterConfirmationNotification : Notification 
        public RegisterConfirmationNotification(string to, object model)
        : base(to, model)



        public override string Subject => "Account Confirmation";

        public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



        SendAsync should be refactored into its own service abstraction and implementation and also follow explicit dependency principle by accepting a Notification argument directly



        public interface INotificationService 
        Task SendAsync(Notification notification);



        The implementation can be as simple as the following



        public class NotoficationService : INotificationService 
        private readonly IEmailSender emailSender;

        public NotoficationService(IEmailSender emailSender)
        this.emailSender = emailSender;


        public async Task SendAsync(Notification notification)
        var engine = new RazorLightEngineBuilder()
        .UseFilesystemProject(Directory.GetCurrentDirectory())
        .UseMemoryCachingProvider()
        .Build();

        string message = await engine.CompileRenderAsync(notification.Template, notification.Model);

        await emailSender.SendEmailAsync(notification.To, notification.Subject, message);




        Even the compilation of the razor template can be extracted out into its own service in order for this code to be more SOLID. I'll leave that choice up to you to implement.



        Finally, the AccountController would now explicitly depend on the INotificationService in order to be able to send notifications. The Notification derived model can be then passed to the service and the message sent.



        public class AccountController : Controller 
        private readonly INotificationService notificationService;

        public AccountController(INotificationService notificationService)
        this.notificationService = notificationService;


        //...

        [HttpPost]
        public async Task<IActionResult> Register([FromBody]MyModel model)
        //...

        var notificationModel = new RegisterConfirmationViewModel FirstName = "Jacques" ;
        var notification = new RegisterConfirmationNotification (model.Email, notificationModel);
        await notificationService.SendAsync(notification);

        //...

        return View();








        share|improve this answer













        As you have already suspected, your code is trying to do too much. Consider separating functionality out into their own distinct concerns. (SRP/SoC -Single Responsibility Principle / Separation of Concerns)



        Your abstract Notification acts more like a base model and should be refactor to reflect that



        public abstract class Notification 

        public string To get;

        public abstract string Subject get;

        public abstract string Template get;

        public virtual object Model get;

        public Notification(string to, object model)
        this.To = to;
        this.Model = model;




        The class is now responsible solely for storing the data to be sent.



        This would mean that the RegisterConfirmationNotification class definition would now look like



        public class RegisterConfirmationNotification : Notification 
        public RegisterConfirmationNotification(string to, object model)
        : base(to, model)



        public override string Subject => "Account Confirmation";

        public override string Template => "Views/EmailTemplates/RegisterConfirmation.cshtml";



        SendAsync should be refactored into its own service abstraction and implementation and also follow explicit dependency principle by accepting a Notification argument directly



        public interface INotificationService 
        Task SendAsync(Notification notification);



        The implementation can be as simple as the following



        public class NotoficationService : INotificationService 
        private readonly IEmailSender emailSender;

        public NotoficationService(IEmailSender emailSender)
        this.emailSender = emailSender;


        public async Task SendAsync(Notification notification)
        var engine = new RazorLightEngineBuilder()
        .UseFilesystemProject(Directory.GetCurrentDirectory())
        .UseMemoryCachingProvider()
        .Build();

        string message = await engine.CompileRenderAsync(notification.Template, notification.Model);

        await emailSender.SendEmailAsync(notification.To, notification.Subject, message);




        Even the compilation of the razor template can be extracted out into its own service in order for this code to be more SOLID. I'll leave that choice up to you to implement.



        Finally, the AccountController would now explicitly depend on the INotificationService in order to be able to send notifications. The Notification derived model can be then passed to the service and the message sent.



        public class AccountController : Controller 
        private readonly INotificationService notificationService;

        public AccountController(INotificationService notificationService)
        this.notificationService = notificationService;


        //...

        [HttpPost]
        public async Task<IActionResult> Register([FromBody]MyModel model)
        //...

        var notificationModel = new RegisterConfirmationViewModel FirstName = "Jacques" ;
        var notification = new RegisterConfirmationNotification (model.Email, notificationModel);
        await notificationService.SendAsync(notification);

        //...

        return View();









        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Apr 8 at 16:40









        Nkosi

        1,868619




        1,868619






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191523%2fnotification-system%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Python Lists

            Aion

            JavaScript Array Iteration Methods