C# StructureMap导致Web API帮助页ModelDescriptionLink.cshtml中出现堆栈空异常
我有一个Web API项目,它将StructureMap用于其DI。它已经正常工作了一段时间,但是我在Web API帮助页面(Microsoft.AspNet.WebApi.HelpPage)中遇到了一些问题,其中由于空堆栈而引发InvalidOperationException 我用帮助页面创建了一个新的Web API项目,在添加StructureMap.WebApi2包之前,它工作正常,而前面提到的异常在这里抛出,在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 (
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包,对吗?