Search code examples
asp.net-mvc-3orchardcmsmvcmailer

Trying to call code in my controller but getting Null Reference error


Don't want to over-complicate the issue, but I think I need to post all the code that's hooked into this error.

Using MvcMailer and introduced a separate Send mechanism (for use with Orchard CMS' own EMail).

The MvcMailer Code:

1) AskUsMailer.cs:

public class AskUsMailer : MailerBase, IAskUsMailer
{
    public AskUsMailer()
        : base()
    {
        //MasterName = "_Layout";
    }

    public virtual MvcMailMessage EMailAskUs(AskUsViewModel model)
    {
        var mailMessage = new MvcMailMessage { Subject = "Ask Us" };
        ViewData.Model = model;
        this.PopulateBody(mailMessage, viewName: "EMailAskUs");
        return mailMessage;
    }
}

2) IAskUsMailer.cs:

public interface IAskUsMailer : IDependency
{
    MvcMailMessage EMailAskUs(AskUsViewModel model);
}

3) AskUsController.cs: (GETTING NULL REFERENCE ERROR BELOW)

[Themed]
    public ActionResult Submitted()
    {
        //This is the new call (see new code below):
        //Note: Debugging steps through eMailMessagingService,
        //then shows the null reference error when continuing to
        //SendAskUs
        eMailMessagingService.SendAskUs(askUsData);
        //Below is normal MvcMailer call:
        //AskUsMailer.EMailAskUs(askUsData).Send();
        return View(askUsData);
    }

Note: askUsData is defined in a separate block in the controller:

    private AskUsViewModel askUsData;
    protected override void OnActionExecuting(ActionExecutingContext 
        filterContext)
    {
        var serialized = Request.Form["askUsData"];
        if (serialized != null) //Form was posted containing serialized data
        {
            askUsData = (AskUsViewModel)new MvcSerializer().
                Deserialize(serialized, SerializationMode.Signed);
            TryUpdateModel(askUsData);
        }
        else
            askUsData = (AskUsViewModel)TempData["askUsData"] ?? 
                new AskUsViewModel();
        TempData.Keep();
    }
    protected override void OnResultExecuted(ResultExecutedContext 
        filterContext)
    {
        if (filterContext.Result is RedirectToRouteResult)
            TempData["askUsData"] = askUsData;
    }

I did not know how to get my EMailMessagingService.cs (see below) call into the controller, so in a separate block in the controller I did this:

    private IEMailMessagingService eMailMessagingService;

    public AskUsController(IEMailMessagingService eMailMessagingService)
    {
        this.eMailMessagingService = eMailMessagingService;
    }

I think this is part of my problem.

Now, the new code trying to hook into Orchard's EMail:

1) EMailMessagingServices.cs:

public class EMailMessagingService : IMessageManager
{
    private IAskUsMailer askUsMailer;
    private IOrchardServices orchardServices;
    public EMailMessagingService(IAskUsMailer askUsMailer, 
        IOrchardServices orchardServices)
    {
        this.orchardServices = orchardServices;
        this.askUsMailer = askUsMailer;
        this.Logger = NullLogger.Instance;
    }

    public ILogger Logger { get; set; }

    public void SendAskUs(AskUsViewModel model)
    {
        var messageAskUs = this.askUsMailer.EMailAskUs(model);
        messageAskUs.To.Add("email@email.com");
        //Don't need the following (setting up e-mails to send a copy anyway)
        //messageAskUs.Bcc.Add(AdminEmail);
        //messageAskUs.Subject = "blabla";

        Send(messageAskUs);
    }
    ....
}

The EMailMessagingService.cs also contains the Send method:

    private void Send(MailMessage messageAskUs)
    {
        var smtpSettings = orchardServices.WorkContext.
            CurrentSite.As<SmtpSettingsPart>();

        // can't process emails if the Smtp settings have not yet been set
        if (smtpSettings == null || !smtpSettings.IsValid())
        {
            Logger.Error("The SMTP Settings have not been set up.");
            return;
        }

        using (var smtpClient = new SmtpClient(smtpSettings.Host, 
            smtpSettings.Port))
        {
            smtpClient.UseDefaultCredentials = 
                !smtpSettings.RequireCredentials;
            if (!smtpClient.UseDefaultCredentials &&
                !String.IsNullOrWhiteSpace(smtpSettings.UserName))
            {
                smtpClient.Credentials = new NetworkCredential
                    (smtpSettings.UserName, smtpSettings.Password);
            }

            if (messageAskUs.To.Count == 0)
            {
                Logger.Error("Recipient is missing an email address");
                return;
            }

            smtpClient.EnableSsl = smtpSettings.EnableSsl;
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;

            messageAskUs.From = new MailAddress(smtpSettings.Address);
            messageAskUs.IsBodyHtml = messageAskUs.Body != null &&
                messageAskUs.Body.Contains("<") && 
                messageAskUs.Body.Contains(">");

            try
            {
                smtpClient.Send(messageAskUs);
                Logger.Debug("Message sent to {0} with subject: {1}",
                   messageAskUs.To[0].Address, messageAskUs.Subject);
            }
            catch (Exception e)
            {
                Logger.Error(e, "An unexpected error while sending 
                    a message to {0} with subject: {1}", 
                    messageAskUs.To[0].Address, messageAskUs.Subject);
            }
        }
    }

Now, in EMailMessagingService.cs I was getting an error that things weren't being implemented, so I auto-generated the following (don't know if this is part of my error):

    public void Send(Orchard.ContentManagement.Records.ContentItemRecord recipient, string type, string service, System.Collections.Generic.Dictionary<string, string> properties = null)
    {
        throw new NotImplementedException();
    }

    public void Send(System.Collections.Generic.IEnumerable<Orchard.ContentManagement.Records.ContentItemRecord> recipients, string type, string service, System.Collections.Generic.Dictionary<string, string> properties = null)
    {
        throw new NotImplementedException();
    }

    public void Send(System.Collections.Generic.IEnumerable<string> recipientAddresses, string type, string service, System.Collections.Generic.Dictionary<string, string> properties = null)
    {
        throw new NotImplementedException();
    }

    public bool HasChannels()
    {
        throw new NotImplementedException();
    }

    public System.Collections.Generic.IEnumerable<string> GetAvailableChannelServices()
    {
        throw new NotImplementedException();
    }

2) IEMailMessagingServices.cs

public interface IEMailMessagingService
{
    MailMessage SendAskUs(AskUsViewModel model);
}

MvcMailer works fine without this addition (outside of Orchard), but I am trying to get everything working within Orchard.

I just cannot figure out what I am doing wrong. Any thoughts?

Sorry for excessive code.


Solution

  • IEmailMessaginService does not implement IDependency, so it can't be found by Orchard as a dependency. That's why it's null.