28

我有一个非常有线的错误,我的一个自定义控件似乎是创建两个编译文件,当我尝试动态加载它时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.但是在出现此错误并寻找解决方案之后,我严格遵循 MSDN 上的内容。无论我做什么,错误仍然存​​在。

我也尝试过这两种方法,一种是单独的,另一种是一起的(再次失败)

<%@ Register src="~/mod/OneProduct_MediumImage.ascx" tagname="OneProduct_MediumImage" tagprefix="uc1" %>
<%@ Reference Control="~/mod/OneProduct_MediumImage.ascx" %>

配置

我的 web.config,我尝试了maxBatchSize20、100、1000,也有optimizeCompilationstrue 或 false,但错误再次出现。

<compilation debug="false" defaultLanguage="C#" batch="true"
maxBatchSize="800" batchTimeout="10800" optimizeCompilations="false"
targetFramework="4.0">

现在有一些关于

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

当出现此错误时,我现在做的解决方法是:我只是强制项目重新编译并进行少量更改,然后错误消失,直到下一次更新。

我有一个错误,试图解决最后几周的树,却找不到原因。我已经尝试了几乎所有我能做的事情,但都失败了,并且错误再次出现。所以我在这里发帖也许有些人可以帮助我并找到解决办法。

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

更新 1

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

一个是捆绑在一起的 4 个自定义控件。另一个模块是单独的自定义控件。

解决方法

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

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

更新 2

再次出现,即使在我将一些文件移动到不同的目录之后。是随机的,找不到明确的关联是什么触发了它。

更新 3

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

maxBatchGeneratedFileSize="40"
4

5 回答 5

11

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

请参阅此答案以确切了解我在这种情况下所说的“循环引用”是什么意思,因为含义非常微妙。

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

更新 1

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

我会给你一个我认为可行并且很容易尝试的替代解决方案(即使它有点小技巧)。在给您带来问题的用户控件中,在指令中添加以下属性:

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

如果您在其他一些控件中看到此内容,则可以添加相同的内容,但使用 dummy2、dummy3 等...

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

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

顺便说一句,不言而喻,您看到的是 ASP.NET 中的一个错误,而且该错误可能已经存在 10 多年了!也许在某个时候它应该得到解决:)

于 2013-03-06T17:13:46.830 回答
2

为了跟踪问题的原因,我认为了解您的控件是如何创建的很重要。请参考这篇文章:Turing an .ascx User Control into a Redistributable Custom Control

步骤 1:创作用户控件

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

第 3 步:使用 Publish 命令预编译站点

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

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

注意:也许这应该是评论,但我想包括上述链接中的引号。我希望它会有所帮助。

于 2013-03-07T09:46:51.267 回答
1

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

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

这里有一些有用的链接: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

于 2016-02-14T23:43:25.173 回答
0

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

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

在我的情况下,由于两个 DLL 是不同的版本而引发了错误。4.0.0 和 4.1.0。也许你应该调查一下。也许指定编译文件的版本(我猜是 DLL)

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

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

于 2013-03-04T22:51:55.757 回答
0

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

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

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

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

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

<%@ Control Language="cs" 
    AutoEventWireup="false" 
    CodeBehind="OneProduct_MediumImage.ascx.cs" 
    Inherits="ASP.Modules_OneProduct_MedioumImage"
    ClassName="OneProduct_MediumImageControl" %>
于 2013-03-07T09:04:56.553 回答