【发布时间】:2017-11-13 23:39:33
【问题描述】:
11/7 更新 10:29 MST
奇怪的是,如果我将属性从ComponentModel 文件夹移回Common 项目的根目录,则代码可以正常工作。在为 InflowHealth.Common.ComponentModel 命名空间重构所有引用之后,我无法想象什么可能引用旧命名空间。
这几乎就像有一些参考隐藏在某处不是基于代码的,而是运行时和动态的,但我在查看InflowHealthErrorContext 的所有查找结果时肯定看不到它。
11/6 更新 19:33 MST
有趣的是,当我注释掉使用自定义属性继承路由的行并使用默认属性时,它仍然爆炸。更有趣的是,它正在寻找的命名空间InflowHealth.Common.InflowHealthErrorContextAttribute实际上是在我重构它并将其移动到文件夹(和命名空间)ComponentModel之前的旧 FQN。
11 月 6 日 07:42 MST 更新
我相信我已经确定该问题与我用来继承操作的另一个自定义属性有关。像这样将该属性添加到HttpConfiguration:
public static void MapInheritedAttributeRoutes(this HttpConfiguration config)
{
config.MapHttpAttributeRoutes(new InheritanceDirectRouteProvider());
}
该属性的实现非常简单:
public class InheritanceDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(true);
}
}
似乎继承此InflowHealthErrorContext 属性会导致问题,但我不确定问题到底出在哪里。我试过了:
- 删除
Inherited = false,使其可继承。 - 删除
AllowMultiple = true只是因为它配置错误。
那些并没有改变错误。
原帖
我在由几个 Web API 应用程序共享的 Common 程序集中有一个非常简单的属性。就这么简单,我就是不知道是什么导致了这个异常。
我已尝试收集有关此的 Fusion 日志,但它没有记录它们。
这是Attribute:
using System;
namespace InflowHealth.Common.ComponentModel
{
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public sealed class InflowHealthErrorContextAttribute : Attribute
{
// This is a positional argument
public InflowHealthErrorContextAttribute(string errorContext)
{
ErrorContext = errorContext;
}
public string ErrorContext { get; }
}
}
这将用于稍后为过滤器内部完成的自动错误日志记录提供一些额外上下文的路由:
[Authorize(Roles = Roles.ALL_ADMINS)]
[Route("api/ControlPanelApi/PayerClassifications")]
[InflowHealthErrorContext("Error getting payer classifications.")]
public IHttpActionResult GetPayerClassifications(int clientId, bool showAllRows)
{
return Ok(GetData(payerClassificationManager, clientId, showAllRows));
}
在加载应用程序时,当注册 Web API 路由时,它会失败。这是它的突破口:
GlobalConfiguration.Configure(WebApiConfig.Register);
它抛出了这个异常:
无法从程序集“InflowHealth.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”加载类型“InflowHealth.Common.InflowHealthErrorContextAttribute”。
这是堆栈跟踪:
at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
at System.Attribute.GetCustomAttributes(MemberInfo element, Type type, Boolean inherit)
at System.Attribute.GetCustomAttribute(MemberInfo element, Type attributeType, Boolean inherit)
at System.Reflection.CustomAttributeExtensions.GetCustomAttribute[T](MemberInfo element)
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.IsValidActionMethod(MethodInfo methodInfo)
at System.Array.FindAll[T](T[] array, Predicate`1 match)
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem..ctor(HttpControllerDescriptor controllerDescriptor)
at System.Web.Http.Controllers.ApiControllerActionSelector.GetInternalSelector(HttpControllerDescriptor controllerDescriptor)
at System.Web.Http.Controllers.ApiControllerActionSelector.GetActionMapping(HttpControllerDescriptor controllerDescriptor)
at System.Web.Http.Routing.AttributeRoutingMapper.AddRouteEntries(SubRouteCollection collector, HttpConfiguration configuration, IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider)
at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<>c__DisplayClass4.<MapAttributeRoutes>b__1()
at System.Web.Http.Routing.RouteCollectionRoute.EnsureInitialized(Func`1 initializer)
at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config)
at System.Web.Http.HttpConfiguration.EnsureInitialized()
at System.Web.Http.GlobalConfiguration.Configure(Action`1 configurationCallback)
at InflowHealthPortal.MvcApplication.Application_Start() in Global.asax.cs:line 22
【问题讨论】:
-
GetPayerClassifications方法是否与InflowHealth.Common.ComponentModel在同一个命名空间和/或项目中?如果他们在不同的项目中,那么他们使用的是什么框架? -
@Svek 他们在不同的项目中。它们都以 .NET 4.5 为目标,带有
GetPayerClassifications的程序集通过项目引用引用属性所在的Common程序集。 -
在构建 MVC 应用程序时检查 .dll 是否存在于输出文件夹中;如果不是,请将属性更改为
Copy always -
@MikePerrenoud 删除
bin和obj文件夹并重建。一个流浪的 dll 可能会到处闲逛。您是否还可以提供可用于重现问题的minimal reproducible example?我已经尝试使用您迄今为止提供的内容制作一个最小的项目,但无法得到类似的错误。 -
我和@Nkosi 在一起 - 我建议运行 ProcMonitor 并查看 实际 加载的 DLL 视觉工作室,可能来自一些旧 bin 或旧参考。
标签: c# .net asp.net-web-api attributes