May 29
Nos podemos encontrar en la situación, en el que al  añadir una librerÃa de terceros a nuestro proyecto, al compilar, se produzca un error como este:
Unable to emit assembly: Referenced assembly ‘albloguera.utils’ does not have a strong name.
Esto es debido a que el assembly al cual estamos añadiendo esta DLL está firmado con un Strong Name. Los emsamblados firmados con Strong Name solo pueden hacer referencia a otras librerÃas firmadas con Strong Name.
Para solucionar el problemilla, vamos a usar la ventana de comandos de Visual Studio.

1. Crear el fichero de claves. No es necesario, ya que podemos usar el mismo que ya tenemos en nuestro Assembly.
2. Obtemos el MSIL (Microsoft Inmediate Language) del assembly.
- ildasm albloguera.utils.dll /out:albloguera.utils.il
3. Generamos el nuevo Assembly, añadiendo el KeyFile al MSIL
- ilasm albloguera.utils.il /dll /key= albloguera.snk
Abr 18
Esto de jQuery se esta convirtiendo en un vicio (compite mano a mano con Silverlight) y conforme más juegas más quieres y más te diviertes. Y si añadimos UpdatePanels, nos divertimos aún más si cabe.
Al usar jQuery, seguramente usaremos el evento Ready para añadir manejadores de eventos, añadir efectos, añadir / quitar clases.... en fin, inicializar los controles de nuestra página. El evento Ready de jQuery  es un evento que se lanza una vez que todo el DOM de la página ha sido cargado por completo. Por otro lado tenemos los postback parciales provocados por los updatePanels. El cometido de estos controles es evitar la carga completa de la página, es decir, solo actualizar aquellos controles contenidos en el control UpdatePanel. Pero lo que hace realmente no es actualizar los valores de los controles, sino que los sustituye por otros nuevos, tras lo cual todos los controles que hay en el UpdatePanel perderán las clases y eventos asociados a ellos en la inicialización de la página. Esto incluye tanto controles de servidor como controles de cliente, todos serán reemplazados.
Por ejemplo tomemos como ejemplo este UpdatePanel y controles:
Â
HTML:
-
<asp:UpdatePanel ID="UP" runat="server">
-
<ContentTemplate>
-
-
-
-
<span class="label8">Nombre:
</span>
-
</td>
-
-
<input type="text" id="txtnombre" class="inputText" />
-
</td>
-
-
<asp:TextBox runat="server" ID="lblNombre"/>
-
</td>
-
</tr>
-
-
-
<span class="label8">Direccion:
</span>
-
</td>
-
-
<input type="text" id="txtDireccion" class="inputText" />
-
</td>
-
-
<asp:TextBox runat="server" ID="lblDireccion"/>
-
</td>
-
</tr>
-
-
-
<asp:Button runat="server" ID="btnAceptar" Text="Aceptar"
-
CssClass="btnMandatory" onclick="btnAceptar_Click"/>
-
</td>
-
</tr>
-
</table>
-
</ContentTemplate>
-
</asp:UpdatePanel>
 La inicialización de la página la llevarÃamos a cabo normalmente asÃ:
JavaScript:
-
      $(document).ready(function () {
-
           // Inicializacion de controles
-
-
      });
