Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap throws ArgumentNullException on HttpContext

I'm having a very weird issue with StructureMap.MVC5

I created a brand new MVC5 project in Visual Studio (default options for an ASP.net MVC project were left selected.)

I then installed structuremap.mvc5 via the nuget package manager (Install-Package StructureMap.MVC).

I then added the following code to to the top of the "HomeController.cs" file:

namespace TestMVC.Controllers
{
    public interface ITest
    {
        string TestMessage();
    }
    public class Test : ITest
    {
        public string TestMessage()
        {
            return "this worked again 23";
        }
    }

I then added a constructor and private member as follows:

public class HomeController : Controller
{
    private readonly ITest _test;

    public HomeController(ITest test)
    {
        _test = test;
    }

Finally, I updated the About action result as follows:

public ActionResult About()
{
    ViewBag.Message = _test.TestMessage();

    return View();
}

The project compiles and start up. I get given the default Index page as normal, but then somewhere between 2 and 5 seconds after the page is returned in the browser, I get an exception thrown in "StructureMapDependencyScope.cs" on the return line of this method:

private HttpContextBase HttpContext {
    get {
        var ctx = Container.TryGetInstance<HttpContextBase>();
        return ctx ?? new HttpContextWrapper(System.Web.HttpContext.Current);
    }
}

The exact error given is:

System.ArgumentNullException was unhandled by user code
  HResult=-2147467261
  Message=Value cannot be null.
Parameter name: httpContext
  ParamName=httpContext
  Source=System.Web
  StackTrace:
       at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)
       at TestMVC.DependencyResolution.StructureMapDependencyScope.get_HttpContext() in d:\Code\Annies\AnniesV4\AnniesV4-BookingAdministration\TestMVC\DependencyResolution\StructureMapDependencyScope.cs:line 69
       at TestMVC.DependencyResolution.StructureMapDependencyScope.get_CurrentNestedContainer() in d:\Code\Annies\AnniesV4\AnniesV4-BookingAdministration\TestMVC\DependencyResolution\StructureMapDependencyScope.cs:line 55
       at TestMVC.DependencyResolution.StructureMapDependencyScope.DisposeNestedContainer() in d:\Code\Annies\AnniesV4\AnniesV4-BookingAdministration\TestMVC\DependencyResolution\StructureMapDependencyScope.cs:line 90
       at TestMVC.DependencyResolution.StructureMapDependencyScope.Dispose() in d:\Code\Annies\AnniesV4\AnniesV4-BookingAdministration\TestMVC\DependencyResolution\StructureMapDependencyScope.cs:line 85
       at TestMVC.App_Start.StructuremapMvc.End() in d:\Code\Annies\AnniesV4\AnniesV4-BookingAdministration\TestMVC\App_Start\StructuremapMvc.cs:line 44
  InnerException: 

Checking, System.Web.HttpContext.Current is indeed null at this point.

If I stop and restart the project, the same error occurs.
If I press F5 to continue, the website then continues to function as expected.
However, if, after pressing F5, I then wait a few moments, stop and restart the project, I don't get the error again until I make some sort of code change and rebuild!

This seemingly makes zero sense to me!

Anyways.. any help would be appreciated!

(Using VS2015 Enterprise RC if that makes any difference)

like image 223
Sk93 Avatar asked Jun 04 '15 10:06

Sk93


1 Answers

The problem is in the dispose of the container. Is trying to dispose a nested container that lives in the HttpContext which is null in the moment of disposal.

I made this changes to the StructureMapDependencyScope class in order to avoid this exception:

public IContainer CurrentNestedContainer
{
    get
    {
        if (HttpContext == null)
            return null;

        return (IContainer)HttpContext.Items[NestedContainerKey];
    }
    set
    {
        HttpContext.Items[NestedContainerKey] = value;
    }
}

private HttpContextBase HttpContext
{
    get
    {
        var ctx = Container.TryGetInstance<HttpContextBase>();
        if (ctx == null && System.Web.HttpContext.Current == null)
            return null;

        return ctx ?? new HttpContextWrapper(System.Web.HttpContext.Current);
    }
}
like image 147
Guido Zanon Avatar answered Nov 03 '22 02:11

Guido Zanon