[EVENTO] Jornadas de Actualización en Tecnologías Innovadoras #UNNE #Corrientes 6/Sep 2013

Tengo el agrado de invitarlos a las Jornadas de Actualización en Tecnologías Innovadoras el próximo Viernes 6 de Septiembre de 2013 a las 17hs (Lugar: UNNE-FACENA, 9 de Julio 1449, Corrientes, Argentina)

La hemos organizado Desarrollos NEA con la UNNE (Universidad Nacional del Nordeste) FACENA (Facultad de Ciencias Exactas y Naturales y Agrimensura) en una Jornada de Actualización Tecnológica; son una serie de charlas que si bien comienzan con estos temas, nos han comentando desde la UNNE que se vienen una serie con diferentes tecnologías; así que agendandose la fecha  para compartir unas horas intercambiando conocimiento.

En esta oportunidad veremos estos temas:

JornadasActualizacion-UNNE-Septiembre2013

 

 

Jornadas de Actualización en Tecnologías Innovadoras

  • Desarrollo de una red social con Visual Studio 2013 Preview y ASP.NET MVC 5
    Aquí entre Marcos Budimir (@MarkiBudi), Maximiliano Gonzalez Schweizer (@maxigs7) y Diego Cantero (@Mariano_D_C) y quien yo @fernandezja generaremos un proyecto donde mostraremos estas tecnologías:
    • Entity Framework Code First
    • ASP.NET MVC 5
    • Autenticación con Redes Sociales
    • ASP.NET Web API
    • Angular.js
    • SignalR
    • LESS, Web Essentials
    • Bootstrap
  • Inteligencia de Negocios con SQL 2012.
    Aquí Humberto Oraisón nos dará la Introducción al nuevo “Modelo de Datos Tabulares de SSAS”
    • Conceptos.
    • Ventajas y desventajas respecto del modelo tradicional de datos multidimensionales.
    • Introducción al lenguaje de consulta: DAX (Data Analysis Expressions).
    • Implementando una solución BI con datos tabulares.
    • Consumiendo datos tabulares con Excel 2013, SharePoint 2013 y Power View.
  • Infraestructura con Windows Server 2012
    Aquí Francisco Casco (@FranciscoACasco) tiene estos temas:
    • Active Directory
    • DHCP y RRAS
    • File Server (NTFS y Share)
    • GPO (Políticas de Grupo)
    • Remote Desktop Services
    • Virtualización (Hyper-V)

 

Esperamos contar con su presencia, están todos invitados…

Posted 08-30-2013 15:27 por Jose A. Fernandez | con no comments

[ASP.NET+jQuery] Gridview con checkbox limitando a un solo valor de selección

Si necesitamos tener un control checkbox en cada fila y que solo podamos seleccionar un sola fila a la vez (idem a un option)
Esto puede servir tanto para ASP.NET Webform como para MVC, con la salvedad de que depende de como renderizan las grillas de datos.
Gracias a una pregunta de los foros de MSDN de ASP.NET “Limitar selección Checkbox en GridView” tenia algo similiar en el borrador así que aquí va.

Si tenemos un Gridview con una columna template algo así:

<asp:GridView ID="GridView1" runat="server" 
        AutoGenerateColumns="False">
        <Columns>
            <asp:TemplateField HeaderText="Seleccion">
                 <ItemTemplate>
                     <asp:CheckBox ID="chkSeleccion" runat="server" CssClass="controlSeleccion" />
                 </ItemTemplate>
            </asp:TemplateField>  
            <asp:BoundField DataField="Nombre" HeaderText="Nombre" />
            <asp:BoundField DataField="FechaNacimiento" HeaderText="Fecha Nacimiento" />
        </Columns>
    </asp:GridView>

 

Cuando renderiza en ASP.NET 4.0 lo hace de esta manera

La tabla HTML La celda con el control
image image



Solución con jQuery: Evento .click()

Podriamos tener un selector en jQuery que tome todos los checkbox que están dentro de nuestra clase “controlSeleccion” y cada vez que se realiza un evento click (con mouse o sin el directamente con el teclado igualmente dispara el evento)

<script type="text/javascript">
   1:         $(function () {
   2:             $('.controlSeleccion input:checkbox').click(function () {
   3:                 $('.controlSeleccion input:checkbox').removeAttr('checked');
   4:                 $(this).attr('checked', true);
   5:             });
   6:         });    
</script>

NOTA: El selector :checkbox es identico a [type=checkbox]

Solución con jQuery: Atachando el evento con .on() (nuevo en jQuery 1.7)

En la version 1.7 de jQuery tenemos la sintaxis “.on()” para bindear a eventos (como lo eran live o bind, etc).

Nos quedaria algo asi para hacer lo anterior:

<script type="text/javascript">
   1:     $(function () {
   2:         $('.controlSeleccion input:checkbox').on('click', function () {
   3:             $('.controlSeleccion input:checkbox').removeAttr('checked');
   4:             $(this).attr('checked', true);
   5:         });
   6:     });    
</script>

 

Para otros post:

Mas adelante escribiré como hacer que este checkbox se comporte como el “comando de selección del gridview”, para que nos quede todo “un poco mas elegante”, ya que en este caso particular el desarrollador deberá “iterar” para buscar que control esta seleccionado. Una mejora seria que este control este enlazado a algun campo booleano del la colección de objetos

 

 

Espero que les sirva de ayuda o guía.

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 01-10-2012 0:57 por Jose A. Fernandez | con no comments

[Control+F 2011] Curso Terminado: .NET Senior 80hs. WPF/WCF/Silverlight (Polo IT Corrientes)

Se acerca fin de año y por estos lugares, terminó un curso intensivo (y casi sin respiro) de estas tres tecnologías (WPF/WCF/Silverlight) en el marco de las Becas Control+F (@becascontrolf)

