The base class includes the field ‘X’, but its type is not compatible

Si recibimos el error siguiente después de copiar nuestra web precompilada a nuestro directorio virtual donde tenemos la aplicación:

The base class includes the field ‘XXXXX’, but its type
(XXXXXXX) is not compatible with the type of control
(ASP.XXXXXX_ascx).

Es decir, hay un control de usuario que da error, sin embargo, en local nos funcionaba.
Pasa porque la caché no se ha borrado, se sigue haciendo referencia en algún sitio a una dll temporal anticuada.

SOLUCIÓN:

La mejor opción para que ni siquiera olamos este error es utilizar la opción de Build Website, y si no, borremos antes de pegar el nuevo contenido.
¿Por qué Build Website?
Esta opción te pregunta si existen archivos, y si es así, antes de copiar a la carpeta lo borra todo:

Añade el archivo app_offline ( para ver más sobre app_offline, mira mi artículo sobre el temaEste enlace abre una nueva ventana), mientras se genera la web:

Cuando termina de generar la web, borra el archivo app_offline y deja sólo el resultado.

En este post, dan otras soluciones:
http://www.velocityreviews.com/forums/t91323-user-control-codebehind-type-not-compatible-with-asp-type.htmlEste enlace abre una nueva ventana

septiembre 25, 2015 at 3:38 pm Deja un comentario

Control Adapters en .NET 2

Los controles de .NET son una maravilla porque te facilitan la tarea de programar y ha supuesto para el concepto de programación web un antes y un después. Con .NET te olvidas casi por completo que existen los comandos Request.Form o Request.QueryString porque se ven sustituidos por los controladores de eventos.

No obstante, tienen un handicap a primera vista en la versión 1.1 e incluso en la 2, que el renderizado ya venía con el sello de fábrica Microsoft y con el marcado (HTML) que ellos han decidido. Para los que trabajamos con niveles de accesibilidad AAEste enlace abre una nueva ventana esto supone una torturaporque la doble AA por ejemplo no te permite incluir inline el width o dejar etiquetas style etc…

Entonces llega el programador listillo y dice .NET me da la posibilidad de crear un control que herede del control original de .NET , le hago un render con un override y “p’alante”. Al estilo de esto:

    public class AccessibleImageButton : System.Web.UI.WebControls.ImageButton

{

protected override void Render(HtmlTextWriter output)

{

System.Text.StringBuilder sb = new System.Text.StringBuilder();

 

System.IO.StringWriter sw = new System.IO.StringWriter(sb, System.Globalization.CultureInfo.CurrentCulture);

 

HtmlTextWriter mywriter = new HtmlTextWriter(sw);

 

base.Render(mywriter);

 

mywriter.Close();

 

sw.Close();

 

string s = sb.ToString();

 

s = s.Replace(“style=\”border-width:0px;\””, String.Empty);

 

output.Write(s);

 

}

 

 

}

Desde luego este tipo de código es totalmente válido e inevitable si además queremos añadirle funcionalidades nuevas al control. Por ejemplo, si queremos que las rutas de una imagen vaya a una carpeta determinada dependiendo si una sesión “contraste” se ha activado, y si no, a otra para imágenes normales.

Sin embargo: en .NET 2 se ha creado un nuevo mecanismo built-in y que han venido a llamar “control adapters“.
Estos controladores te permite crear, digamos, un plug-in para cualquier control de servidor, y modificarlo para cambiar su lógica de renderizado.

¿Cuál es la ventaja?
Así a bote pronto, es menos engorroso y sobre todo, se hace a un nivel global dentro de la web.

¿Cómo funcionan los control adapters?
Se utiliza un nuevo tipo de archivo de extensión “.browser” que se coloca en la carpeta “App_browsers” que hará que se produzca el override de los controles que se especifique automáticamente para todo el sitio web:

appbrowsers

El código necesario por ejemplo para reescribir el renderizado de un ImageButton sería el siguiente: Archivo “.browser” dentro de carpeta App_Browsers:

<browsers>

 

<browser refID=”Default”>

<controlAdapters>

 

<adapter controlType=”System.Web.UI.WebControls.ImageButton”

adapterType=”ImageButtonControlAdapter” />

 

</controlAdapters>

</browser>

 

</browsers>

Clase para el Adaptador que referenciamos en el “.browser” y que normalmente puede ir en App_Code pero también se puede poner en un proyecto aparte:

public class ImageButtonControlAdapter : System.Web.UI.Adapters.ControlAdapter

{

protected override void Render(System.Web.UI.HtmlTextWriter output)

{

System.Text.StringBuilder sb = new System.Text.StringBuilder();

 

System.IO.StringWriter sw = new System.IO.StringWriter(sb, System.Globalization.CultureInfo.CurrentCulture);

 

HtmlTextWriter mywriter = new HtmlTextWriter(sw);

 

base.Render(mywriter);

 

mywriter.Close();

 

sw.Close();

 

string s = sb.ToString();

 

s = s.Replace(“style=\”border-width:0px;\””, String.Empty);

 

output.Write(s);

 

}

}

 

