jueves, 14 de marzo de 2013

ASP.NET AJAX UpdatePanel vs ASP.NET PageMethod


He de aclarar antes de empezar que este post no intenta ahuyentar a programadores que estén trabajando o evaluando ASP.NET AJAX, simplemente pretende atraer atención sobre el hecho de que hay que tener cuidado con lo que se hace con los UpdatePanels y no usarlos para todo ;)

Pongamos una simple página ASP.NET AJAX con un botón, al hacer click tendremos una llamada AJAX al servidor para actualizar la hora que se muestra en pantalla.
Ésta es la parte relevante del código
<asp:UpdatePanel ID="up1" runat="server">
    <ContentTemplate>
        <asp:Label ID="l1" runat="server" />
        <asp:Button ID="b1" runat="server" OnClick="actualizar" Text="Actualizar"/>
    </ContentTemplate>
</asp:UpdatePanel>     
... el .aspx.cs ...
protected void actualizar(object sender, EventArgs ea)
{
    l1.Text = System.DateTime.Now.ToLongTimeString();
}
Cada vez que se pide la información al servidor estamos haciendo una petición de este tipo
ctl02=up1%7Cb1&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwULLTE1NzUzNjc2NjNkZPprXRC88qjwsppC6ijFSkTPpJOl
&__EVENTVALIDATION=%2FwEWAgLmpKatCgK%2B7%2BbtDMzDEjpVzHzhiCikPAfrk6sPE4AT&b1=Actualizar
y recibiendo una respuesta como esta...
129|updatePanel|up1|
            <span id="l1">16:43:17</span>
            <input type="submit" name="b1" value="Actualizar" id="b1" />
        |112|hiddenField|__VIEWSTATE|/wEPDwULLTE1NzUzNjc2NjMPZBYCAgM
PZBYCAgMPZBYCZg9kFgICAQ8PFgIeBFRleHQFCDE2OjQzOjE3ZGRk+JnW9
BNv8dIcJmqvxt10mIGvh4w=|48|hiddenField|__EVENTVALIDATION|/wEW
AgL38IziBAK+7+btDLtfoq6BnTLgLznM9KGlIW/BK1GH|0|asyncPostBackControlIDs||
|0|postBackControlIDs|||4|updatePanelIDs||tup1|0|childUpdatePanelIDs|||3|
panelsToRefreshIDs||up1|2|asyncPostBackTimeout||90|12|formAction||Default.aspx
|27|pageTitle||Update Panel vs PageMethods|
...y teniendo en cuenta que sólo nos importa la parte en negrita... pues... como que es bastante.... El resto de información es:
En la petición... va la información del viewstate de la página, para que desde el aspx.cs podamos acceder a los controles de servidor y tomar decisiones en base a los valores (además de información de parámetros, eventos...)
En la respuesta...va la información para reconstruir gráficamente la parte de la página afectada por la operación
Pero además de la sobrecarga de tráfico generada, cuando el postback causado por la petición AJAX llega al servidor, con la información del viewstate se recrea la clase Page, se ejecutan los eventos de página, etcétera....lo cual es una sobrecarga para el servidor.
Esto no es malo, siempre y cuando vayamos a trabajar con estado nos hace falta regenerar la clase para poder tomar decisiones en base a los controles y el estado en curso. Pero en el caso que nos ocupa (obtener una fecha/dato independiente) todo esto es excesivo :)
Vamos a ver una alternativa que consume menos ancho de banda y menos recursos en el servidor
ASP.NET AJAX UpdatePanel vs PageMethods
Pero... que es un PageMethod???
Teniendo en cuenta que un aspx internamente es una clase System.web.Page. Un PageMethod es un método dentro de esa clase Page que cumple dos requisitos... es static y esta decorado con el atributoWebMethod. Lo que nos permiten es que podamos llamar desde javascript a un método específico de una página web aspx.
Si tenemos en cuenta que estamos obteniendo una funcionalidad concreta a través de una llamada desde Javascript, podemos decir que es algo """parecido""" a un webservice.
La diferencia fundamental radica en que el PageMethod vive dentro de la página y ésta es el único cliente que puede consumirlo, mientras que el webservice es una funcionalidad que reside en un servicio accesible desde cualquier cliente, es un concepto mucho más amplio :)
En este ejemplo concreto podríamos llamar a un WebService en lugar a un PageMethod, conceptualmente nos da igual.
Vamos al lío....para llamar al pagemethod modificamos un poco el código cliente
Es necesario que habilitemos el trabajo con PageMethods estableciendo el valor de un flag del ScriptManager: <asp:ScriptManager runat="server" id="s1"EnablePageMethods="true" />
Esto va a crearnos un objeto Javascript que se llama PageMethods y que nos va a dar acceso a los metodos "especiales" de la página:
    <script type="text/javascript">
    function actualizar()
    {
        PageMethods.actualizar (actualizarOK, actualizarFAIL);
    }
    function actualizarOK(result)
    {      
        $get('l1').innerHTML = result;          
    }
    function actualizarFAIL(error)
    {
        $get('l1').innerHTML = "Intentelo mas tarde";
    }
