System.Web.Routing.RouteCollection.GetRouteData中的exception
我在iis7上运行的asp.net mvc代码中随机获得了两个exception:
Exception type: InvalidOperationException Exception message: Collection was modified; enumeration operation may not execute. at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.List'1.Enumerator.MoveNextRare() at System.Collections.Generic.List'1.Enumerator.MoveNext() at System.Web.Routing.RouteCollection.GetRouteData(HttpContextBase httpContext) at System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) at System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
和
Exception type: NullReferenceException Exception message: Object reference not set to an instance of an object. at System.Web.Routing.RouteCollection.GetRouteData(HttpContextBase httpContext) at System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) at System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
它不是一贯可重复的,但我认为这是改变(或腐败) RouteTable.Routes
的东西。 我在项目中访问RouteTable.Routes
的唯一地方是Global.asax.cs
,我知道那里的代码只被调用一次,所以这不是问题所在。 有关如何追踪它的任何想法?
在我的例子中,它最终成为HttpModule: Ext.Direct.Mvc (ASP.NET MVC的Ext.Direct)。 此模块有一个错误(在0.8.0版本中已修复),每次为IHttpModule调用Init()时,它都会再次注册路由。 ( 可能多次调用 )。 如果时机正确,它将破坏RouteTable.Routes
集合,并导致上述两个例外之一。
该错误与.Net中不具有线程安全性的集合一致。
根据关于RouteCollection.GetWriteLock()的MSDN文章, RouteTable.Routes
不是线程安全的。 这个问题是因为某些代码试图以一种非线程安全的方式修改RouteTable.Routes
。
最佳实践是修改Application_Start
的RouteTable.Routes
。 如果必须以可以由多个线程同时访问的方式对其进行修改,请确保以线程安全的方式进行修改。 检查以下复制的MSDN示例,以便于参考:
using (RouteTable.Routes.GetWriteLock()) { Route newRoute = new Route("{action}/{id}", new ReportRouteHandler()); RouteTable.Routes.Add(newRoute); }
同样适用于从RouteTable读取 – RouteCollection.GetReadLock() 。
可能,如果通过删除HttpModule来解决这个问题,那是因为这个HttpModule没有实现这样的锁定机制。
其他答案解释了发生了什么,但提供了如何实际跟踪它的细节。 它可能不是你自己的代码导致所有这些麻烦,所以Ctrl-F是不够的..
这个想法
解决问题的原因是,您通常会在实际修改RouteCollection的请求上获得错误。 通常安全地调用UrlHelper.GenerateUrl()
等会在看似随机的时间失败。 为了追踪它,我选择在初始设置后禁止改变路线,将受害者的例外情况转移到罪魁祸首。
第1步:实现自定义RouteCollection
如果设置了标志,那么当有人试图改变路线时会大声喊叫。 这是一个粗略的实现,但你明白了。
public class RestrictedRouteCollection : RouteCollection { public Boolean EnableRestrictions { get; set; } protected override void InsertItem(Int32 index, RouteBase item) { if (EnableRestrictions) { throw new Exception("Unexpected route added".); } base.InsertItem(index, item); } protected override void SetItem(Int32 index, RouteBase item) { if (EnableRestrictions) { throw new Exception("Unexpected change of RouteCollection item."); } base.SetItem(index, item); } protected override void RemoveItem(Int32 index) { if (EnableRestrictions) { throw new Exception("Unexpected removal from RouteCollection, index: " + index); } base.RemoveItem(index); } protected override void ClearItems() { if (EnableRestrictions) { throw new Exception("Unexpected clearing of routecollection."); } base.ClearItems(); } }
第2步:替换默认集合
在Global.asax的Application_start中,在设置路由之前用您的实例替换默认的RouteCollection。 因为似乎没有替换它的API,所以我们强制它在私有字段上reflection:
var routeTable = new LockableRouteCollection(); var field = typeof(RouteTable) .GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic); if (field == null) { throw new Exception("Expected field _instance was not found."); } field.SetValue(null, routeTable); Debug.Assert(RouteTable.Routes == routeTable);
步骤3:在设置预期路线后限制更改
RouteConfig.RegisterRoutes(routeTable); routeTable.EnableRestrictions = true;
全部完成! 现在,在exception日志中查看错误请求。
可能的罪魁祸首:ImageResizer
在我的例子中,它是一个名为ImageResizer
(v4.0.4)的第三方组件,其内部MvcRoutingShimPlugin
自由添加/删除一个没有锁定的路由。 此特定错误已经报告并修复 (虽然此时尚未正式发布)。
上述就是C#学习教程:System.Web.Routing.RouteCollection.GetRouteData中的exception分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1006621.html