smsohan / MvcMailer

A Mailer for ASP.Net MVC that forms the Email Body using MVC Views (Razor etc.) following Ruby on Rails ActionMailer style
MIT License
584 stars 178 forks source link

Why is MvcMailer give intermittent NullReferenceException Errors? #35

Open gabrielfuller opened 12 years ago

gabrielfuller commented 12 years ago

On StackOverflow as well: http://goo.gl/sZXoS

I am using MvcMailer via Nuget to try and send Emails using the MVC Views and Models system. I am also using Sharp Architecture so I have my Domain Objects, Infrustructure, Presentation, Tests and Tasks in different projects within the solution.

I created my IClientMailer interface and ClientMailer class in the Presentation project and am able to create the mail message and call EmailBody(ViewName, EmailBoilerplate) method on the MvcMailer's MailerBase class, but the odd thing is that sometime it works and sometimes it gives me the below error. I do not understand why I am only getting this error some of the time and I cannot seem to find how to debug the project more to find out more information.

Anyone have any thoughts on how to get it to work correctly 100% of the time.

[NullReferenceException: Object reference not set to an instance of an object.] Mvc.Mailer.StringResult.ExecuteResult(ControllerContext context, String mailerName) +142 Mvc.Mailer.MailerBase.EmailBody(String viewName, String masterName) +181 EasyOptions.Web.Mvc.Code.ClientMailer.FirstPaymentCoupon(String[] emailAddresses, FirstPaymentCouponEmailViewModel model) in C:\Users\Gabriel\Documents\Repositories\EasyOptions\Solutions\EasyOptions.Web.Mvc\Code\ClientMailer.cs:53 EasyOptions.Web.Mvc.Controllers.FirstPaymentCouponController.SendEmail(Int64 loanId, FirstPaymentCouponViewModel model) in C:\Users\Gabriel\Documents\Repositories\EasyOptions\Solutions\EasyOptions.Web.Mvc\Controllers\FirstPaymentCouponController.cs:64 lambdamethod(Closure , ControllerBase , Object[] ) +166 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +208 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +27 System.Web.Mvc.<>cDisplayClass15.b12() +55 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>cDisplayClass17.b14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary2 parameters) +191 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343 System.Web.Mvc.Controller.ExecuteCore() +116 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10 System.Web.Mvc.<>cDisplayClassb.b5() +37 System.Web.Mvc.Async.<>cDisplayClass1.b0() +21 System.Web.Mvc.Async.<>cDisplayClass8`1.b7(IAsyncResult ) +12 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62 System.Web.Mvc.<>cDisplayClasse.bd() +50 System.Web.Mvc.SecurityUtil.b__0(Action f) +7 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8963149 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

smsohan commented 12 years ago

Just from this description, it will be very hard for me to realize why it's doing so. But you can get the source code of MvcMailer from

github and try debugging it to catch the problem.

Sohan http://smsohan.com skype:smsohan | gtalk:sohan39 | cell: 403-714-2673

On Thu, Jan 5, 2012 at 2:23 PM, Gabriel Fuller reply@reply.github.com wrote:

On StackOverflow as well: http://goo.gl/sZXoS

I am using MvcMailer via Nuget to try and send Emails using the MVC Views and Models system. I am also using Sharp Architecture so I have my Domain Objects, Infrustructure, Presentation, Tests and Tasks in different projects within the solution.

I created my IClientMailer interface and ClientMailer class in the Presentation project and am able to create the mail message and call EmailBody(ViewName, EmailBoilerplate) method on the MvcMailer's MailerBase class, but the odd thing is that sometime it works and sometimes it gives me the below error. I do not understand why I am only getting this error some of the time and I cannot seem to find how to debug the project more to find out more information.

Anyone have any thoughts on how to get it to work correctly 100% of the time.

[NullReferenceException: Object reference not set to an instance of an object.]   Mvc.Mailer.StringResult.ExecuteResult(ControllerContext context, String mailerName) +142   Mvc.Mailer.MailerBase.EmailBody(String viewName, String masterName) +181   EasyOptions.Web.Mvc.Code.ClientMailer.FirstPaymentCoupon(String[] emailAddresses, FirstPaymentCouponEmailViewModel model) in C:\Users\Gabriel\Documents\Repositories\EasyOptions\Solutions\EasyOptions.Web.Mvc\Code\ClientMailer.cs:53   EasyOptions.Web.Mvc.Controllers.FirstPaymentCouponController.SendEmail(Int64 loanId, FirstPaymentCouponViewModel model) in C:\Users\Gabriel\Documents\Repositories\EasyOptions\Solutions\EasyOptions.Web.Mvc\Controllers\FirstPaymentCouponController.cs:64   lambdamethod(Closure , ControllerBase , Object[] ) +166   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +208   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +27   System.Web.Mvc.<>cDisplayClass15.b12() +55   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263   System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263   System.Web.Mvc.<>cDisplayClass17.b14() +19   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary2 parameters) +191   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343   System.Web.Mvc.Controller.ExecuteCore() +116   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10   System.Web.Mvc.<>cDisplayClassb.b5() +37   System.Web.Mvc.Async.<>cDisplayClass1.b0() +21   System.Web.Mvc.Async.<>cDisplayClass8`1.b7(IAsyncResult ) +12   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62   System.Web.Mvc.<>cDisplayClasse.bd() +50   System.Web.Mvc.SecurityUtil.b__0(Action f) +7   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8963149   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184


