c# asp.net compiler-construction user-controls dynamic-compilation

c# - InvalidCastException para objeto del mismo tipo-Carga de control personalizado



asp.net compiler-construction (5)

Tengo un error muy cableado, parece que uno de mis controles personalizados es crear dos archivos compilados, y cuando intento cargarlo dinámicamente con LoadControl() simplemente falla porque no puedo LoadControl() uno a otro, incluso si son exactamente lo mismo. Escribo el mensaje para ver que todo es lo mismo, solo cambio el dll compilado.

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''.

El código

Este es el código tal como está en este momento después de haber seguido exactamente lo que está escrito en 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 }

Anteriormente tengo Load the control sin ASP. pero después de que aparece este error y en busca de solución, sigo estrictamente lo que está en MSDN. El error todavía está aquí sin importar lo que haga.

También probé ambos métodos, cada uno solo, y juntos (nuevamente falla)

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

Config

Mi web.config, lo he maxBatchSize con maxBatchSize 20, 100, 1000, también con optimizeCompilations verdadero o falso, pero el error aparece nuevamente.

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

Ahora algunos detalles sobre

  • El error es aleatorio, en algunas compilaciones aparece, en otras no.
  • El proyecto es grande, las páginas están en vivo con mucha gente en cada minuto que pide ver algo, pero también aparece cuando no hay nadie adentro.
  • Se ejecuta en 64 bits dot.net 4, integrado
  • Ejecutar como un jardín web pero también probado y un solo grupo (y obtener el mismo problema)
  • La sesión está desactivada en el proyecto completo.
  • Las páginas se ejecutan desde 2007, pero este problema aparece el último mes, desafortunadamente no puedo encontrar dónde y cómo se inicia, o qué lo desencadena porque tardo algunos días en verlo.
  • Aparece solo una carga de control personalizada, la que tiene una llamada pesada.
  • He cambiado 4 veces el código haciendo pequeños cambios, o grandes cambios y todavía estoy allí.
  • Intenté con optimizeCompilations verdadero y falso y el mismo problema.
  • Intenté también deteniendo la web, borrando todos los archivos temporales, volviendo a abrir, y había otra vez.
  • Intenté colocar un mutex en global.asax cuando la aplicación comienza a bloquear solo una compilación en ese momento, pero esto también falla.
  • Desde el momento en que funciona, todo está bien, pero si no funciona, no se corrige automáticamente.
  • El código que cargo este control personalizado existe y se llama en más de un lugar en el código, en diferentes páginas.
  • Otros controles personalizados, con una carga similar no tuvieron ningún problema.
  • ViewState está deshabilitado para este control personalizado.
  • También he intentado reubicar algún código, cambiar la llamada de función completa con micro optimiza, no volver a fallar.
  • Funciona bien en la computadora de desarrollo . Coloco batch="true" en web.config y el error aparece de inmediato.
  • No hay otros problemas como ese, como un error que no podemos solucionar sin importar qué. El sistema se ejecuta durante días, el grupo NO se recicla en absoluto, la memoria es estable y hay más libertad de uso. El programa se ejecuta desde hace años, pero cambiamos casi todos los días con actualizaciones.
  • Bajo el mismo código central se ejecutan más de un sitio (algo así como stackexchange) y todos tienen el mismo problema aleatorio.
  • AutoEventWireup es falso
  • Aparece y en otro control personalizado que cargo de la misma manera.

Lo que hago ahora como solución alternativa cuando aparece este error: simplemente obligo al proyecto a recompilarse con un pequeño cambio, y el error desaparece, hasta la próxima actualización.

Tengo un error que intenta resolver las últimas semanas de árbol sin encontrar el motivo. He intentado con casi todo lo que puedo hacer, pero todo falla, y el error aparece nuevamente. Así que publico aquí tal vez algunos me pueden ayudar y encontrar una manera de salir de esto.

Última palabra: Este error es una locura, el control personalizado es el mismo, hago cualquier cosa en él. Solo lo cargo dinámicamente y auge, el compilador lo tiene dos veces diferentes por alguna razón que solo él sabe, al azar.

Actualización 1

Pude reproducir el error en la máquina del desarrollador. Ahí descubrí que los dos módulos dll que contienen este control personalizado tienen un diferente.

El uno era un paquete de 4 controles personalizados juntos. El otro módulo era el control personalizado solo.

Solución

Después de semanas de árbol tratando de arreglar este error, termino que este error aparece cuando el compilador hace la compilación por lotes de un directorio, y agrupa muchos controles personalizados diferentes, en el mismo dll. Entonces, cuando intento cargarlo solo, arrojo esta excepción.

Así que muevo el control personalizado problemático solo en un directorio diferente y parece que lo evito por ahora.

Actualización 2

Aparece de nuevo, incluso después de mover algunos archivos a un directorio diferente. Es aleatorio y no puede encontrar una conexión clara con lo que desencadena su.

Actualización 3

Debido a que detectamos que el problema principal aquí es la compilación de lotes ( batch="true" ) que compila en el mismo dll muchos controles personalizados, una forma de decirle al compilador que NO haga eso es el parámetro maxBatchGeneratedFileSize . Lo uso con un valor de 100, y el problema aparece nuevamente, ahora lo bajé a 40 y lo compruebo.