</script>   
Habéis observado que es más incómodo para el desarrollador que el UpdatePanel, dado que ahora somos nosotros los que tenemos que navegar por el DOM para actualizar la parte cliente.
En el lado cliente sólo nos falta modificar los controles ASP.NET para que apunten al Javascript
<asp:Label ID="l1" runat="server" />
<input type="button" id="b1" onclick="actualizar();" value="Actualizar"/>
y el servidor... configurar el método como PageMethod
using System.Web.Services;
....
[WebMethod]public static string actualizar()
{
    return System.DateTime.Now.ToLongTimeString();
}
Lo ejecutamos.....y...vemos que se envía menos información
( De hecho en el cuerpo no va nada... vemos que la petición al servidor es un post a http://server/website/default.aspx/actualizar para invocar al servicio )
y definitivamente vuelve menos información
{"d":"15:56:53"}

Porqué un PageMethod y no un WebService?
A ojo de buen cubero...si dudáis... encapsulad esa información en un webservice, así estará accesible desde más puntos..obviamente habría que ver el caso concreto para ver si realmente no merece la pena tener un webservice, esto sería si la funcionalidad va a ser específica a esa página, en ese caso tiraríamos por un PageMethod

Lo dicho al principio
Este post no es para desanimar a nadie en el trabajo con UpdatePanels y AJAX, es para que penséis un segundo antes de liaros la manta a la cabeza y poner updatepanels por todas partes. Funcionar....funcionará, pero... a qué coste? :) 
Happy hacking!

David Salgado