“Con el objetivo de fomentar más y mejor empleo en las áreas de software y tecnología a nivel nacional, el Ministerio de Trabajo, Empleo y Seguridad Social de la Nación, en conjunto con CESSI, y con el apoyo de empresas referentes del sector, ofrecen cursos de capacitación gratuita en todo el país.”

Esta vez se armaron en Corrientes, y los gestionó el Polo IT Corrientes a los cursos de Programación .NET Junior, .NET Senior, Administración en SQL Server y Genexus

Aquí los que rindieron el primer día, y los del segundo (a la derecha):

ControlF-NETSENIOR-2011

Algunos ya trabajaban con este tecnología o en .NET, pero la mayoría alumnos de entidades educativas de la región (UTN FRRe, UNNE, Institutos de IT)  y por eso razón casi la mitad del curso quedo en el grupo de los rezagados que quedaron por el camino (por falta de tiempo)

Mas fotos

 

Similares que tuve la oportunidad de estar al frente:

Mas info

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 12-19-2011 16:05 por Jose A. Fernandez | con no comments

Archivado en: ,,

[EF] Utilizar el ConnectionString de mi modelo Entity Framework

Trabajando con Federico necesitamos realizar consultas a la DB “dinámicamente” para rellenar reportes con Report Server embebido en nuestras aplicaciones web.
Para eso utilizamos Procedimientos Almacenados, y como queremos que sea lo mas “genérico posible”, obtenemos el nombre del reporte (ya sea por un campo de la DB o armándolo con alguna política de nombres teniendo en cuenta el del reporte).

Como sabemos la Cadena de Conexión de Entity Framework esta compuesta por la cadena, path de archivos del modelo y de asignación. Por ejemplo…

<connectionStrings>
    <add name="AdventureWorksEntities" 
         connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
         provider=System.Data.SqlClient;provider connection string='Data Source=localhost;
         Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60;
         multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />
</connectionStrings>

Para armar nuestro Comando ADO.NET “puro y simple” (y genérico para llenar nuestros reportes) necesitamos la Conexión y para ello una cadena… y no queríamos:

  • Tener una cadena por separado (la tentación y fuerte!)
  • Parsear la cadena de conexión de EF (para obtener la parte que necesitamos)

 

Entonces solo basta una lectura rápida de las propiedades de la conexión en este caso nos valemos de la propiedad StoreConnection del EntityConnection

Textual de MSDN:

(…)Proporciona acceso a la conexión de origen de datos subyacente usada por el objeto EntityConnection.(…)

 

Podríamos entonces tener una propiedad estática que nos ayude:

public static string ConnectionString
{
    get
    {
        using ( AdventureWorksEntities contexto = new AdventureWorksEntities())
        {
            string cadenaCon = 
                    ((System.Data.EntityClient.EntityConnection)contexto.Connection).StoreConnection.ConnectionString;
            return cadenaCon;
            }
    

    }
}
 

 

Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 11-08-2011 8:56 por Jose A. Fernandez | con no comments

[ASP.NET MVC] Razor: Utilizar el caracter @ en funciones javascript y/o html. Caracter escape @@

Si alguien quiere utilizar en una vista con Razor el caracter “@” en alguna función javascript y/o html por ejemplo, algo simple…

var indiceArroba = email.indexOf("@");