En este caso lo que estamos haciendo es buscar un estilo que se inserta automáticamente en los ImageButton y que no podemos dejar si queremos cumplir el nivel AA de accesibilidad web.

septiembre 25, 2015 at 3:31 pm Deja un comentario

App_offline.htm

El app_offline.htm  (cuidado ni .aspx ni html): una página que colocada en la raíz de un dominio, hace que toda la web se redirija a dicho archivo.
Una forma cómoda y “unexpensive” de actualizar una web sin que uno reciba errores porque aún no se han terminado de copiar los archivos de una actualización al servidor.
http://weblogs.asp.net/scottgu/archive/2005/10/06/426755.aspxEste enlace abre una nueva ventana

septiembre 25, 2015 at 3:27 pm Deja un comentario

MaintainScrollPositionOnPostback

Muchas veces nos habremos visto en la necesidad de volver a un punto de la página después de hacer un postback para que el usuario no tuviera que utilizar el scroll lateral.

Normalmente yo suelo utilizar un focus() en javascript si se trata de un formulario y lo añado con ClientScript.RegisterClientScriptBlock. El problema es cuando no hay ningún elemento al que hacer foco (un input o textarea por lo general).

Esto funciona. Quizás no es elegante. Al mismo tiempo hay que meterlo por código y quizás no va en la filosofía de .NET de automatizar con un código además optimizado.

Actualmente esto que yo hacía por código en .NET se haría con <control >: .Focus().

No obstante, puede optimizarse más, y para eso viene en nuestra ayuda el atributo MaintainScrollPositionOnPostback que podemos añadir a la directiva Page de nuestro html. Esto hará que se guarde la posición exacta en píxeles en unos hidden y se restaurará automáticamente mediante javascript.

Con esto se genera lo siguiente en el html:

<input type=”hidden” name=”__SCROLLPOSITIONX” id=”__SCROLLPOSITIONX” value=”0″ />

<input type=”hidden” name=”__SCROLLPOSITIONY” id=”__SCROLLPOSITIONY” value=”257″ />

theForm.oldSubmit = theForm.submit;

theForm.submit = WebForm_SaveScrollPositionSubmit;

theForm.oldOnSubmit = theForm.onsubmit;

theForm.onsubmit = WebForm_SaveScrollPositionOnSubmit;

theForm.oldOnLoad = window.onload;

window.onload = WebForm_RestoreScrollPosition;

// –>

Si queréis alternar el comportamiento de la página para que a veces lo haga y otras no, en vez de desactivar este comportamiento, Scott Mitchell nos lo explica para que funcione a las mil:
http://aspnet.4guysfromrolla.com/articles/111407-1.aspxEste enlace abre una nueva ventana

septiembre 25, 2015 at 3:26 pm Deja un comentario

DropDownList y AppendDataBoundItems

Ejemplo:
<asp:DropDownList ID=”ddlSector” runat=”server” ></asp:DropDownList>

Partimos de un DropDownList, ahora queremos poblar un DataSource con datos de una base de datos (utilizo una colección List por simplificar, lo óptimo es una colección propia del objeto que estemos tratando):
List<string> list=new List<string>();
list=getSectores();

El problema que se nos plantea es que queremos que la opción “Selecciona sector” aparezca en primer lugar.

Hay 2 maneras:

1.-AppendDataBoundItems es la fácil, lo que haremos es lo siguiente
<asp:DropDownList ID=”ddlSector” runat=”server” AppendDataBoundItems=”true”>
<asp:ListItem Value=”0″ Text=”Selecciona un sector”></asp:ListItem>
</asp:DropDownList>

Si no colocamos el atributo AppendDataBoundItems, al hacer DataBind, el valor inicial se borrará.

2.-Podremos insertar el elemento dentro de la lista que hemos poblado de datos:
list.Insert(0,”Selecciona Sector”);
Y después hacerle el DataBound.

septiembre 25, 2015 at 3:25 pm Deja un comentario

DropDownlist and InitialValue

He visto muchas veces implementar una lógica innecesaria para validar un DropDownList para que sea válido el valor si no es igual al valor 0 que normalmente pertenece a la opción del selectbox: “Selecciona una opción”.
Por ejemplo he visto esto:
<asp:CustomValidator ID=”ctvDdlCampo” runat=”server” ControlToValidate=”ddlTCampo” OnServerValidate=”ctvDdlCampo_ServerValidate”></asp:CustomValidator>