Reply to this email directly or view it on GitHub: https://github.com/smsohan/MvcMailer/issues/35

tocklime commented 12 years ago

I got the exact same stack trace. Having got the source code, and stepped through, it turned out it was a nullreferenceexception in my view, but the stack trace had been replaced at some point during the exception making its way to the browser screen. (possibly due to the try..finally block in ExecuteResult(ControllerContext context, String mailerName) ).

I think the real problem here is that the stack traces are getting mucked up.

abrahamD commented 12 years ago

I seem to have the same problem. I also added the source to my solution to debug and I end up at the same spot in ExecuteResult(ControllerContext context). It appears to be incapable to render the view after the first request on a fresh build. For instance, if I stop the virtual servers, rebuild and debug it will work the first time around. Yet all the successive attempts fail.

abrahamD commented 12 years ago

Actually, never mind. I got the problem fixed. I turns out the MvcMailer isn't compatible with the Castle Windsor project. I tried to get the MvcMailer controller to get instantiated automatically in my controller and it wasn't doing something right apparently.

walkindude commented 11 years ago

@abrahamD I see you came to the conclusion that MvcMailer isn't compatible with Castle Windsor. Can I ask you how you got around this issue?

Thanks in advance.

abrahamD commented 11 years ago

@walkindude It's fairly simple. All you have to do is instantiate your MailService (class that extends MailerBase) manually in your controller's constructor.

walkindude commented 11 years ago

@abrahamD thank you very much for the quick reply. That's an approach I considered, but won't that make the controller hard to test? If I instantiate the mailer directly inside the constructor, I'm not going to be able to mock it in my unit tests. Or maybe I'm missing something?

abrahamD commented 11 years ago

@walkindude Well, what I do to get around that is reassign my controller's Mailer manually in my test's setup as such:

Target = new Controller(...) { MailService = MailServiceMock.Object };

markearthware commented 11 years ago

I managed to get mvcmailer working together with castle windsor.

Install component like this: container.Register(Component.For().ImplementedBy().Named("MailerService").LifeStyle.Transient);

mvcmailer uses an mvc controller under the covers so the transient lifestyle is important as it keeps the http context avaliable

Eonasdan commented 11 years ago

I still randomly get this issue.

I can send the same message over and over and sometimes it works and other times it doesn't

smsohan commented 11 years ago

Is it going to spam? Sometimes the email servers will block repeated mails with similar content.


Sent from my iPhone Sohan SM

On 2013-01-09, at 7:46 AM, Eonasdan notifications@github.com wrote:

I still randomly get this issue.

I can send the same message over and over and sometimes it works and other times it doesn't

— Reply to this email directly or view it on GitHubhttps://github.com/smsohan/MvcMailer/issues/35#issuecomment-12047075.

Eonasdan commented 11 years ago

spam? No, I'm getting

[NullReferenceException: Object reference not set to an instance of an object.]

I'm testing this on a local dev machine currently and I'm using an local basic smtp server

smsohan commented 11 years ago

You'd need to find out what object/method it's invoking when this error shows up. It should be deterministic, unless there's something clever going on with how the instances are created. MvcMailer source code is available, so you can debug it if you want.

Sohan http://smsohan.com skype:smsohan | gtalk:sohan39 | cell: 403-714-2673

On Wed, Jan 9, 2013 at 9:37 AM, Eonasdan notifications@github.com wrote:

spam? No, I'm getting

[NullReferenceException: Object reference not set to an instance of an object.]

I'm testing this on a local dev machine currently and I'm using an local basic smtp server

— Reply to this email directly or view it on GitHubhttps://github.com/smsohan/MvcMailer/issues/35#issuecomment-12052804.

Eonasdan commented 11 years ago

when trying to step through this

    ViewData.Model = entity;
var mailer = Populate(x =>
                {
                    x.Subject = "blah";
                    x.ViewName = "foo";
                    x.To.Add("");
                });

it works, but if just let it run I get the nullref

walkindude commented 11 years ago

@Eonasdan are you getting the exact same stacktrace as the one posted at the beginning? Have you tried debugging?

As @kobeyu pointed out, the stacktrace gets munged, so your best bet is adding MvcMailer's source to your solution and stepping through.

Also, if you do it, please try commenting out lines 30, 32 and 35 of StringResult.cs and seeing if the stacktrace then points to the actual source of the exception.

This is a weird one, though. The fact that it works every time you step through the code you posted would lead one to believe it's a timing issue, but I don't think it's the case here.

Eonasdan commented 11 years ago

I now get