El mensaje que nos proporciona:
""" is not valid at the start of a code block.  Only identifiers, keywords, comments, "(" and "{" are valid.

image

O simplemente si quieres escribir en HTML un simple @

image

Con el mensaje:
A space or line break was encountered after the "@" character.  Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.

 

Solución: El caracter escape para el @ es el doble @@

Para poder seguir adelante el carácter escape para el @ es simplemente el doble arroba @@ Sonrisa

var indiceArroba = email.indexOf("@@");
 
<span>O si quieres simplemente escribir un @@ simple.</span>

 

NOTA:  No esta demás comentar también que podemos combinar HTML/Client Scripting con código Razor utilizando @: y <text>, mas info aquí

 

 

Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 10-21-2011 16:13 por Jose A. Fernandez | con no comments

Archivado en: ,,

[SQL2008+NET] Leer un campo Time (SQL 2008) en un SqlDataReader para obtener un TimeSpan (.NET)

Si estas accediendo a un SQL SERVER 2008 y utilizando uno de sus nuevos tipos de datos como el Time veras que no es fácil leerlo con un SqlDataReader. La idea es obtener el valor del Time (SQL) que en .NET es un tipo de dato TimeSpan.

Si estas pensando hacer esto! olvídalo…

TimeSpan tiempo = (TimeSpan)reader["tiempo"];

Ir a las fuentes (ayuda a MSDN)

Investigando un poco di con método GetTimeSpan del SqlDataReader

Para los curiosos:
Si utilizas el tipo de dato Time(de SQL 2008) se mapea a un tipo de datos TimeSpan de .NET.
Si vemos el articulo Asignar tipos de datos de SQL Server (ADO.NET) vemos que para obtener este valor tenemos un método GetDateTime del SqlDataReader
Pero luego descubrí el GetTimeSpan

 

Obteniendo el valor de campo Time…

  • Para obtener el valor del Time (SQL) que en .NET es un tipo de dato TimeSpan utilizamos el método GetTimeSpan del SqlDataReader, que recibe la posición de la columna, si es la columna 3, el índice es 2... ejemplo:
    TimeSpan horaTimeSpan = reader.GetTimeSpan(2);
  • Podemos mejorar agregando el método GetOrdinal para obtener el índice de la columna si tenemos el nombre
    TimeSpan horaTimeSpan = reader.GetTimeSpan(reader.GetOrdinal("hora"));
    hora.Text = horaTimeSpan.ToString("HH:mm");

 

NOTA 1: Como dice la ayuda en MSDN se debería antes verificar si IsDBNull la columna del reader o sino la conversión genera una excepción

NOTA 2: Dar formato al TimeSpan “para que quede legible por nosotros, los humanos” ;)

Espero que te sirva de ayuda o guía.

 

Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 05-11-2011 21:30 por Jose A. Fernandez | con no comments

Microsoft Community Contributor Award 2011

image

Es grato recibir buenas noticias por correo! Y mas si es un premio.

Dear Jose,
Congratulations! We’re pleased to inform you that your contributions to Microsoft online technical communities have been recognized with the Microsoft Community Contributor Award.
The Microsoft Community Contributor Award is reserved for participants who have made notable contributions in Microsoft online community forums such as TechNet, MSDN and Answers. The value of these resources is greatly enhanced by participants like you, who voluntarily contribute your time and energy to improve the online community experience for others.
Becoming a Microsoft Community Contributor Award recipient includes access to important benefits, such as complimentary resources to support you in your commitment to Microsoft online communities…
Thank you for your commitment to Microsoft online technical communities and congratulations again!

Uno día a día esta con el “cotidiano fuego de los proyectos” y se hace tiempo para ayudar y seguir aprendiendo en los foros… donde cada uno aporta un granito de arena, para que entre todos podamos crecer y evangelizar en la tecnología que nos apasiona (y nos da dolores de cabeza).

Asi que los invito a los foros de MSDN, TechNet y Answers, para compartir, preguntar, ayudar o simplemente “mirar pasivamente”.

Gracias a Microsoft por el reconocimiento… y también por el premio; ya que además de la “distinción” tenemos acceso a una librería online con muchos libros de Microsoft Press (E-Reference Library de Safari Book Online) así que no hay impedimento para seguir formándose…

Es grato ver en Geeks.ms que Javier Torrecilla y Josué Yeray Julián Ferreiro también tienen este honor… y es mas honor para mi compartir con ellos.

 

MCC11_Logo_Horizontal_Full-color

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 05-06-2011 22:33 por Jose A. Fernandez | con no comments

[ASP.NET] Submit a un iFrame dentro de la misma pagina. Con PostbackUrl y modificando el target del formulario (JS puro y jQuery)

Por una pregunta sobre este tema “Enviar datos a una forma dentro de un iframe”, desempolve algo que tenia en borrador hace años…

ANTES NADA… Por qué lo tenia en borrador?

Pense que nadie lo necesitaba… Porque trabajar con iFrames en ASP.NET Webforms en “un dolor constante”, hay que hacer cosas con javascript para la comunicación… una tema fácil es incrustar desde ASP.NET contenido en iframes, y otra es enviar-recibir información. Todo esto porque la magia es ASP.NET es tener un solo formulario que casi casi no debes “tocarlo”

(NOTA: en ASP.NET MVC es una maravilla trabajar con javascript, tienes un mejor control del HTML resultante)

En ASP.NET Webforms tenemos varias opciones a los iFrames para “cargar contenido”

 

Pero volvamos al tema de enviar datos a una iFrame dentro de la misma pagina…

 

El problema

Al problema que en los foros de MSDN preguntaron tenia era como eje esta misma temática así que aquí va para tenerla de referencia.
“Enviar datos a una forma dentro de un iframe”, que como sabemos en ASP.NET tenemos un solo formulario en las paginas, en cada postback se realiza un post a la misma pagina salvo que cambiemos en un boton por ejemplo la propiedad PostbackUrl para modificar la pagina donde enviara los datos… pero no podemos definir el target (nombre del frame) de donde queremos que cargue la pagina destino.

Solución

Para que funcione necesitamos en ASP.NET webforms o en cualquier otro formulario web modificar el atributo target del formulario

Solución en ASP.NET Webforms

Como modificamos la pagina de destino para enviar los datos? con la propiedad PostbackUrl.
Como modificamos el target del formulario? en el cliente lo tenemos que hacer al momento de realizar el click… del boton. Nos ayudamos con OnClientClick

Bueno para muestra “basta un botón” así que el ejemplo para descargar image

 

La pagina padre

Default.aspx

Ingrese un Nombre: <asp:TextBox ID="txtNombre" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Button ID="btnAceptar" runat="server" Text="Aceptar" OnClientClick="enviarDatosAFrame('iframePaginaHija');" PostBackUrl="~/PaginaIframeDestino.aspx" />
<iframe id="iframePaginaHija" name="iframePaginaHija" src="PaginaIframeDestino.aspx" width="100%" height="200px"></iframe>
<p>&nbsp;</p>
<asp:Label ID="lblHora" runat="server" Text="lblHora"></asp:Label>

Si podemos ver el botón que es un webcontrol Button que tiene dos atributos definidos

  • OnClientClick: Que nos ayuda a llamar a una funcion del lado del cliente antes de enviar el submit
  • PostbackUrl: Nos ayuda a definir una pagina de destino diferente a la actual cuando se realice el submit

Tenemos un script llamado “enviarDatosAFrame” que es una función del lado del cliente en javascript que nos ayuda a cambiar el atributo target del formulario de ASP.NET

<script type="text/javascript">
    function enviarDatosAFrame(frameNombre) {
        var formulario = document.getElementById('form1');
        formulario.target = frameNombre;

        setTimeout('formularioInicializar(\'' + formulario.id + '\');', 2000);
    }         
</script>
Mas adelante vemos que es el formularioInicializar.

NOTA: Para que nos sirva de esta manera que buscamos el formulario por Id (getElementById), debes tener definido el Id del formulario de ASP.NET (de tu pagina o MasterPage)

 
 
 

La pagina destino (el contenido del iframe)

PaginaIframeDestino.aspx (en el ejemplo)

Nombre: <asp:Label ID="lblNombre" runat="server" Text="lblNombre"></asp:Label>
<p>&nbsp;</p>
<asp:Label ID="lblHora" runat="server" Text="lblHora"></asp:Label>

Tengo definido en la pagina la directiva PreviousPageType para tener intellisense de lo voy a obtener de la pagina padre

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PaginaIframeDestino.aspx.cs" Inherits="PaginaIframeDestino" %>
<%@ PreviousPageType VirtualPath="~/Default.aspx"  %>


En el codebehind…

protected void Page_Load(object sender, EventArgs e)
   {
       if (PreviousPage != null)
       {
           //Sin el atributo de pagina PreviousPageType 
           //TextBox txt = (TextBox)PreviousPage.FindControl("txtNombre");
           //string nombre = txt.Text;

           //Con el atributo de pagina PreviousPageType, 
           //tenemos acceso a intellisense de PreviousPage (que agregamos una propieddad publica) 
           string nombre = PreviousPage.Nombre;


           lblNombre.Text = nombre;
       }

       lblHora.Text = DateTime.Now.ToLongTimeString();
   }

 

NOTA en la pagina padre (default.aspx) tengo una propiedad para recuperarla en la destino

public partial class _Default : System.Web.UI.Page
{
    public string Nombre {
        get {
            return txtNombre.Text;
        }
    }
...

 

Colocar el atributo target directamente en el form? por si lo pensaste colocar aquí…

Hacer esto significaría que todo postback de esa pagina tendrá como target el definamos “estáticamente allí”… si lo hacemos con javascript a este cambio será dinámico y solamente hay que agregar al control que hace el sumbit la funcionalidad de que ejecute, previo submit, el cambio de target

image

 

 

Con JQuery: Agregar funcionalidad no intrusiva en botón

Con la ayuda de jQuery podemos armar una función que nos ayude a la tarea de modificar el target del formulario a partir de la configuración de un botón si necesidad de adicionar OnClientClick sino simplemente configurando el botón con unos atributos

En este ejemplo, para probar los atributos data de jQuery, se me ocurrió utilizar data-FrameDestino para definir el nombre del iframe donde quiero enviar los datos y como todavía no se como es el selector para “data”, utilice un selector de clase css, entonces todos los botones con la clase “postbackToFrame” tendrán esta funcionalidad

El botón queda así:

<asp:Button ID="btnAceptarConjQuery" runat="server" Text="Aceptar (con jQuery)" 
        PostBackUrl="~/PaginaIframeDestino.aspx" 
        CssClass="postbackToFrame" 
        data-frameDestino="iframePaginaHija" />

La función jQuery

<script type="text/javascript">
    $(document).ready(function () {
        $(".postbackToFrame").click(function () {
            var form = $(this).parents("form:first");
            var formNombre = $(form).attr("id");
            var frameNombre = $(this).data("frameDestino");
            if (frameNombre != null || frameNombre != 'undefined') {

                $(form).attr('target', frameNombre);
            }

            setTimeout('formularioInicializar(\'' + formNombre + '\');', 2000);
        });
    })
</script>

Mas adelante vemos que es el formularioInicializar…

 

Modificamos el target del form, pero las siguientes acciones toman el mismo camino. Como inicializamos?

Cuando modificamos en el cliente el target del formulario el mismo permanece allí y cualquier otra acción que involucre un postback se dirigirá al target correspondiente. Si en la pagina tenemos mas botones, linkbutton o cualquier control que realice un submit tomara el valor del formulario que configuramos

Si llegamos a necesitar que el valor del target se inicialice debemos llamar a una función para tal motivo luego de un tiempo prudencial del submit, en mi caso 2000 milisegundos

Con jQuery

<script type="text/javascript">
    function formularioInicializar(formularioNombre) {
        $('#' + formularioNombre).attr('target', '');
    }      
</script>

O como la primer versión con javascript puro.

<script type="text/javascript">
    function formularioInicializar(formularioNombre) {
        var form = document.getElementById(formularioNombre);
        formt.target ='';
    }      
</script>
 
NOTA: Seria bueno este inicializar formulario reciba el target tambien y podemos unificar todas las funciones que modifican este atributo
 
 

Ejemplo para descargar

 

Espero que les sirva de ayuda o guía.

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 03-26-2011 14:12 por Jose A. Fernandez | con no comments

[ASP.NET] Modificar la salida HTML para Compactar (Minify). En el Render (RegEx, YUI Compresor for .NET) , con Response.Filter y con PageParserFilter

Como en los foros de MSDN alguien necesitaba de un tema similar, lo tenia en borrador y encontré el “justificativo” de terminarlo. Ahora lo tengo para referencias de “opciones de capturar la salida HTML”, encubriendo para minificar el HTML resultante.

Que es Compactar (Minify) HTML?

La idea es limpiar el HTML resultante de caracteres que no son necesarios para renderizar la pagina (espacios en blanco innecesarios, salto de línea) esto se llama Minificar (Minification) Por que son innecesarios estos caracteres? Solo están para una mejor lectura para nosotros “los mortales desarrolladores” la maquina no los necesita.. y el HTML tampoco :)

Aquí utilizare de sinónimo Minificar = Minimizar = Compactar

Puedes ver con un ejemplo online de esta tarea:

Veamos a “vista de águila”…

Antes Después
image image

Se utiliza generalmente para los Javascript, y los CSS donde existen muchas herramientas online, incluso para .NET el Microsoft Ajax Minifier

Es necesario compactar la salida HTML?

No colocar todos los huevos en la misma canasta/cesta”

Depende… utilizando herramientas como YSlow o Page Speed no darán información en que lugar “ganamos más” optimizando. Y no siempre es en la compactación del HTML, ya que con la configuración de la Compresión HTTP (gzip) en el IIS es suficiente.

Entonces que tenemos que compactar?

Lo que si es necesario es comprimir, compactar y agrupar (son tres técnicas que en conjunto logran reducir tiempos deF descarga) los CSS y JS porque allí si ganamos en cantidad de archivos a descargar, como así también los CSS Sprites pero bueno eso ya es otro tema

Todo el mundo ya conoce que tenemos herramientas para estas tareas como por ejemplo Microsoft Ajax Minifier o YUI Compressor for .NET (u otras similares) Algunas con todas las características que necesitamos otras con menos.

 

Primero lo primero: Como modificamos el HTML resultante?

Si conocemos el ciclo de vida de una pagina ASP.NET, lo que se nos viene a la cabeza como lugar para realizar la acción es el método Render, por lo que hay que sobrescribirlo.

La idea la tome por aquí para obtener el HTML resultante, que era para quitar el Viewstate, así que nos sirve para este ejemplo.

 

Ahora el objetivo: Minimizar el HTML

Lo primero que se nos viene la cabeza es reemplazar cadenas, y allí el “balón de oro” es el que tenga mejor performance para cadenas inmutables ;)

Muy bueno este articulo: Comparing RegEx.Replace, String.Replace and StringBuilder.Replace – Which has better performance?

Pero además, vamos a necesitar si o si expresiones regulares (esos textos que como siempre digo parece que un Vulcano los haya escrito) para detectar algunos patrones que nos son simples de buscar. Entonces para el ejemplo RegEx.Replace. (perdonen pero hay que sufrir con esto de expresiones regulares)

 

Objetivos secundarios de este post

Vamos a ver opciones para modificar el HTML resultante para minimizarlo, las complicaciones que podamos tener y porque no es uno de los pilares de la optimización pero aunque no lo utilicemos veremos tecnicas que en alguna oportunidad nos pueden ayudar para otras tareas de modificar la salida:

  • Modificar la salida de una pagina HTML
  • Seguir sufriendo utilizando con expresiones regulares y como nos ayudan bastante (aunque no las entendamos luego de 1 hora)
  • Utilizar los Response.Filter (Filtros para la salida)
  • Conocer y ver una implementación (de terceros) de PageParserFilter

 

Que opciones tenemos para minimizar el HTML

  1. Sobrescribimos el método Render de una pagina, y “limpiamos” con expresiones regulares
  2. Sobrescribimos el método Render y limpiamos con componentes como el YUI Compressor for .NET
    1. Utilizamos la formidable clase en C# para minimizar CSS realizada por Michael Ash que es la que utiliza el YUI Compressor for .NET
  3. Un poco mas “técnicos”… Utilizamos Response.Filter
  4. Vamos hasta “al infinito y mas allá”. Utilizamos PageParserFilter.
    Aqui nos ayudamos con un componente que ya lo tiene implementado
  5. [Idea a futuro] Componente del IIS para limpiar caracteres en blanco… (no lo tengo implementado, si alguien tiene un ejemplo bienvenido en los comentarios)

 

OPCION 1: Sobrescribimos el método Render de una pagina, limpiamos con expresiones regulares

Aquí sobrescribimos el evento Render para obtener la cadena de salida y tratarla

protected override void Render(HtmlTextWriter writer)
    {

        //Obtemos el HTML resultante dentro de un TextWriter
        TextWriter tw = new StringWriter();

        HtmlTextWriter htmlWriter = new HtmlTextWriter(tw);

        //Renderizamos la pagina
        base.Render(htmlWriter);

        htmlWriter.Close();

        //Obtenemos la cadena del HTML
        string htmlResultante = tw.ToString();

        //Limpiando
        string htmlMin = YODA.Web.HTMLUtil.MinificarHTML(htmlResultante);

        //Escribiendo la salida
        writer.Write(htmlMin);
    }

Haciendo uso de expresiones regulares simples podremos Minificar el HTML, solo para algunos patrones (espacios entre tags, saltos de linea, tabs, espacios en blanco mayores que 2

namespace YODA.Web
{
    public class HTMLUtil
    {
        public HTMLUtil()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public static string MinificarHTML(string htmlCadena)
        {
            Regex regEspaciosEntreTags = new Regex(@">(?! )\s+", RegexOptions.Singleline);
            Regex regSaltoDeLinea = new Regex(@"([\n\s])+?(?<= {2,})<", RegexOptions.Singleline);
            Regex regSaltoDeLinea2 = new Regex(@"\r\n", RegexOptions.Singleline);
            Regex regTabs = new Regex(@"\t", RegexOptions.Singleline);
            Regex regEspaciosEnBlanco = new Regex(@"\s{2,}", RegexOptions.Singleline);


            htmlCadena = regEspaciosEntreTags.Replace(htmlCadena, ">");
            htmlCadena = regSaltoDeLinea.Replace(htmlCadena, "<");
            htmlCadena = regSaltoDeLinea2.Replace(htmlCadena, string.Empty);
            htmlCadena = regTabs.Replace(htmlCadena, string.Empty);
            htmlCadena = regEspaciosEnBlanco.Replace(htmlCadena, string.Empty);

            return htmlCadena.ToString();
        }

    }  
}

Puedes buscar en regexlib.com algunos ejemplos. En el ejemplo para descargar dejo varias implementaciones.

 

NOTA IMPORTANTE: Este código no es del todo óptimo, pero sirve como ejemplo. Ya que espacios de variables en javascript  var vble1 = “   valor 1”; lo optimiza por los espacios; Los saltos de linea no tiene en cuenta si lo que viene es una funcion js, y asi sucesivamente. Vuelvo a insistir, antes que el lector se acuerde de mi familia, que esto es un ejemplo de como modificar

 

 

 

OPCION 2: Sobrescribimos el método Render y limpiamos con componentes como el YUI Compressor for .NET

image

NOTA Opción 2: Aquí utilice el componente pero dentro del componente la clase que hace la magia de minimizar es un código de autoría de Michael Ash

Asi que lo dejo también dentro de ejemplo a descargar en la carpeta App_Code

NOTA: No podremos utilizar Microsoft Ajax Minifier  solo tenemos dos métodos que nos nos ayudan a minimizar JS y CSS incluso de obuscar para minimizar el nombre de variables

image

 

Opcion 1.1, 2.1 (Tip): Heredar comportamiento (sobreescribir el Render en un solo lugar)

Ambas Opciones (1, 2) que sobrescriben el Render pueden estar en una Pagina Base para luego heredarla o en una Master base, como el ejemplo

namespace YODA.Web
{
    public class MasterPageBase : System.Web.UI.MasterPage
             
    {
        public MasterPageBase()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        protected override void Render(HtmlTextWriter writer)
        {

            //Obtemos el HTML resultante dentro de un TextWriter
            TextWriter tw = new StringWriter();

            HtmlTextWriter htmlWriter = new HtmlTextWriter(tw);

            //Renderizamos la pagina
            base.Render(htmlWriter);

            htmlWriter.Close();

            //Obtenemos la cadena del HTML
            string htmlResultante = tw.ToString();
            
            //Limpiando
            string htmlMin = YODA.Web.HTMLUtil.MinificarHTML(htmlResultante);

            //Escribiendo salida
            writer.Write(htmlMin);

        }
    }
}

hay que hacer que la Master de nuestro sitio herede de la MasterPageBase que creamos

public partial class SiteWithOverrrideRender : YODA.Web.MasterPageBase
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

 

 

OPCION 3: Utilizamos Response.Filter

Aqui debemos crear un filtro, que es una clase que hereda en este ejemplo de MemoryStream y realice las acciones correspondientes

“(…)Cuando se crea un objeto Stream y se establece la propiedad Filter para el objeto Stream, toda la salida HTTP enviada por Write pasa por el filtro.(…)”

namespace YODA.Web
{
    public class MinificarHTMLFiltro : MemoryStream
    {
        public Stream HtmlStream { get; set; }

        public MinificarHTMLFiltro(Stream htmlStream)
        {
            this.HtmlStream = htmlStream;
        }


        public override void Write(byte[] buffer, int offset, int count)
        {
            string contenidoEnElBuffer = UTF8Encoding.UTF8.GetString(buffer);

            //Acciones a realizar

            //Accion 1: Minificar salida limpinado tabs/espacios en blanco
            contenidoEnElBuffer = YODA.Web.HTMLUtil.MinificarHTML3(contenidoEnElBuffer);

            HtmlStream.Write(UTF8Encoding.UTF8.GetBytes(contenidoEnElBuffer), offset, UTF8Encoding.UTF8.GetByteCount(contenidoEnElBuffer));
        }
    }
}

Y lo utilizamos en el Load de la pagina, simple no?

protected void Page_Load(object sender, EventArgs e)
    {
        Response.Filter = new MinificarHTMLFiltro(Response.Filter);
    }

 

 

OPCION 4: Utilizamos PageParserFilter

Como ya lo dije, aquí es utilizando PageParserFilter, pero no comente que es un poco difícil (y doloroso) crear una clase que herede de PageParserFilter y haga lo que necesitamos, ya que deben construir todos los controles del árbol de controles de una pagina…
Gracias a enlace que compartió Jason Ulloa en los foros de MSDN, pude llegar hasta aquí:

Que es una implementación de PageParserFilter justamente para el objetivo de limpiar los espacios en blanco. Y podremos utilizarlo en ASP.NET Webforms y en ASP.NET MVC

Como lo implementamos, configuramos?

  1. Creamos nuestro PageParserFilter (o utilizamos un componente)
  2. Registramos en la seccion pages del web.config
    <system.web>    
        <pages pageParserFilterType="YODA.Web.MinificarHTMLPageParserFilter">
        </pages>
    ...
    En el ejemplo Omari Нa que lo puedes descargar

    <system.web> <pages pageParserFilterType="Omari.Web.UI.WhiteSpaceCleaner, WhiteSpaceCleanerForWebFormsAndMVC2"> </pages> ...

 

OPCION 5: [Idea a futuro] Componente del IIS para limpiar caracteres en blanco…minimizar

Mejorar… siempre! Para los mas experimentados… Comprimir todo en el IIS. CREAR UN COMPONENTE

Podríamos armar un componente para el IIS para que comprima el HTML resultante de cualquier pagina… ya existe? por favor háganmelo saber a través de los comentarios

 

Ganamos algo? Algunos inconvenientes

Comente mas arriba que hay otros lugares en nuestra app web para empezar a optimizar, porque no siempre ganamos haciendo esto de compactar la salida HTML

Problemas que podemos tener:

  • Como la minificacion es automática, el documento HTML mal formado puede ocasionar una salida “no bien formada” (con errores para el renderizado en el navegador) (incluso eliminando porciones de contenido)
    Por qué puede estar mal formado? porque somos nosotros simples mortales lo que escribimos parte del mismo. Todavía no es todo “autogenerado”, todavía ;)
    Es decir: Si alguien se le fue “los dedos” y escribió <br> />  y al limpiar entre tags no sabremos que puede pasar.
    Mas arriba comente algo sobre por ejemplo limpiar bien los saltos de linea que esta demas (y el problema de javascript)
  • Hay que tener en cuenta el tiempo que involucra tener esta funcionalidad y realizarla por cada pagina, en cada peticion
    Con las otras tecnicas se puede mejorar.

 

 

 

Tips/Recomendaciones

Esto de compactar HTML ( o CSS y JS) tiene que ir de la mano de otras técnicas para optimiza porque no es tampoco nada recomendable estar haciendo esto siempre, ya que es un punto que hay procesamiento. Por este motivo podemos ayudarnos con:

  • Comprimir el contenido que se envía al cliente (típicamente con Gzip) ya la mayoría de los “mortales” utilizamos navegadores modernos que soportan recibir este tipo de contenido.
  • Cachear un poco el contenido en el servidor y en el cliente cuando se pueda,

Algunos tips a tener en cuenta para optimizar aplicaciones web pueden verlo aquí:

Dejo otros enlaces mas abajo.

 

Síntesis

Se aprendió además de la idea de minificar el HTML, varias opciones de como modificar la salida HTML de nuestros proyectos con ASP.NET Webforms.

 

Ejemplo para descargar

 

Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 02-15-2011 10:04 por Jose A. Fernandez | con no comments

Archivado en: ,

[TFS2008] Descargar/Modificar/Publicar Templates de procesos

Hoy me toco modificar un template de un proceso que tenemos en nuestro TFS, siempre lo modificamos online (agregar nuevos campos) pero hoy con Diego decidimos que es hora de hacerlo en un template nuevo, porque que la tarea ardua de  modificar sobre el proyecto “en caliente” no era bueno repetirlo. Además el proceso ya se estandarizó en nuestro sistema de calidad.

Antes que nada… “las fuentes”!

Si quieres hablar, rezar, pensar o realizar alguna acción sobre TFS y tienes a la lengua castellana como “natural” es imposible no caer en algunos de los 1000 post de El Bruno que tiene sobre TFS (y otros temas), como se diría por aquí  “el que sabe… sabe”. Los invito a visitar su blog… Así que de ahí tomo de referencia para el presente articulo,  también dejo enlaces al final.

Empezamos con lo general

Para modificar todo es tocar y retocar XML, pero por por suerte tenemos las Team Foundation Server Power Tools que tiene el Process Template Editor
para VS2008 tienes TFS 2008: Power Tools (Oct/2008)

Cuando instalas tienes en Herramientas el Process Template Editor y puedes editar un work item directamente desde el servidor

image

O puedes abrir un Template de proceso…

image

 

Descargar/Publicar Template de Procesos

Aqui el primer paso su queremos armar un nuevo template modificando uno actual

En el menu del VS que es  Team > Team Foundation Server Settings > Process Template Manager…
image

…o también desde el menú contextual arriba del nombre del servidor en el Explorador

image

Y desde alli podremos ralizar el Download de un proceso y su correspondiente Upload

image

 

Y como seguimos? Modificando los workitems necesarios…

Mas adelante publico otro ejemplo de modificar un Workitem (el que tuvimos que agregar), pero tienes este HowTo de elBruno [TFS2008] HowTo: Agregar un campo personalizado a la definición de un WorkItem

 

Espero que les sirva.


Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 01-11-2011 9:01 por Jose A. Fernandez | con no comments

[Control+F 2010] Curso Terminado: .NET Junior 160hs (UTN – FRRe)

Una vez mas tuve la grata tarea de estar al frente de un curso de Control+F, al igual que el año pasado.
Terminamos a finales de Noviembre las 160 horas de formación de .NET Junior en el marco de las Becas Control+F, en los laboratorios de la UTN FRRE

Aquí los Padawan

ControlF-Curso52-NETJunior-UTN-FRRE-2010

El curso

En esta versión del curso de 160hs menos horas que el curso anterior del año pasado, esta vez en UTN FRRE tenia dos cursos, unos de ellos los daba Hernán Zini (que este año no blogueo fotos todavía)

Temas:

Las Becas Control+F?

Que son las becas? es una iniciativa de capacitación en tecnologías informáticas organizada por el Ministerio de Trabajo de la Nación (Argentina) en conjunto con CESSI y empresas de primera línea del sector informático

 

Un poco mas de fotos…
SDC14471SDC14841SDC14469SDC14840
… por si no se dan cuenta nos vimos desde Agosto hasta Noviembre… desde pulóveres hasta remeras Guiño

 

Mas info

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 12-27-2010 21:20 por Jose A. Fernandez | con no comments

Archivado en: ,,

[Sync Framework] COM Exception: Retrieving the COM class factory for component with CLSID {031913FE-EB2A-49F2-B2BE-B996B2448CD4} failed due to the following error: 80040154

Muy largo el titulo! Disculpas. (Pero para el que necesita vendría bien encontrarlo por el titulo como lo queria hacer yo)

Bueno estas cosas hay que publicarlas… tal como viene a la vida y se nos presenta en nuestras pantallas

 

Introducción

Utilizando en un proyecto Microsoft Sync Framework (@syncfx) para utilizarlo en un componente nos descargamos en nuestro equipo de  proyecto el SDK 2.1 (la version 4.0 esta en CTP desde Oct/2010 para los kamikaze), todo bien para el desarrollo en mi SO de 32bits pero cuando alguien en el equipo de desarrollo con un sistema operativo a 64bits lo quiso levantar, nos arrojaba el siguiente mensaje…

 

Mensaje de la excepción:

Retrieving the COM class factory for component with CLSID {031913FE-EB2A-49F2-B2BE-B996B2448CD4} failed due to the following error: 80040154 Clase no registrada (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))

Mensaje

Retrieving the COM class factory for component with CLSID {C201C012-C929-4D72-B9C5-341D48630630} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))

Imagen de la excepción:

image

Por allí en la InnerException nos tiraba una clave en la Registry dentro de WOW64 (emulación de 32bits dentro del SO de 64bits) entonces buscando algo que me diga que era

Aclaración: en la maquina de SO de 64bits se instalo el SDK 2.1 para su versión 
image

 

Solución

Bueno, es obvia, si el proyecto esta compilado para x86, y los componentes no los tengo instalado los debo instalar en la de 64bit para x86, pero como no lo hicimos así y en el deploy vamos a encontrarnos con maquinas de diferentes plataformas entonces cambiamos la configuración con que se compila a que sea para “Any CPU”

image

Antes… (un poco de historia)

Buscando en los foros de Sync Framework dimos con muchos ejemplos de cuando no existía al versión para 64bits, pero desde la 2.0 la tenemos disponible.
En la lista de discusion de los ejemplos de MS Sync en MSDN Code Gallery encontré también en este pequeño cambio que propusieron.
Antes la única forma era emular en la maquina de 64bits, 32bits (el famoso WOW64)

 

 

Enlaces

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 12-21-2010 19:22 por Jose A. Fernandez | con no comments

[Libros] Comentarista! ;) ..de libros de Murach sobre VB.NET 2008 / ASP.NET 3.5 / ADO.NET, LINQ & EF

BooksMurach_003Hace un par de meses me contactaron de Murach para realizar un comentario sobre algunos libros, que luego me enviaron …y estoy en deuda en este tema. Hoy justamente comente un par de enlaces y volví a este tema desde los foros de MSDN donde recomendamos unos de estos libros.

http://www.asp.net/community/books

http://www.asp.net/community/books/aspnet-web-forms-books

Este post lo tengo en borrador desde hace unos cuantos meses, así que en los próximos días estaré publicando brevemente que opinión merecen estos libros (aunque sea el de la tecnología que mas me agrada que es ASP.NET, EF).

 


Por lo pronto pueden ver la “presencia” que tienen, pero no se asusten están armados/impresos didácticamente cuando se abre en una hoja del lado izquierdo tenemos la teoría y del derecho la practica/código de la misma, particularmente me me gusto esta interesante propuesta de impresión.

 

Los libros:

 

BooksMurach_002

 

Enlaces:

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 11-11-2010 15:06 por Jose A. Fernandez | con no comments

[ASP.NET] Enviar mail a través de Gmail/Hotmail/Live.com configurando mailSettings en el web.config (nuevo enableSsl="true" en ASP.NET 4.0)

Para enviar email a través de los servidores de Google (o Google App) o de desde Hotmail/Live.com es necesario configurar puertos específicos y habilitar SSL.
Ya nos comentaban como hacerlo por código José Alarcón Aguín

Como verán era necesario habilitar por codigo SSL con la propiedad EnableSsl (del SmptClient) . “Era” la única manera/forma antes de ASP.NET 4.0...

Un pedido hacia el equipo de ASP.NET era habilitarlo desde el web.config, y lo tenemos disponible… pueden verlo en el  al pedido en Microsoft Connect

 

Introducción: Sección mailSettings en el web.config

Desde ASP.NET 2.0, tenemos una sección de configuración mailSettings, donde podremos configurar la sección smtp

<system.net>
    <mailSettings>
     <smtp deliveryMethod="Network">
        <network .... />
     </smtp>
    </mailSettings>
</system.net>

En la parte smtp podremos configurar como la sección network (donde tenemos por medio de atributo de configuración la posibilidad de habilitar SSL)

Configurando la seccion mailSettings podremos enviar directamente sin previa configuración de la instancia de la clase SmtpClient, … un mensaje de correo:

SmtpClient smtpClient = new SmtpClient();
try
{
    smtpClient.Send(emailMsg);
}
catch (System.Net.Mail.SmtpException ex)
{
      //acciones
}

 

Configurando… con “enableSsl” (nuevo desde ASP.NET 4.0)

Podemos incluir "EnableSSL" (que es una opción de la clase System.Net.Mail.SmtpClient) desde el archivo de configuración (sección mailSettings) y allí configurando network para el envío a través de SMTP.

Ejemplo de configuración con Google App:

Datos de servidor SMTP:
Server SMTP: smtp.gmail.com / Port: 587 / Enable SSL
User: {user}@gmail.com // {user}@tudominio.com (Google App)
Configuración:
<system.net>
   <mailSettings>
     <smtp deliveryMethod="Network" from=username@gmail.com >
       <network enableSsl="true" 
                defaultCredentials="false" 
                clientDomain="www.tudominio.com"  
                host="smtp.gmail.com" 
                port="587" 
                userName="username@tudominio.com" 
                password="password"/>
     </smtp>
   </mailSettings>

Ejemplo para utilizar Live.com (nuestro Hotmail)

Datos de servidor SMTP:
Server SMTP: smtp.live.com / Port: 587 / Enable SSL
User: {user}@live.com
Configuración:
<system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="usuario@live.com">
        <network enableSsl="true"
               defaultCredentials="false"
               clientDomain="www.tudominio.com"
               host="smtp.live.com"
               port="587"
               userName="usuario@live.com"
               password="password"/>
      </smtp>
    </mailSettings>
 
Puede ver mas info de los atributos de la sección network aquí

Notas sobre “enableSsl”

…from MSDN

(…)El atributo enableSsl especifica si se usa SSL para obtener acceso a un servidor de correo SMTP.La clase System.Net.Mail.SmtpClient sólo admite la extensión de servicio SMTP para SMTP seguro sobre Seguridad de la capa de transporte como se define en RFC 3207.En este modo, la sesión de SMTP

comienza en un canal no cifrado, a continuación, el cliente ejecuta un comando STARTTLS al servidor para intercambiar para proteger la comunicación mediante SSL.Vea RFC 3207 publicada por Internet Engineering Task Force (IETF) para obtener más información.

Un método de conexión alternativo es donde una sesión de SSL se establece al frente antes de que se envíe cualquier comando de protocolo. Este método de conexión a veces se denomina SMTP/SSL y de manera predeterminada usa el puerto 465.Actualmente no se admite este método de conexión alternativo utilizando SSL.(…)

 

Enlaces

 

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 10-07-2010 13:07 por Jose A. Fernandez | con no comments

Archivado en: ,

JUTI XI – Presentación: ASP.NET MVC 2 con Entity Framework 4.0 en VS2010

Hace un par de semanas estuvimos con Cristina presentando en la JUTI algunas características de Entity Framework 4.0 y ASP.NET MVC 2 con Visual Studio 2010. Aquí va el post (que lo tenia en borrador) y la presentación que nos recordó Noelia que no la publicamos aún (así que aquí esta lo que debíamos)

Esto ya nos comento Diego, que presentó con Lautaro y el invitado especial Rodrigo Eirasca (de CGE Consultores de Gestión Empresaria),  el tema Certificar Calidad bajo ISO 9001:2008

Este es el 11° año de la JUTI (Jornadas Universitarias Tecnológicas sobre Informática) que se viene realizando en la UTN-FRRE (que este año esta de cincuentenario)

http://www.juti-frre.com.ar/
NOTA: Lástima que la web de la JUTI la utilicen para otros eventos, seria bueno tener un enlace “histórico” para no perder todas las versiones anteriores :(

Aquí les dejo el enlace a la presentación, y de paso la pruebo la incrustación directa :)

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Posted 10-04-2010 17:01 por Jose A. Fernandez | con no comments

Más artículos Página siguiente >