Optimizando el rendimiento de ASP .net


  • Minimiza las peticiones cliente/servidor
    Se puede mejorar el rendimiento de la página y la experiencia del usuario si no se utiliza código que produzca acciones de ida y vuelta en el servidor. Hay circunstancias en las que no es necesario utilizar los controles de servidor ASP.NET ni controlar los eventos de devolución de datos. A la hora de realizar algún tipo de desarrollo debemos tener claro el alto coste que supone viajar al servidor. Además, si ViewState se encuentra activado, ASP.NET guardará todo el estado de los controles existentes disminuyendo el rendimiento y la velocidad de carga considerablemente.La ejecución en el cliente es la respuesta.
    Amplía esta información aquí.

  • Utiliza la propiedad IsPostBack del objeto Page para evitar ejecuciones innecesarias en acciones de ida y vuelta al servidor
    Normalmente en los eventos de Page_Init o Page_Load, se realizan ciertas acciones de inicialización y carga. Evalúa qué código requiere que se ejecute sólo en la primera carga y cuales deben ejecutarse siempre por cada petición. De este modo la ejecución siempre será sólo de aquello que se necesite. Utiliza la propiedad Page.IsPostBack para excluir y englobar el código que se ejecutará sólo en la primera carga. 
    Amplía esta información aquí.
    [ad#default]
  • Guarda el estado de vista del control de servidor sólo cuando sea necesario
    Para deshabilitar o habilitar el estado de vista del control establece el atributo EnableViewStatesobre el propio control o en la directiva Page con el valor False o True.
    Con esta propiedad activada, ASP.NET se encarga automáticamente de recopilar el estado de todos los controles de la página para generar un valor encriptado y guardarlo en un INPUT HIDDENllamado __VIEWSTATE de la página. De este modo siempre mantiene el estado y datos de todos los controles entre peticiones al servidor. Para una aplicación de alto rendimiento es recomendable desactivar siempre, o casi siempre, esta propiedad. De este modo evitamos laencriptación/desencriptación del estado de los controles y la transferencia del valor encriptado entre el cliente y servidor (que dependiendo de los controles que añadas puede llegar a ser muypesado) mejorando el rendimiento y la velocidad de carga. 
    Amplía esta información aquí.
    Aún si se necesite tener el ViewState activado pueden realizarse acciones para optimizar el rendimiento:
    • Existen funcionalidades para comprimir el ViewState. Minimizando y reduciendo el tamaño de éste mejorando el tiempo de carga y recepción de datos entre el cliente/servidor.
    • Mueve el Viewstate al final de la página (INPUT HIDDEN) para no incluirlo en el inicio del documento (por defecto), mejorando la velocidad de carga.
    [ad#default]
  • Mantén el almacenamiento en búfer activado a menos que tengas razones para desactivarloDeshabilitar el almacenamiento en búfer en las páginas Web ASP.NET representa un costo de rendimiento significativo
    Con el Búfer activo, el servidor web no devuelve datos hasta que no haya finalizado la ejecución de toda la página. Con el Búfer desactivado realiza procesos de ejecución y respuesta hasta la finalización total de la respuesta. Es decir, con el búfer desactivado el servidor web requerirá más recursos para generar la devolución de datos para una misma petición, disminuyendo en gran medida el rendimiento. Una buena opción es activar siempre el Búfer y controlar manualmente la devolución de datos, aunque no se haya ejecutado aún la totalidad de la página, mediante Response.Flush(). La opción de Búfer también debe activarse en el Servidor Web. 
    Amplía esta información aquí
  • Utiliza Server.Transfer, en vez de Response.Redirect o Response.RedirectPermanent (ASP .net 4.0) en el redireccionamiento entre páginas ASP.NET dentro de una misma aplicación web
    Para la redirección es aconsejable por temas de rendimiento utilizar Server.Transfer ya que no se envían nuevamente las cabeceras para la redirección (siempre y cuando no se requiera enviar nuevas cabeceras según tipo de redirección).
    Amplía esta información aquí.
  • Deshabilita el estado de sesión cuando no lo utilices
    No todas las aplicaciones o páginas requieren el estado de sesión por usuario; deshabilita el estado de sesión si no es necesario.
    • Si en determinadas páginas no se utilizan variables de sesión: Desactiva la funcionalidad especificando el atributo EnableSessionSate a False en la directiva Page.
    • Si en determinadas páginas sólo se utilizan variables de sesión para lectura: Activa la funcionalidad especificando el atributo EnableSessionSate a ReadOnly en la directiva Page.
    • Si necesitas disponer de lectura y modificación de variables en sesión: Activa la funcionalidad especificando el atributo EnableSessionSate a True en la directiva Page.
    Una opción es guardar los datos de sesión del usuario en cookies que se almacenan en el navegador del usuario especificándoles un valor para su caducidad.
    Sesión en escenarios balanceados:
    Normalmente las aplicaciones de alto rendimiento se encuentran balanceadas en varios servidores o varios workers dentro de un mismo servidor, o ambas.
    Teniendo en cuenta que el tipo por defecto para la sesión de usuario es en memoria en el servidor, no nos serviría en dichos escenarios.
    Lo común en estos escenarios es el guardado de la sesión en SQL Server (sobre una base de datos central) o en un proceso de .NET aspnet_state.exe compartido en un único servidor, o en cada server (compartido por workers).
    Si los servidores responden por afinidad (siempre el mismo servidor al mismo usuario durante el transcurso de peticiones durante la sesión), podemos utilizar cualquier tipo de guardado de sesión (siempre teniendo presente las ventajas e inconvenientes de cada uno).
    Amplía esta información sobre los modos de sesión aquí.
    Amplía esta información sobre el atributo EnableSessionState aquí.
  • Utiliza procedimientos almacenados para el acceso a los datos
    El rendimiento mejorará si empleas, siempre que sea posible, procedimientos almacenados compilados en lugar de comandos SQL. Además proporciona encapsulación del código SQL en los procedimientos almacenados evitando el HardCode en el código, dificultando la reutilización y escalabilidad.
  • Utiliza SqlDataReader para la lectura de datos sobre una determinada conexión sobre la base de datos. 
    En los casos en los que sólo necesites recuperar datos para mostrarlos o guardarlos en objetos complejos propios para el tratamiento de lógica de negocio, la clase SqlDataReader proporciona un mayor rendimiento que la clase DataSet/DataTable. Las colecciones DataSet son colecciones desconectadas de la base de datos, se almacenan en memoria, aumentando el consumo de la memoria y utilizando grandes consumos de CPU. Utiliza sólo DataTable cuando se priorice la duración de la conexión sobre la base de datos, es decir, cuando necesites colecciones de forma desconectada. O te enfrentes a requerimientos que te impongan la utilización las funcionalidades que ofrecen las colecciones DataSet.
    Amplía esta información sobre SqlDataReader aquí.
    Amplía esta información sobre DataSet aquí.
  • Guarda en caché los datos y los resultados de página siempre que sea posible
    ASP.NET ofrece mecanismos para almacenar en caché los resultados de página (OutputCache) o datos (Caché) cuando no tienen que calcularse dinámicamente para cada solicitud de página. Además, el diseño de las solicitudes de páginas y de datos que puedan almacenarse en caché, especialmente en las áreas del sitio en las que se espere mayor tráfico, puede optimizar el rendimiento de las páginas. Si utilizas la caché correctamente, el rendimiento de su sitio mejorará más que si utiliza cualquier otra característica de .NET Framework.
    Utiliza el Cache de datos para almacenar las coleccionas más comunes utilizadas en la aplicación Web. Esto reducirá el número de accesos a la base de datos, disminuyendo el cuello de botella que a menudo suele ocurrir con una base de datos central.
    Utiliza el elemento OutputCache de los controles y páginas que tengan más concurrencias y mayor tráfico para evitar la ejecución en el servidor sobre un control o página común que ya se haya procesado. Esto mejorará considerablemente el uso de CPU, mejorando el rendimiento global de la aplicación y el servidor tendrá más recursos disponibles para aumentar el rendimiento en las peticiones entrantes. En un futuro redactaré un post específicamente para esta funcionalidad.
    Amplía esta información sobre Caché aquí.
    Amplía esta información sobre OutputCaché aquí.

    Para entornos balanceados se recomienda utilizar funcionalidades que permitan gestionar la ubicación única de almacenamiento de caché (caché distribuida entre servidores).
    Amplía esta información sobre Caché distribuida aquí.
    Amplía esta información sobre Microsoft Velocity aquí.
    Amplía esta información sobre N-Cache aquí.
    Novedades de OutputCache para ASP.net 4.0
  • Utiliza la paginación y ordenación desde la base de datos y no sobre la interfaz de usuario (UI).
    Normalmente los controles más utilizados con soporte a la paginación es el GridView. Aunque debemos recuperar todos los datos para que el control gestione y fragmente en páginas dichos resultados.
    La recuperación de los datos y la ejecución que le conlleva al control realizar la paginación supone un coste notable que puede influir negativamente al rendimiento. Realizar la paginación sobre el origen de datos (sobre procedimientos almacenados configurados para ello), devolviendo exclusivamente los datos que se mostrarán en una determinada página sobre un conjunto total administrado por la base de datos, mejorará enormemente el rendimiento de la aplicación.
    Comentar que el control GridView utiliza muchísimos recursos del .NET debido al gran abanico de posibilidades y funcionalidades que nos permite/aporta. Esto también puede afectar negativamente al rendimiento, consumos de CPU y velocidad de carga.
    Si el conjunto de datos a mostrar no realiza ninguna funcionalidad específica o compleja debemos optar por controles con menos funcionalidades y posibilidades, pero que a su vez nos ofrezcan mejor rendimiento y más agilidad en la carga, como por ejemplo el Repeater.
  • Considera desactivar la validación de eventos
    Atributo: EnableEventValidation. 
    Este atributo realiza la validación de los eventos originado desde la interfaz de usuario. Si la interfaz de usuarios no permite suplantar eventos en los controles y el control de datos (creación, modificación y eliminación) se realiza de una manera encapsulada y controlada en su aplicación web, deshabilite el atributo EnableEventValidation (indicando False) para evitar pérdida de rendimiento y evitar el coste que supone que ASP.NET realice las validaciones por ti.
    Amplía esta información aquí.
  • Deshabilita el modo de depuración
    Deshabilita siempre el modo de depuración antes de implementar una aplicación de producción o realizar cualquier medida del rendimiento. Si el modo de depuración está habilitado, el rendimiento de la aplicación puede verse afectado. Indique Debug=False en el WebConfig.
    Amplía esta información aquí.
  • Precompila la aplicación
    Una aplicación Web se compila por lotes en la primera solicitud de un recurso. Si no se ha compilado ninguna página de la aplicación, la compilación por lotes compila todas las páginas de un directorio en fragmentos para mejorar el uso del disco y de la memoria. Puede utilizar la herramienta aspnet_compiler.exe para precompilar una aplicación Web y evitar el proceso de compilación en la primera solicitud. 
    Amplía esta informaciónaquí.
  • Controla el uso de las excepciones (Try/Catch)
    El tratamiento de excepciones degrada significativamente el rendimiento de la aplicación. Es aconsejable filtrar posibles excepciones mediante condiciones.
  • Implementa en código administrado los componentes COM llamados frecuentemente
    .Net Framework permite trabajar con los componentes COM tradicionales, pero usar versiones antiguas no mejora el rendimiento. En algunos casos actúa de manera desfavorable al rendimiento de la aplicación. Cada caso es particular por lo que la mejor manera de decidir si transformar un componente es verificar las numero de llamadas a las funciones del código administrado desde el código no administrado. Es recomendable transformar en código administrado todos los componentes COM que requieran un gran numero de llamadas para interactuar.
Amplía esta información aquí.


Fuente:
http://www.josecuellar.net/microsoft-asp-net/optimizando-el-rendimiento-de-asp-net/

BUENAS PRÁCTICAS EN C# ASP.NET

BUENAS PRÁCTICAS EN C#PDFImprimirE-mail
ASP.NET

1. No utilice las variables de sesión a través del código. Utilice variables de sesión sólo dentro de clases y proporcione métodos para acceder al valor almacenado en estas variables. Una clase puede tener acceso a las variables de sesión mediante System.Web.HttpCOntext.Current.Session.
2. No guarde objetos de gran tamaño en la sesión. Esto puede consumir gran cantidad de memoria del servidor en función del número de usuarios.
3. Siempre use una hoja de estilo para controlar la apariencia de las páginas. Nunca especificar el nombre de fuente y tamaño en ninguna de las páginas. Utilice clases de  estilo. Esto le ayudará a cambiar la interfaz de usuario de su aplicación fácilmente en el futuro. Así, si usted desea personalizar la interfaz de usuario, sólo es cuestión de desarrollar una hoja de estilos nueva.
MANEJO DE EXCEPCIONES
1.    Nunca “capturar una excepción y no hacer nada”. Si se oculta una excepción, nunca se sabrá si la excepción sucedido. Muchos desarrolladores utilizan este método para ignorar errores no significativos. Trate de evitar las excepciones comprobando todas las condiciones de error mediante programación. En el peor de los casos, usted debe registrar la excepción en un log y continuar.


Fuente:
http://www.ba-technology.net/index.php/metodologia/91?start=7

miércoles, 13 de marzo de 2013

Heinrrich Facho: Google brinda tips para tener una página web exito...

Heinrrich Facho: Google brinda tips para tener una página web exito...: Una buena página web puede convertirse en la vitrina principal de tu negocio. Simplemente basta analizar cuáles son los métodos que los...

Google brinda tips para tener una página web exitosa


Una buena página web puede convertirse en la vitrina principal de tu negocio. Simplemente basta analizar cuáles son los métodos que los usuarios utilizan hoy para buscar información. Piensa, por ejemplo, cuándo fue la última vez que recurriste a una guía de teléfonos para buscar una tienda o una dirección. Muchas de estas actividades, que hasta hace apenas unos años se realizaban a través de otros medios, hoy se canalizan mediante la web. 

Pero todo esto no quiere decir que, en el mundo online, los resultados lleguen por sí solos. En un universo tan competitivo como el digital, no alcanza con diseñar nuestra página web y simplemente sentarse a esperar los resultados. Según cifras de Netcraft, en todo el mundo hay más de 550 millones de sitios web, de los cuales 300 millones se crearon durante 2011. Entonces, una vez que tu sitio está online, tienes que conseguir que los usuarios que están interesados en tu negocio puedan encontrarlo en la web.

Y ¿cómo puedes lograr esto? Los buscadores son una excelente puerta de entrada. Allí es donde los usuarios ingresan sus consultas sobre productos y servicios,  por lo que tener una buena presencia en los motores de búsqueda es un factor clave para atraer visitas a tu web. A continuación, voy a brindarte algunos consejos para mejorar el posicionamiento y la visibilidad de tu sitio en Google.

1. Añade tu página al índice de Google. Para esto puedes ingresar en la herramienta para Agregar URLs e ingresar la dirección de tu sitio web. Es necesario incluir la URL completa, incluyendo el prefijo http://. Es muy probable que tu página aparezca en Google sin necesidad de cargarla en el índice, ya que puede ser agregada desde el momento en que es linkeada desde otros sites,  aun así nunca está de más agregarla manualmente.

2. Consigue links a tu sitio desde otras páginas web. De este modo, puedes lograr que tu website aparezca mejor posicionado en el buscador. Google elabora un PageRank que le asigna a cada página un puntaje en función de la cantidad y calidad de sitios que linkean a ella. Es importante que subas a tu sitio a directorios de empresas, guías de servicios, y que también procures figurar en los sitios de tus proveedores. Toma en cuenta que Google se esfuerza mucho por detectar los vínculos fraudulentos, por lo que es fundamental que los links a tu web provengan de sitios de calidad.

3. Procura que el contenido de tu sitio describa a tu negocio con precisión. Para esto, establece categorías en tu sitio web y crea una sección para cada una de ellas, por ejemplo, contacto, productos, etc. Asegúrate de que las palabras clave que los usuarios pueden usar para buscar tu negocio están incluidas en los contenidos del sitio, por ejemplo, si tu negocio se dedica al alquiler de carteras en Lima, puedes incluir palabras como “carteras“ “alquiler“ “moda“ “diseños“ y agregar las marcas de carteras con las que cuentas. Asimismo, si eres una empresa que se dedica a la venta de desayunos delivery en Lima, puedes incluir palabras como “desayunos“ “delivery“ y “regalos“. 

4. No incorpores texto en formato de imagen. Este es un error muy común. Por ejemplo, para titular una sección se agrega una imagen que dice: “Servicios de Reparación de Cocinas”. Pero al subir el contenido como imagen, el mismo no es interpretado por Google. Es fundamental que todo contenido importante esté en formato de texto. Además, al incluir fotografías (por ejemplo de un producto), es importante agregar una breve descripción de la misma para que el buscador la reconozca y clasifique.

5. Actualiza tus contenidos periódicamente. La mejor forma de lograr que los usuarios ingresen a tu página y que otros sitios incluyan un link a tu sitio web es ofrecer contenido actualizado, útil y de calidad. Si tienes un catálogo de tus productos o servicios, puedes renovarlo periódicamente para incluir ofertas o novedades. Otra buena opción puede ser incluir en tu sitio un blog para difundir noticias sobre tu negocio o sector.

6. Avísale a tus contactos que tienes un sitio, y también infórmales cuando hagas actualizaciones. Tus propios proveedores, clientes o socios pueden ser una buena alternativa para difundir el sitio y lograr visitas. Cuando lances tu sitio o hagas alguna actualización, puedes enviarles un correo con el enlace para que lo visiten. Probablemente ellos también tengan sus sitios web y, si publicas contenido útil, es posible que incluyan un link a tu página y ayuden a mejorar tu posicionamiento en Google.

7. Asegúrate de que tu página funciona de forma óptima. Ningún usuario se siente a gusto si ingresa a un sitio y parte de la página no funciona, o recibe el mensaje de “Página no encontrada” al hacer clic en un enlace. Procura que todo en tu web funcione óptimamente, y controla también que pueda visualizarse de manera óptima en los diferentes buscadores que hay en el mercado.

Hay muchos secretos y métodos para lograr que un sitio web tenga éxito y logre atraer más visitantes. Lo fundamental es no olvidar cuál es el objetivo del negocio, y tratar de generar contenidos que resulten interesantes para los clientes potenciales. Es esencial además asegurarse de que la página funciona de modo óptimo y actualizarla periódicamente, no considerarla simplemente como una suerte de catálogo online. El mundo de la web cambia todo el tiempo y, si se mantiene una página dinámica y adaptada al comportamiento de los consumidores, sin lugar a dudas se obtendrán excelentes resultados.


Por – Rodrigo Echevarría, Sales Manager en Google Perú



Fuentes: http://www.rpp.com.pe/2013-03-12-google-brinda-tips-para-tener-una-pagina-web-exitosa-noticia_575300.html