De esta manerá todo funciona correctamente, pero solo mientras no pulsemos el botón "Aceptar" que provoca el postpack parcial. Una vez hagamos click, todos los eventos asociados a los controles desaparecerán. Para solucionarlo tenemos que reasignarlos nuevamente, y una forma de hacerlo es añadiendo un manejador al evento que controla cuando un postback asÃncrono ha finalizado. Nuestro código podrÃa quedar asÃ:
JavaScript:
-
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(Load);
-
-
$(document).ready(function () {
-
Load();
-
});
-
-
function Load() {
-
$('#' + '<%=btnAceptar.ClientID %>').attr('disabled', true);
-
$('#' + '<%=lblNombre.ClientID %>').attr('readonly', true);
-
$('#' + '<%=lblDireccion.ClientID %>').attr('readonly', true);
-
-
$(".inputText").blur(function () {
-
$(this).css("background-color", "FFFFFF");
-
});
-
-
$(".inputText").focus(function () {
-
$(this).css("background-color", "CCCCCC");
-
});
-
-
$(".inputText").keyup(function () {
-
-
-
if ($(this).val() == '')
-
$('#' + '<%=btnAceptar.ClientID %>').attr('disabled', true);
-
else {
-
var nodata = false;
-
$.each($(".inputText"), function () {
-
if ($(this).val() == '')
-
nodata = true;
-
});
-
$('#' + '<%=btnAceptar.ClientID %>').attr('disabled', nodata);
-
}
-
-
});
-
-
$('#' + '<%=btnAceptar.ClientID %>').click(function () {
-
$('#' + '<%=lblNombre.ClientID %>').attr('value', $("#txtnombre").val());
-
$('#' + '<%=lblDireccion.ClientID %>').attr('value', $("#txtDireccion").val());
-
});
-
}Â
Lo que hemos hecho es envolver todo el código que tenÃamos en el evento Ready de jQuery en una función, y llamar a esta función tanto en el evento Ready, como cuando el postback asincrono del updatePanel ha terminado.
Una segunda opción serÃa Inyectar un script desde servidor que invoque a esta nueva función.
C#:
-
protected void btnAceptar_Click(object sender, EventArgs e)
-
 {
-
       lblNombre.Text = lblNombre.Text + "--> Validado con Exito";
-
       lblDireccion.Text = lblDireccion.Text + "--> Validado con Exito";
-
       ScriptManager.RegisterStartupScript(this, GetType(), "", "Load();", true);
-
 }
Mar 20
El pasado 19 de Marzo tuvimos una sesión de Silverlight en el grupo de Usuario de .Net de Málaga. Participé junto al MVP Braulio Diez. Braulio hizo una magnÃfica presentación de Silverlight y hasta donde podemos llevar esta tecnologÃa.Â
Aquà podeis conseguir el material (presentación y ejemplos) que usó Braulio.
Por mi parte hice una pequeña demostración de la integración de una aplicación Silverlight con Javascript.
- Acceso al DOM de la página
- Llamar a métodos Javascript desde Silverlight
- Llamar a métodos Silverligth desde Javascript
- Acceso a la Sesión de una aplicación asp.Net