maxBatchGeneratedFileSize="40"


Recientemente me encontré con un problema similar cuando estaba compilando una versión modificada de asp.net MVC 4 e importando la nueva DLL en el proyecto.

De alguna manera estaba haciendo referencia a las versiones anteriores de los archivos DLL en el web.config (incluido el archivo web.config en la carpeta de vistas)

El error en mi caso se produjo porque las dos DLL eran versiones diferentes. 4.0.0 y 4.1.0. Quizás deberías investigar eso. Tal vez especifique una versión de los archivos compilados (supongo que los archivos DLL)

Espero que esto te ayude a solucionar el problema.

Otros consejos: ¿Supongo que tienes algún tipo de sistema de control de versiones? En caso afirmativo, revierte todos los cambios antes de que esto comience y mira cuidadosamente el código y qué modelos / controles cambian y cómo. si no está utilizando VCS ... no hay mucho que pueda hacer para revertir los cambios. Y deberías comenzar a usar un VCS.


Para rastrear la causa del problema, creo que es importante saber cómo se creó su control. Consulte esta lectura: Cómo convertir un control de usuario .ascx en un control personalizado redistribuible .

Paso 1: crear el control de usuario

Para autorizar el control del usuario, lo mejor es comenzar con una aplicación vacía que no contenga nada más que el archivo ascx. Si bien la creación del control de usuario utiliza técnicas "estándar", existen algunas restricciones que debe tener en cuenta para que se conviertan con éxito en un control personalizado independiente. La principal restricción es que el control del usuario debe ser autónomo . Es decir, no puede depender de elementos globales de la aplicación, como App_Code o global.asax. La razón de esto es que, dado que el objetivo es convertir el UserControl en una DLL independiente, se rompería en otras aplicaciones si dependiera de un código que no forma parte de esa DLL . Una excepción a esta regla es que el UserControl puede depender de ensamblajes que viven en el directorio bin (o en el GAC). Solo tiene que asegurarse de que los otros ensambles estén siempre disponibles cuando usa su control personalizado en otras aplicaciones.

y

Paso 3: utilice el comando Publicar para precompilar el sitio

(...) Seleccione "Usar nombres fijos y conjuntos de una sola página". Esto garantizará que su control de usuario se compilará en un único conjunto que tendrá un nombre basado en el archivo ascx . Si no marca esta opción, su control de usuario podría compilarse junto con otras páginas y controles de usuario (si tuviera alguno), y el ensamblado recibiría un nombre aleatorio con el que sería más difícil trabajar.

En mi opinión, es muy probable que tenga el control del usuario compilado y registrado en GAC como un ensamble separado y también incluido en la DLL de su aplicación web.

Nota: Tal vez esto debería haber sido un comentario, pero quería incluir las citas del enlace antes mencionado. Espero que sea útil.



A veces me he dado cuenta de que el diseñador crea un segundo archivo de diseñador de CodeBehind, por ejemplo, usted tendría:

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

No se dará cuenta si no tiene la opción "Mostrar todos los archivos" en el conjunto Explorador de soluciones, pero para un proyecto web el compilador compilará todos los archivos de la carpeta, no solo los incluidos en el proyecto.

En segundo lugar, si su proyecto es un "Proyecto de sitio web", no hay espacios de nombres, lo que puede conducir a muchos errores extraños. Mira esta pregunta SO: Problema del espacio de nombres .net

Finalmente, logré resolver los aparentes errores de UserControl al configurar el atributo ClassName en el archivo de control, por ejemplo:

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


Esto puede suceder cuando tiene los lotes activados y tiene alguna forma de referencias circulares en el nivel del directorio.

Consulte esta respuesta para ver exactamente lo que quiero decir con "referencias circulares" en este contexto, ya que el significado es bastante sutil.

Si logras romper el ciclo (por ejemplo, moviendo un control de usuario a otro lugar), no abordarás este problema.

Actualización 1

Creo que, en teoría, esto solo puede ser causado por un ciclo, pero a veces pueden ser difíciles de detectar.

Te daré una solución alternativa que creo que funcionará y es muy fácil de probar (a pesar de que es un truco). En los controles de usuario que le están dando problemas, agregue el siguiente atributo en la directiva:

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

Si ve esto con algunos otros controles, puede agregar lo mismo pero con dummy2, dummy3, etc ...

Esto tendrá el efecto de no agrupar este control de usuario único, ya que tiene diferentes necesidades de compilación de las demás. Técnicamente, puede agregar cualquier parte de la línea de comando C # como CompilerOptions , pero un dummy /define es el más simple e inofensivo.

Pero a diferencia de desactivar el procesamiento por lotes en todo el mundo, el impacto en el rendimiento será mínimo, ya que solo un subconjunto muy pequeño de páginas no se combinará.

Por cierto, no hace falta decir que lo que estás viendo es un error en ASP.NET, ¡y ese error ha estado allí probablemente por más de 10 años! Tal vez en algún momento debería ser tratado :)