Y en el método ctvDdlCampo_ServerValidate implementar lo siguiente:
public void ctvDdlTipoNoticia_ServerValidate(object sender, ServerValidateEventArgs e)
{
if (ddlAgrupaciones.SelectedIndex > 0)
{

}}

Se hace así porque nos hemos saltado una solución más elegante.
En fin ¿cómo lo hubiéramos hecho? simplemente con un RequiredFieldValidator que indique el atributo InitialValue a 0 que es el valor del “Selecciona campo”:

<asp:RequiredFieldValidator ID=”rfvddlCampo” runat=”server”

ControlToValidate=”ddlCampo” InitialValue=”0″></asp:RequiredField>

septiembre 25, 2015 at 3:24 pm Deja un comentario

Subdominios, dominios y sesiones

Para aquellos a los que manejáis sesiones entre dominios y subdominios, existe un problema con .NET y asp, las sesiones propias del lenguaje, es decir, las establecidas con el objeto Session se realizan utilizando el dominio o subdominio en el que se crea la sesión.
Hasta ahí parece todo bien, pero en realidad, esto provoca que por ejemplo prueba.midominio.com y http://www.dominio.com tengan sesiones diferentes. Si por ejemplo, para hacer búsquedas enviara a un usuario logeado a search.midominio.com, perdería la sesión.
Afortunadamente los colegas de Redmond han pensado en ello, para compartir el mismo dominio entre ambos subdominios, tenemos que indicarle bajo qué dominio se van a crear las sesiones así:

Response.Cookies[“ASP.NET_SessionId”].Value = Session.SessionID;

Response.Cookies[“ASP.NET_SessionId”].Domain = “midominio.com”;

septiembre 25, 2015 at 3:22 pm Deja un comentario

Ordenando un StringCollection: ArrayList.Adapter

Como decía en mi articulo Colecciones y discusión sobre NameValueCollection, la clase StringCollection no contiene un método típico de ArrayList o List, como es el método Sort().

Existe otra solución: utilizar un adaptador de ArrayList que ordenará toda clase que implemente el interfaz IList como es el caso de StringCollection:

ArrayList.Adapter(coll).Sort();

septiembre 25, 2015 at 3:22 pm Deja un comentario

Colecciones y discusión sobre NameValueCollection

Vamos a darle un repaso a las colecciones elemento fundamental para programar, entre otras cosas, ya que los DataTable o DataSet cada día está más en desuso por su coste en recursos frente a las colecciones.
Vamos a ver los pros y los contras de las colecciones más famosas, y al final haremos una crítica al uso y abuso de NameValueCollection que he notado.

Gracias a Dino Esposito,gran divulgador de .NET, ya que me baso en material que él ha escrito.
Echemos un vistazo a la oferta de colecciones que nos proporciona .NET:

colecciones

Interfaces / clases

Antes de meternos con las clases, hay que remontarse a los interfaces que se encuentran en el namespace System.Collection.Generic y de las que heredan, cosa que resulta fundamental para después saber qué métodos podemos implementar o qué colecciones podemos pasar a un determinado DataSource.
Tenemos 3 interfaces fundamentales para las colecciones: ICollection, IList e IDictionary. Estas 3 heredan de IEnumerable. IList y IDictionary heredan a su vez de ICollection.

Lo más destacable de estos 3 interfaces:
1.-ICollection:De este interfaz, obtenemos los siguientes métodos: Count, CopyTo(), GetEnumerator() (para iterar la colección). También tenemos el método IsSynchronized() y Synchronize() para aislar el objeto en una aplicación multihilo.
Las clases que lo implementan directamente son por ejemplo: Queue, Stack . Estas 2 clases son curiosas porque sus elementos se destruyen después de acceder a sus datos, la diferencia es que Queue es un contenedor first-in first-out o sea el primero que pusimos es el primero al que accedemos y en el Stack es al contrario.
El problema con las colecciones que sólo heredan de ICollection es que no contemplan métodos para quitar o añadir elementos: IList.

2.-IList: Implementa ICollection y permite añadir y quitar elementos (Add / Insert / Remove / RemoveAt). También incluye: Clear(), Contains().
Clases que heredan de IList: Array, ArrayList,DataView y CollectionBase.

3.-IDictionary: tipo de colección (implementa ICollection) diferente a las anteriores, porque son colecciones de pares de clave y valor (inglés:”collection of key/value pairs”). Por explicarlo de un modo sencillo, no sólo tenemos un campo, tenemos 2, uno con la clave o índice y otro con su valor.
Incluye el método: ContainsKey() y TryGetValue() .
Los diccionarios almacenan los pares en KeyValuePairs , entonces para iterarlos podemos hacer lo siguiente:
Dictionary<string, string> dic = new Dictionary<string, string=””>();
dic.Add(“pruebaclave”, “prueba”);

foreach (KeyValuePair<string, string> kvp in dic)
{
Console.WriteLine(“key={0},value={1}”, kvp.Key,kvp.Value);
}

