Reputation: 21
How can we utilize HTTP Context while running the Background Worker Thread? Getting exception while using MVC mailer to send email by a background thread. Exception: Parameter cannot be NULL, HTTP Context.
Upvotes: 0
Views: 5175
Reputation: 119
When using async/await and HTTPContext together, always use ConfigureAwait(true) to allow to continue on the original context. For example, see below. You can call ConfigureAwait on await calls as well.
var task = new Task(() => book.Bindbook()).ConfigureAwait(true);
task.Start();
Upvotes: 2
Reputation: 31723
I suppose your method needs an HttpContext but is not executed withing an WebRequest.
HttpContext is not easy to mock but not impossible. Try assigning HttpContext current with this code
HttpContext.Current = HttpContextHelper.CreateHttpContext(
new HttpRequest("SomePage.asmx", "http://localhost/SomePage.asmx", ""),
new HttpResponse(new StringWriter())
);
HttpContext helper is a helper class based on this blog post http://www.necronet.org/archive/2010/07/28/unit-testing-code-that-uses-httpcontext-current-session.aspx
public class HttpContextHelper
{
public static HttpContext CreateHttpContext(HttpRequest httpRequest, HttpResponse httpResponse)
{
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 10, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer });
return httpContext;
}
}
However (and that's important): You're propably doing it wrong. BackgroundWorker is not intended to use within MVC but with Windows Forms. Try using the TPL instead.
public ActionResult SendMail()
{
Task.Factory.StartNew(() => MailSender.SendMail(...));
return View(...);
}
Or even better, with async:
[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
View = "TimeoutError")]
public async Task<ActionResult> SendMailAsync(CancellationToken cancellationToken )
{
ViewBag.SyncOrAsync = "Asynchronous";
return View("SendMail", await MailSender.SendMailAsync(cancellationToken));
}
Explaination here http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4
Upvotes: 1