user792373
user792373

Reputation: 21

Parameter cannot be NULL. Parameter name: HTTP Context

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

Answers (2)

HarryPotter
HarryPotter

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

Jürgen Steinblock
Jürgen Steinblock

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

Related Questions