相同类型的Object的InvalidCastException – 自定义控件加载

我有一个非常有线的错误,我的一个自定义控件似乎是创建两个编译文件,当我尝试使用LoadControl()动态加载它时只是失败,因为无法将一个转换为另一个 – 即使它们正是相同。 我写的消息看到的一切都是一样的,只是改变了编译过的dll。

 System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.InvalidCastException: [A]ASP.Modules_OneProduct_MedioumImage cannot be cast to [B]ASP.Modules_OneProduct_MedioumImage. Type A originates from 'App_Web_kg4bazz1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\80ed7513\10eb08d9\App_Web_kg4bazz1.dll'. Type B originates from 'App_Web_oneproduct_mediumimage.ascx.d1003923.4xoxco7b, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\80ed7513\10eb08d9\App_Web_oneproduct_mediumimage.ascx.d1003923.4xoxco7b.dll'. 

代码

在我完全遵循MSDN上的内容后,这就是现在的代码:

 foreach (int OneProductID in TheProductIdArrays) { // here is the throw. ASP.Modules_OneProduct_MedioumImage OneProduct = (ASP.Modules_OneProduct_MedioumImage)LoadControl(@"~/mod/OneProduct_MediumImage.ascx"); // do some work with //OneProduct } 

以前我没有ASP.加载控件ASP. 但在出现此错误并寻找解决方案后,我严格按照MSDN上的内容进行操作。 无论我做什么,这个bug仍然在这里。

我也尝试了这两种方法,每种方法都在一起,并且一起(再次失败)

   

配置

我的web.config,我已尝试使用maxBatchSize ,也使用optimizeCompilations true或false,但错误再次出现。

  

现在一些细节

  • 错误是随机的,在某些编译出现时,在其他一些不是。
  • 这个项目是一个很大的项目,页面上有很多人在每一分钟要求看到的东西,但也会在内部没有人的情况下出现。
  • 运行在64bit dot.net 4,Intergrated
  • 作为网络花园运行,但也测试和单独一个池(并得到相同的问题)
  • 整个项目的会议结束。
  • 这些页面是从2007年开始运行的,但这个问题出现在上个月,遗憾的是我找不到在哪里以及如何启动,或者是什么触发它因为我有些日子才看到它。
  • 仅出现一个自定义控件加载,即具有大量调用的加载。
  • 我已经改变了4次代码做了很小的改动,或者做了很大的改变,仍然存在。
  • 我尝试使用optimizeCompilations true和false以及相同的问题。
  • 我也尝试通过停止网络,删除所有临时文件,重新打开,然后再次。
  • 当应用程序当时开始仅锁定一个编译时,我尝试在global.asax上放置一个互斥锁,但这也失败了。
  • 从有效的那一刻开始,一切都很好,但如果没有,则不会自动纠正。
  • 我加载此自定义控件的代码是存在的,并在代码上的多个位置,在不同的页面上调用。
  • 具有类似负载的其他自定义控件没有任何问题。
  • 此自定义控件禁用ViewState。
  • 我也尝试重新定位一些代码,用微优化更改完整的函数调用,不再失败。
  • 在开发计算机上工作正常 。 我在web.config上放置batch="true" ,然后就会出现错误。
  • 没有像这样的其他问题,就像我们无法解决的错误一样。 系统运行了几天,池根本不回收,内存稳定,还有更多免费使用。 该计划现已运行多年,但我们几乎每天都会更新。
  • 在相同的核心代码下运行多个站点(类似于stackexchange)并且都具有相同的随机问题。
  • AutoEventWireup为false
  • 它出现,并在其他自定义控件上,我加载相同的方式。

当我出现此错误时,我现在所做的是解决方法:我只是通过一个小的更改强制项目重新编译,并且错误消失,直到下一次更新。

我有一个错误,尝试解决最后一个树周,找出原因。 我几乎尝试了任何我能做到的事情,但都失败了,而且这个bug又出现了。 所以我在这里发帖也许有些人可以帮我解决这个问题。

最后一句:这个错误很疯狂,自定义控件是一样的,我对它做任何事情我只是动态加载它并且繁荣,编译器有两个不同的时间由于某种原因只有他知道 – 随机。

更新1

我能够重现开发人员机器上的错误。 在那里我发现包含这个自定义控件的两个DLL模块有不同。

一个是一组4个自定义控件。 另一个模块是单独的自定义控件。

解决方法

在尝试修复此错误的树周后,我最终发现当编译器批量编译目录并在同一个dll中捆绑许多不同的自定义控件时会出现此错误。 因此,当我尝试单独加载它时会抛出此exception。

所以我将有问题的自定义控件单独移动到另一个目录中,似乎我现在就避免使用它。

更新2

即使我将一些文件移动到另一个目录后,也会再次出现。 是随机的,无法找到与其触发的明确联系。

更新3

因为我们发现这里的主要问题是批处理编译( batch="true" ),它在同一个dll上编译许多自定义控件,一种说到编译器不这样做的方法是maxBatchGeneratedFileSize参数。 我使用它的值为100,问题再次出现,现在我将它降低到40并测试它。

 maxBatchGeneratedFileSize="40" 

打开批处理并在目录级别具有某种forms的循环引用时,可能会发生这种情况。

请看这个答案 ,看看在这种情况下’循环引用’的确切含义,因为含义非常微妙。

如果您设法打破循环(例如,通过将用户控件移动到其他位置),您将不会遇到此问题。

更新1

我认为理论上,这只能由一个循环引起,但有时它们很难被发现。

我会给你一个替代解决方案,我觉得它会起作用并且很容易尝试(即使它有点像黑客)。 在给您提供问题的用户控件中,在指令中添加以下属性:

 <%@ Control Language="C#" [...] CompilerOptions="/define:dummy1" %> 

如果你看到这个与其他一些控件,你可以添加相同的东西,但使用dummy2,dummy3等…

这将具有不对这一个用户控件进行批处理的效果,因为它具有与其他用户控件不同的编译需求。 从技术上讲,您可以添加任何C#命令行作为CompilerOptions ,但虚拟/define是最简单,最无害的。

但与全局关闭批处理不同,性能影响将是最小的,因为只有非常小的页面子集不会被批处理。

顺便说一句,毋庸置疑,你所看到的是ASP.NET中的一个错误,而且这个bug已经有10年多了! 也许在某些时候应该得到解决:)