Aqui podeÃs descargar la presentación y el código de los ejemplos.
Ene 23
A dÃa de hoy yo no tendrÃa duda sobre cual opción elegir, opción que no tiene que ser mejor que la otra. Realmente, yo enfocarÃa el dilema mas bien desde el punto de vista de aplicación web AJAX (orientada al servicio), o aplicación web convencional (.net por supuesto), con sus postbacks (o callbacks) y sus Update Panels. (DeberÃa de estar penalizado el uso del control Update Panel
)
Ajax Control Toolkit
Esta opción nos deja en el ámbito de una aplicación web .Net tradicional con controles de servidor, por lo que seguramente tendremos el grueso de la aplicación en el servidor. Con esto no quiero decir que no sea posible tener lógica en cliente, pero si que resulta bastante engorroso trabajar con los controles del ajax control tolkit con javascript. Por otro lado no debemos olvidar que son controles de servidor, y que son muy fáciles de usar, pero que cuando se complica el desarrollo y la web,  no se por qué, pero el trabajo se complica. Otro punto es el peso de las librerÃas, puf, te echan para atrás. Y un punto no menos importante, si por ejemplo tenemos que hacer una modificación de un Extender, digamos por ejemplo el AutoCcomplete, tendremos que generar un nuevo build y añadir la nueva referencia, y rezar por tener problemas de versiones a la hora de realizar el deploy en el servidor. A modo de anectdota, mencionar que un proyecto en el que estuve trabajando, en cual teniamos un Auto Complete Extender customizado,  tuvimos problemas de referencias cruzadas entre versiones de librerias,  y  con el timestamp del build generado del Extender con la fecha del servidor. Hora del Build X , hora del Servidor de despliegue X-6. Solución, cambiar la hora a la maquina de build y realizar un nuevo build con un timestamp de fecha menor que la hora del servidor web.Â
Leer el artÃculo completo »
Ene 17
La mayorÃa de las veces cuando se define la arquitectura de una aplicación web solo se tiene en cuenta la parte servidor, como si el lado cliente no fuera importante o no existiera. Es verdad que en cliente disponemos de un lenguaje interpretado (no compilado), lo cual hace si cabe un poquito mas complicado el desarrollo,  al no disponer de las ventajas del pre compilado que nos ofrece Visual Studio. Además, el ordenado del código deberÃa ser un factor importante, ya que la tendencia es tener  un único fichero o script de código Javascritp, y esto siempre  comienza siendo unas pocas lÃneas para unas cuantas validaciones y va creciendo paulatinamente debido a la no planificación de la arquitectura en cliente o a nuevos requerimientos.
Atajar esto no es fácil, y el artÃculo no define ningún modelo de arquitectura, pero si unas cuantas pautas de buena conducta que nos ayuden a tener un condigo algo mas limpio y ordenado.
Leer el artÃculo completo »
Dic 13
Que divertido es Javascript, y como echaba de menos un proyecto como el de ahora, casi todo en cliente, pero a pelo sin esas maravillosas facilidades que aporta Silverlight...., bueno algunas si, haciendo uso de Framework de AJAX de Microsot. El contenido de este Post es el tÃpico conocimiento que en mi caso nunca me acuerdo y tengo que echar manos de algun proyecto para recuperarlo. Nunca Mais
JAVASCRIPT:
-
var xPos, yPos;
-
var prm = Sys.WebForms.PageRequestManager.getInstance();
-
prm.add_beginRequest(BeginRequestHandler_scroll);
-
prm.add_endRequest(EndRequestHandler_scroll);
-
-
function BeginRequestHandler_scroll(sender, args) {
-
 if (document.getElementById('gridClientScroll')) {
-
       var item = document.getElementById('gridClientScroll');
-
-
       xPos = item.scrollLeft;
-
       yPos = item.scrollTop;
-
   }
-
}
-
function EndRequestHandler_scroll(sender, args) {
-
-
   if (document.getElementById('gridClientScroll')) {
-
       var item = document.getElementById('gridClientScroll');
-
-
       item.scrollLeft = xPos;
-
       item.scrollTop = yPos;
-
   }
-
}
El código creo que no necesita explicación. Simplemente obtenemos los valores X e Y de elemento con Scroll que queremos persistir después del postback y lo guardamos, para posteriormente, volverlos a establecer. Para ello,  añadimos un manejador de eventos para antes y después del postback asÃncrono, de manera que cada uno de ellos ejecute la función que le especificamos.
May 01
Seguramente que a más de uno le resultarán obvios los puntos mencionados en este post para mejorar el performance de una aplicación web .Net, y reducir el peso de una página, pero nunca esta de mas recordarlos.El que escribe sin ir  más lejos los tuvo que aplicar no hace mucho tiempo cuando un cliente solicitó el análisis de una aplicación para intentar disminuir los tiempos de carga.
Imaginemos el siguiente escenario:
Un formulario con un elevado número de componentes, entre ellos muchos dropdownlist anidados en un DataList. Los dropdownlist son cargados en el servidor, y tenemos varios tipos de combos en cada fila diferenciados por los valores que contienen, y estos se repiten en cada una de las filas del DataList.
Pues si por ejemplo, tenemos 4 combos distintos por fila y el Datalist contiene 20 filas, quiere decir que enviamos 20 veces el contenido de cada tipo de combos desde el servidor al cliente (20x4=80 contenidos repetidos). Además tenemos elementos en el formulario, simplemente para mostrar información, sin nunguna funcionalidad asociada.
Bueno con un escenario asi de simple podemos aplicar los siguientes trucos:
- Sustituir aquellos elementos que no tienen funcionalidad asociada por etiquetas que son los elementos más ligeros capaces de mostrar información. De esta manera eliminamos una sobrecarga del ViewState.
- No cargar los DropDownList en el lado del servidor. En vez de establecer los valores desde .Net, inyectar codigo javascript que defina variables que contengan arrays bidimensionales con la tupla valor y texto que definan cada una de las opciones del combo. Luego, desde cliente, en el onLoad del formulario, cargamos cada unos de los combos con los valores de las variables.
- Eliminar los espacios en blanco que se crean al generar el HTML de la página. Para ello, desde la misma página, podemos sobrescribir el método Render que es justo el último punto desde donde podemos modificar el HTML antes de enviarlo al cliente.
Ahora veamos un ejemplo de código que sobrescribe el método Render de una página.
C#:
-
protected override void Render(HtmlTextWriter writer)
-
{
-
   HtmlTextWriter swHtmlText =
new HtmlTextWriter
(new System.
IO.
StringWriter());
-
-
   base.Render(swHtmlText);
-
-
    //Obtenemos el HTML de la pagina
-
    string strHtml = swHtmlText.InnerWriter.ToString();
-
-
    //Eliminamos todos los espacios en blanco que hay
-
    //entre los controles
-
strHtml = Regex.Replace(strHtml, "^\\s+<", " <", RegexOptions.Multiline);
-
strHtml = Regex.Replace(strHtml, ">\\s+<", "> <", RegexOptions.Multiline);
-
-
    //Escribimos el nuevo HTML limpio
-
    writer.Write(strHtml.Trim());
-
-
}
Feb 28
Creo que este problema es algo frecuente. Intentamos cerrar una pestaña desde una aplicación .Net. Esto simplemente es un "window.close();" y todo funciona correctamente desde Internet explorer 6, pero si intentamos lo mismo en  IE7 salta un popup para preguntarnos si realmente queremos cerrar la pestaña.
La solucion es sencilla. Desde la pagina que queremos cerrar redirigimos nuestra aplicación hacia una página nueva que simplente tendrá el siguiente script:
HTML:
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
-
-
</head>
-
-
-
<script language=javascript type="text/javascript">
-
window.open('', '_self');
-
window.close();
-
</script>
-
</body>
-
</html>
La explicación parece ser que es por motivos de seguridad. No se permite cerrar una pestaña desde Javascript que no ha sido abierta desde Javascript. Con este código simplemente engañamos al navegador haciendole creer que la pagina ha sido abierta desde cliente y luego la cerramos.
Un Bug?
Nov 02
Llevaba tiempo esperando poder reescribir el control Menu Contextual que hice hace ya tiempo, ya que este dejó de funcionar en la sucesivas versiones alfas, betas y gammas de Silverlight (y no más versiones preliminares porque se le acabarÃan las letras a Microsoft, menuda pifia por su parte). Bueno el caso, es que no me apatecÃa volver a escribir el control hasta que Silverlight 2 no fuera una cosa seria. Parece ser que ahora si tenemos una versión final.
El código de este ejemplo lo puedes descargar aquÃ.
La lógica y funcionamiento del control sigue siendo la misma y practicamente no ha cambiado nada. Lo cambios mas importantes han sido la forma de aplicar propiedades sobre los objetos, y además que en esta nueva versión del Control MenuContextual , el userControl MenuContextaul estará formado por objetos OpcionMenu, siendo estos los encargados de pintarse y modificar su estado cuando el raton entre y salga de ellos. El control de los eventos delegados seguirá estando en el control padre MenuContextual.
Enlaces Relacionados:
Oct 08
Si alguna vez necesitamos desactivar un control 'Validator' desde Javascript, solo necesitamos conocer el nombre del validador en cliente, y llamar a la funcion ValidatorEnable de la siguiente forma:
JAVASCRIPT:
-
function DesactivarValidador()
-
{
-
var control= document.getElementById('Validator.ClientID');
-
ValidatorEnable(control, false);
-
}
Comprobado desde la version 1.1 en adelante.
Recent Comments