3

I need to send out emails from an asp.net MVC application and I am using MVC mailer to do the job. As long as there is an HTTPContext it works fine. Unfortunately, I also need to send out emails where there is no context.

The newer version of MVC Mailer has a virtual property for CurrentHttpContext and when I set that with a "fake" context it seems to work locally. As soon as it reaches the server it won't work any more and fails with the following stack trace

System.ArgumentNullException: Value cannot be null.
Parameter name: httpContext
  at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)
  at Glimpse.Core.Extensibility.GlimpseTimer.get_TimerMetadata()
  at Glimpse.Mvc3.Plumbing.GlimpseViewEngine.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache)
  at System.Web.Mvc.ViewEngineCollection.<>c__DisplayClassc.<FindView>b__a(IViewEngine e)
  at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths)
  at System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator, Func`2 locator)
  at Mvc.Mailer.MailerBase.ViewExists(String viewName, String masterName)
  at Mvc.Mailer.MailerBase.PopulateBody(MailMessage mailMessage, String viewName, String masterName, Dictionary`2 linkedResources)
  at Mvc.Mailer.MailerBase.Populate(Action`1 action)

I've done some research and it appears that the problem is that the ViewEngineCollection can't be found because of something it is looking for in the HTTPContext. The "fake" context I am returning is as simple as

  public static HttpContextBase GetHttpContext(string baseUrl)
  {
      if (HttpContext.Current == null)
     {
    Log.InfoFormat("Creating a fake HTTPContext using URL: {0}", baseUrl);
    var request = new HttpRequest("/", baseUrl, "");
    var response = new HttpResponse(new StringWriter());
    return new HttpContextWrapper(new HttpContext(request, response));
      }

   return new HttpContextWrapper(HttpContext.Current);
  }

Am I missing something from my "fake" context? How do I add it?

William Hurst
  • 2,231
  • 5
  • 33
  • 54
  • possible duplicate of [Send async e-mails](http://stackoverflow.com/questions/12201353/send-async-e-mails) – Dunc May 07 '15 at 13:16
  • @Dunc I was trying to send an email from a Windows service which doesn't have an HttpContext available to pass as a parameter, – William Hurst May 08 '15 at 06:10
  • good point, I ended up using RazorEngine directly instead (https://razorengine.codeplex.com) - two lines of code to render a template, but no scaffolding & you have to send the email yourself (still arguably easier than mocking a `HttpContext`) – Dunc May 08 '15 at 08:41
  • If you use Postal your faking will work. I am doing same using Postal with hangfire – Diin Jun 23 '16 at 15:14

1 Answers1

0

You'd want to mock or fake the HttpContextBase, and the request/response.

If you were using RhinoMocks, it could be done as follows:

var httpResponse = MockRepository.GenerateMock<HttpResponseBase>();
var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
// you may need to stub specific methods of request/response
var context = MockRepository.GenerateMock<HttpContextBase>();
            context.Stub(r => r.Request).Return(httpRequest);
            context.Stub(r => r.Response).Return(httpResponse);

Or you could fake if your inherit from the Base classes. The HttpContext you pass into the wrapper in your question will not work.

dove
  • 20,469
  • 14
  • 82
  • 108
  • The problem is that although I'm faking it, it still needs to be able to work with the helpers, etc. – William Hurst Dec 05 '12 at 15:49
  • looking closer, you're also going to have trouble trying to use System.Web.Mvc.ViewEngineCollection no mattter what the fake. – dove Dec 05 '12 at 15:51
  • That's exactly the issue I ran into. Any suggested ways around this? – William Hurst Dec 06 '12 at 06:19
  • Would this make a difference or am I heading down the wrong road completely: http://stackoverflow.com/questions/1228179/mocking-httpcontextbase-with-moq – William Hurst Dec 06 '12 at 06:52