为了跟踪问题的原因,我认为了解控件的创建方式非常重要。 请参阅此阅读: 将.ascx用户控件转换为可再发行的自定义控件 。

第1步:编写用户控件

要创建用户控件,最好从一个只包含ascx的空应用程序开始。 虽然用户控件的创作使用“标准”技术,但您需要注意一些限制才能将其成功转换为独立的自定义控件。 主要限制是用户控件需要是自包含的 。 也就是说,它不能依赖于app_Code或global.asax等app全局内容。 这样做的原因是,由于目标是将UserControl转换为独立的DLL, 如果它依赖于不属于该DLL的代码,它将在其他应用程序中中断 。 此规则的一个例外是UserControl可能依赖于bin目录(或GAC)中的程序集。 在其他应用程序中使用自定义控件时,您只需确保其他程序集始终可用。

步骤3:使用发布命令预编译站点

(…)选择“使用固定命名和单页程序集”。 这将保证您的用户控件将编译为一个具有基于ascx文件名称的程序集 。 如果不选中此选项,则可以将用户控件与其他页面和用户控件(如果有的话)一起编译,并且程序集将收到一个更难以使用的随机名称。

在我看来,您很可能将用户控件在GAC中编译和注册为单独的程序集,并且还包含在您的Web应用程序DLL中。

注意:也许这应该是一个评论,但我想包括前面提到的链接中的引号。 我希望它有用。

在升级的ASP.NET网站上进行了大量调试之后,我的最后一个错误是运行时的这个错误。

我刚刚检查了Build / Publish选项“使用固定命名和单页程序集”,它解决了我的情况:)

这里有一些有用的链接: https : //msdn.microsoft.com/en-us/library/hh475319(v = vs.110).aspx

https://msdn.microsoft.com/en-us/library/aa479044.aspx

http://forums.asp.net/t/960707.aspx

我最近在编译asp.net MVC 4的修改版本并将新DLL导入项目时遇到了类似的问题。

不知怎的,我在web.config中引用了旧版本的DLL(包括views文件夹中的web.config)

我的案例中的错误被抛出,因为这两个DLL是不同的版本。 4.0.0和4.1.0。 也许你应该调查一下。 也许指定编译文件的版本(我猜的是DLL)

我希望这可以帮助您解决问题。

其他提示:我猜你有某种版本控制系统? 如果是,请在此开始之前将所有更改还原,并仔细查看代码以及哪些模型/控件更改以及如何更改。 如果您没有使用VCS …您无法恢复更改。 你应该开始使用VCS。

我注意到有时设计师会创建第二个CodeBehind设计器文件,例如你会:

 OneProduct_MediumImage.ascx OneProduct_MediumImage.ascx.cs OneProduct_MediumImage.ascx.designer.cs OneProduct_MediumImage.ascx.designer1.cs 

如果您在解决方案资源管理器集中没有“显示所有文件”选项,则不会注意到,但对于Web项目,编译器将编译该文件夹中的所有文件,而不仅仅是项目中包含的文件。

其次,如果您的项目是“网站项目”,则没有名称空间,这可能导致许多奇怪的错误。 看看这个问题: 命名空间问题.net

最后,我设法通过在控制文件上设置ClassName属性来解决看似随机的UserControl错误,例如:

 <%@ Control Language="cs" AutoEventWireup="false" CodeBehind="OneProduct_MediumImage.ascx.cs" Inherits="ASP.Modules_OneProduct_MedioumImage" ClassName="OneProduct_MediumImageControl" %>