C# StructureMap导致Web API帮助页ModelDescriptionLink.cshtml中出现堆栈空异常

C# StructureMap导致Web API帮助页ModelDescriptionLink.cshtml中出现堆栈空异常,c#,asp.net-web-api2,structuremap,structuremap3,C#,Asp.net Web Api2,Structuremap,Structuremap3,我有一个Web API项目,它将StructureMap用于其DI。它已经正常工作了一段时间,但是我在Web API帮助页面(Microsoft.AspNet.WebApi.HelpPage)中遇到了一些问题,其中由于空堆栈而引发InvalidOperationException 我用帮助页面创建了一个新的Web API项目,在添加StructureMap.WebApi2包之前,它工作正常,而前面提到的异常在这里抛出,在ModelDescriptionLink.cshtml中 else if (

我有一个Web API项目,它将StructureMap用于其DI。它已经正常工作了一段时间,但是我在Web API帮助页面(Microsoft.AspNet.WebApi.HelpPage)中遇到了一些问题,其中由于空堆栈而引发InvalidOperationException

我用帮助页面创建了一个新的Web API项目,在添加StructureMap.WebApi2包之前,它工作正常,而前面提到的异常在这里抛出,在ModelDescriptionLink.cshtml中

else if (modelDescription is CollectionModelDescription)
{
    var collectionDescription = modelDescription as CollectionModelDescription;
    var elementDescription = collectionDescription.ElementDescription;
    @:Collection of @Html.DisplayFor(m => elementDescription.ModelType, "ModelDescriptionLink", new { modelDescription = elementDescription })
}
else
{
    @Html.DisplayFor(m => modelDescription)
}
当它试图显示指向此模型的资源描述的链接时,它被抛出到@Html.DisplayFor(m=>elementDescription.ModelType,“ModelDescriptionLink”,new{modelDescription=elementDescription})的集合

这是一条精简的路线,仍然会导致异常:

[Route("Test")]
public IHttpActionResult Post([FromBody] IEnumerable<MySimpleModel> models)
{
    return null;
}
通过在此处捕获异常,它稍后会在
HelpPageApiModel.cshtml
中几乎相同的一行中弹出:
@Html.DisplayFor(m=>m.resourcescription.ModelType,“modelsdescriptionlink”,new{modelsdescription=Model.resourcescription})
。这是堆栈跟踪的顶部:

[InvalidOperationException: Stack empty.]
System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) +52
System.Collections.Generic.Stack`1.Peek() +6693321
System.Web.WebPages.WebPageBase.get_Output() +51
System.Web.WebPages.WebPageBase.GetOutputWriter() +35
System.Web.WebPages.WebPageExecutingBase.BeginContext(String virtualPath, Int32 startPosition, Int32 length, Boolean isLiteral) +50
ASP._Page_Areas_HelpPage_Views_Help_DisplayTemplates_ModelDescriptionLink_cshtml.Execute() in c:...ModelDescriptionLink.cshtml:28
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +271
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +122
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +145
System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +695
System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +382
System.Web.Mvc.Html.ActionCacheViewItem.Execute(HtmlHelper html, ViewDataDictionary viewData) +278
[InvalidOperationException: Stack empty.]
System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) +52
System.Collections.Generic.Stack`1.Pop() +6667365
System.Web.WebPages.WebPageBase.PopContext() +66
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +154

仍然不确定StructureMap.WebApi2为什么会出现此问题,但我的解决方案基本上是在没有该库的情况下重写依赖项解析。对于在不使用IDependencyScope的情况下实现它的方法非常有用

编辑:我被要求展示一个例子。这基本上就是那个博客上发布的解决方案,但我希望它无论如何都会有所帮助

为structuremap添加自定义控制器激活器:

public class StructureMapWebApiControllerActivator : IHttpControllerActivator
{
    private readonly IContainer _container;

    public StructureMapWebApiControllerActivator(IContainer container)
    {
        _container = container;
    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var nested = _container.GetNestedContainer();
        var instance = nested.GetInstance(controllerType) as IHttpController;
        request.RegisterForDispose(nested);
        return instance;
    }
}
我的容器初始化如下所示:

public class IoC
{
    public static IContainer InitializeContainer()
    {
        IContainer container = new Container
        (
            c => c.Scan
            (
                scan =>
                {
                    scan.Assembly("assembly1");
                    scan.Assembly("assembly2");
                    scan.LookForRegistries();
                    scan.WithDefaultConventions();
                }
            )
        );
        return container;
    }
}
然后,无论您在哪里设置HttpConfiguration(例如调用
MapHttpAttribute路由()
),都要用新的结构映射器替换控制器激活器:

HttpConfig.MapHttpAttributeRoutes();
var container = IoC.InitializeContainer();
HttpConfig.Services.Replace(typeof(IHttpControllerActivator), new StructureMapWebApiControllerActivator(container));
在我的例子中,我使用的是OWIN,所以我没有使用
GlobalConfiguration.Configuration
HttpConfiguration
,但想法是一样的。我相信通常会有一个
WebApiConfig
类,它有一个传递了
HttpConfiguration
的方法,因此您可以在那里进行替换

HelpController.cs
的更改部分再次编辑:

最初StructureMap试图使用第二个构造函数(它有一个HttpConfiguration参数),导致它无法创建HelpController的实例。我通过将第二个构造函数标记为受保护来修复它

在第一个构造函数的调用中,我还将GlobalConfiguration的HttpConfiguration的引用更改为我自己的(从我的启动类),因为我使用的是Owin

public HelpController(): this(Startup.HttpConfig)
{
    logger.Trace("Help controller created");
}

protected HelpController(HttpConfiguration config)
{
    Configuration = config;
}

你(或某人)能在这里发布一个有效的解决方案吗?我尝试了引用的博客文章,但没有成功。@ssmith-Sure,我只是添加了一些代码,显示了我是如何让它工作的!在我的解决方案中,我得到了几乎完全相同的东西,但仍然看到堆栈是空的。ModelDescriptionLink.cshtml中出现异常:(您是否完全删除了StructureMap.WebApi2包?也许可以尝试使用MVC帮助页面创建一个新的Web API项目,并尝试使用StructureMap和我描述的方法来帮助区分问题所在。)lies@Zout所以我假设您也没有使用StructureMap.MVC5包,对吗?