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.
-
:Please provide some code – malkam Jan 22 '15 at 09:47
-
If you post your code.... – LPs Jan 22 '15 at 09:48
-
In background thread you can not have the HTTP context that belong to some page. – Aristos Jan 22 '15 at 09:53
-
1You need to pass your HTTPContext into the new thread. – heymega Jan 22 '15 at 10:08
-
1possible duplicate of [How does HttpContext.Current work in a multi-threaded environment?](http://stackoverflow.com/questions/1561036/how-does-httpcontext-current-work-in-a-multi-threaded-environment) – Lex Li Jan 24 '15 at 13:03
2 Answers
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();

- 119
- 7
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

- 30,746
- 24
- 119
- 189