System.ArgumentException occurred
  HResult=-2147024809
  Message=Value does not fall within the expected range.
  Source=mscorlib
  StackTrace:
       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
       at System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)
       at System.Web.Hosting.IIS7WorkerRequest.GetServerVariable(String name)
       at System.Web.Hosting.IIS7WorkerRequest.GetRemoteAddress()
       at System.Web.HttpWorkerRequest.IsLocal()
       at System.Web.HttpRequestWrapper.get_IsLocal()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
       at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
       at System.Web.WebPages.StartPage.RunPage()
       at System.Web.WebPages.StartPage.ExecutePageHierarchy()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
       at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
       at Mvc.Mailer.StringResult.ExecuteResult(ControllerContext context) in StringResult.cs:line 55
  InnerException: 
Eonasdan commented 11 years ago

shameless bump.

any idea's @walkindude or @smsohan?

walkindude commented 11 years ago

@Eonasdan I don't have a clue, sorry. The problem is somewhere else than MvcMailer and is possibly related to some object having a longer lifetime than it is supposed to. Maybe this helps?

It's hard to be much more specific. I've been able to drill down to IIS7WorkerRequest, where GetServerVariableInternal() calls MgdGetServerVariableW(), which is a native method defined in one of IIS' DLLs.

That—I think—is the call that fails.

This is the method's declaration

[DllImport(_IIS_NATIVE_DLL, CharSet=CharSet.Unicode)]
internal static extern int MgdGetServerVariableW(
        IntPtr           pHandler,
        string           pszVarName,
        out IntPtr       ppBuffer,
        out int          pcchBufferSize);

and since an HRESULT of -2147024809 is also known as E_INVALIDARGS (and the exception message confirms that, of course), somehow someone is handing MgdGetServerVariableW() a bogus argument. Its return value is specifically checked, by a method called ThrowIfFailedHr.

Figuring out who, how and why is left as an excercise for the reader ;)

I'm sorry I can't be more helpful. But hey, I think it has to do with some setting in your project.

smsohan commented 11 years ago

I've no clue about it. It would help if you could share a project where I can reproduce it.

Sohan http://smsohan.com skype:smsohan | gtalk:sohan39 | cell: 403-714-2673

On Mon, Jan 14, 2013 at 4:11 PM, Stefano Mioli notifications@github.comwrote:

@Eonasdan https://github.com/Eonasdan I don't have a clue, sorry. The problem is somewhere else than MvcMailer and is possibly related to some object having a longer lifetime than it is supposed to. Maybe thishttp://stackoverflow.com/questions/9179217/httprequestbase-userhostaddress-throwing-errorhelps?

It's hard to be much more specific. I've been able to drill down to IIS7WorkerRequest, where GetServerVariableInternal() calls MgdGetServerVariableW(), which is a native method defined in one of IIS' DLLs.

That—I think—is the call that fails.

This is the method's declaration

[DllImport(_IIS_NATIVE_DLL, CharSet=CharSet.Unicode)] internal static extern int MgdGetServerVariableW( IntPtr pHandler, string pszVarName, out IntPtr ppBuffer, out int pcchBufferSize);

and since an HRESULT of -2147024809 is also known as E_INVALIDARGS (and the exception message confirms that, of course), somehow someone is handing MgdGetServerVariableW() a bogus argument. Its return value is specifically checked, by a method called ThrowIfFailedHr.

Figuring out who, how and why is left as an excercise for the reader ;)

I'm sorry I can't be more helpful. But hey, I think it has to do with some setting in your project.

— Reply to this email directly or view it on GitHubhttps://github.com/smsohan/MvcMailer/issues/35#issuecomment-12245244.

Eonasdan commented 11 years ago

changing the MasterName from _Layout to /UserMailer/_Layout caused the error to stop occurring but now the body of the email is empty

public UserMailer()
    {
        MasterName = "/UserMailer/_Layout";
    }
Eonasdan commented 11 years ago

for kicks I put the MasterName back the way it was and once again the email bodies have text when it actually sends correctly. Some times it sends, some times it doesn't.

I setup each mailer to bcc another address to make sure it is at least going out and I get mixed results. Sometimes the email is at the bcc and sometimes it's at the intended email

smsohan commented 11 years ago

It's really hard for me to get a clear picture of this without having a code that reproduces it. Please try and share a bare-bone example project.

Sohan http://smsohan.com skype:smsohan | gtalk:sohan39 | cell: 403-714-2673

On Wed, Jan 16, 2013 at 9:05 AM, Eonasdan notifications@github.com wrote:

for kicks I put the MasterName back the way it was and once again the email bodies have text when it actually sends correctly. Some times it sends, some times it doesn't.

I setup each mailer to bcc another address to make sure it is at least going out and I get mixed results. Sometimes the email is at the bcc and sometimes it's at the intended email

— Reply to this email directly or view it on GitHubhttps://github.com/smsohan/MvcMailer/issues/35#issuecomment-12325307.

smsohan commented 11 years ago

I'd need a way to reproduce it.

Sohan http://smsohan.com skype:smsohan | gtalk:sohan39 | cell: 403-714-2673

On Wed, Jan 16, 2013 at 9:55 AM, Eonasdan notifications@github.com wrote:

ok I created a test project http://goo.gl/i3zm6 which works just fine on my local box

— Reply to this email directly or view it on GitHubhttps://github.com/smsohan/MvcMailer/issues/35#issuecomment-12328105.