Si no funciona KeyValuePair, probad DictionaryEntry(por ejemplo:ListDictionary).

Las clases más típicas que implementan IDictionary: Hashtable, y SortedList. SortedList es una clase con más overhead, ya que cada vez que añades elemento hace una búsqueda binaria para ordenarlo. El problema con Hashtable es que no preserva el orden de añadido de ítems.

Las clases que he mencionado (y que implementan estos interfaces) pertenecen al espacio de nombre System.Collections en su mayoría.
Son clases muy generales que aceptan todo tipo de variables, o sea, reciben objetos / Objects, no están fuertemente tipados y en el caso de los diccionarios sólo manejan pares de clave y valor simétricos.
Su flexibilidad de uso contrasta con el coste / overhead que produce por el continuo boxing y unboxingEste enlace abre una nueva ventana que debemos realizar.

Clases Especializadas

Para salvarnos la vida existen 2 recursos: las clases genéricas enSystem.Collections.Generics (List<string>, Dictionary<string,string>), o las clases en otro espacio de nombres: System.Collection.Specialized.
Atentos, estas clases especializadas contienen un overhead: internamente algunas de ellas implementan un ArrayList o HashTable.

En este namespace, encontramos por ejemplo:
StringCollection: Es un ArrayList para strings, genial para colecciones de cadenas. Carencias: no tiene Sort al contrario que ArrayList o List.
StringDictionary: diccionario de cadenas, pero no guarda el orden de añadido y además hace lowercase a la clave.
ListDictionary: es un diccionario más rápido que un Hashtable para menos de 10 items
HybridDictionary: para mejorar el rendimiento, es una lista que empieza como ListDictionary hasta los 15 items y después cambia a Hashtable aunque pierde el orden de añadido.
OrderedDictionary: Mejor que Dictionary siempre que necesites acceder a los datos por índice ( lista[0] ). Imposible con Dictionary, HashTable, StringDictionary etc…
NameValueCollection: es un diccionario especial porque puede gestionar varios valores para una clave.Si yo añado 2 claves iguales, añadirá los valores separados por comas a la misma clave. Esto es un diccionario asimétrico. Además se puede acceder por índice.

Clases genéricas / Clases propias

De lo mejor: List<string>, Dictionary<string,string> y preferible a HashTable y ArrayList.
Aunque mejor utilizar las colecciones propias de objetos.
Un buen sistema para crear este tipo de colecciones es:
public class ActividadCollection : List<Actividad> { }

Nos ahorramos programar los métodos Add / Remove etc…aunque también puedes implementarlos heredando de las clases abstractas:CollectionBase, DictionaryBase, ReadonlyCollectionBase y NameObjectCollectionBase

NameValueCollection

Aquí dejamos el repaso a las colecciones, y hablemos de NameValueCollection.
El motivo es que me ha resultado curioso cómo se imponen modas por un motivo u otro, como por ejemplo el comparar cadenas con .ToLower() en vez de .ToUpper() cuando Microsoft recomienda lo último.
Rompamos este pequeño y diminuto mito.

Esta colección NameValueCollection aunque por su nombre parezca una colección muy sencilla, tiene un coste mayor que los otros diccionarios. Motivo: implementa un HashTable internamente. Aquí estudian su performance.
Por eso, es mejor un StringDictionary o un genérico Dictionary<string,string> a un NameValueCollection si no vamos a querer asociar varios valores a una clave.

ELEGIR COLECCIÓN

Está claro que debemos elegir la que menor coste produce, aunque debemos pensar en la mayor escalabilidad también.
Se recomienda que empecemos mirando las clases más simples y vayamos subiendo a las más complejas hasta hallar la colección idónea.
Si se trata de diccionarios y no sólo de listas, es importante saber qué cantidad de elementos vamos a manejar, si son pocos utilizamos un ListDictionary. ¿Y si no lo sabemos? El HybridDictionary es perfecto.

En el futuro hablaré de colecciones de autor que han ampliado la oferta del “coleccionista”!!

septiembre 25, 2015 at 3:20 pm Deja un comentario

Utilizar cmd como administrador en el Vista y algunos atajos de teclado raros

Recientemente me encontré con esta pregunta, quería hacer un “iisreset /stop” y para ello se me advertía que necesitaba permisos de administrador.

Está claro que si vamos a Inicio > Programas > Accesorios > Símbolo del Sistema, presionamos botón derecho y cliqueamos en “Ejecutar como administrador”, tendremos la respuesta…

Continue Reading enero 12, 2009 at 10:15 am Deja un comentario

Entradas antiguas


Categorías

julio 2020
L M X J V S D
 12345
6789101112
13141516171819
20212223242526
2728293031  

Entradas recientes

Mis links en del.icio.us

Feeds