Hola!, te quería invitar a este nuevo evento (de todas maneras lo voy a grabar y a publicar), pero no hay como verlo en vivo, ya que podemos hacer consultas, establecer discusión, etc.
El tráfico móvil en la web está explotando. ¿Estás listo? Microsoft ASP.NET MVC 4 incluye nuevas plantillas para dispositivos móviles, un enfoque en el diseño de response desing El orador muestra lo que puedes hacer hoy y mañana para hacer su sitio amigable en un dispositivo móvil. ¿Cuándo debería su sitio móvil convertido en una aplicación móvil? ¿Debe usar CSS3 media querys?, o ir "all in" y el uso de jQuery móvil u otro marco móvil?
Fecha: 27/06/2013 (dd/mm/yyyy).
Hora: 04:00 PM (GMT-05:00 Colombia, Panamá).
Si tiene dudas con la conversión de zonas horarias, por favor haga clic aquí
Inscríbete acá:
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032551084&Culture=es-AR&community=0

 | Hola, hace poco tuve que dar la charla de desarrollo web enfocado a Internet Explorer 10 e Internet Explorer 10 para Windows Phone, agradezco a todos los que fueron. Les dejo las Slides y el material que fue proporcionado y por el gran Jorge Peraza, puedes ver su presentación (en la cual basé parte de la mía) acá: http://channel9.msdn.com/Events/Build/2012/2-015 |
Acá están mis slides:
y puedes descargar desde acá los códigos que revisamos sobre
- Preparar los sitios para Windows 8 (pinned sites, budget, asociar a la tienda, habilitar “compartir”
- Ejemplos de HTML5 (De Jorge Peraza)
- Los códigos cool del desarrollo de HTML5 apps para Windows Phone e IE10.
DESCARGA
https://dl.dropboxusercontent.com/u/1303802/IE10Test.zip
Voy a escribir en unos próximos post, en detalle el tema de como preparar nuestros sitios para aprovechar las ventajas de Windows 8.
Muchas gracias por los buenos comentarios de la charla
, lo pasamos bastaste bien.
Nos vemos!!!
Saludos!
Hola!, los quería invitar al siguiente evento en el que vamos a hablar de las potencialidades de Internet Explorer 10
, Sortearemos una Xbox 360 entre los asistentes!!!

El link de registro es el siguiente!, aprovecha esta oportunidad!
, nos vemos allá!!
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032555640&Culture=es-CL&community=0
Saludos!!
@chalalo
Hola que tal?, seguimos con esta serie de artículos sobre Web Api y Odata, esta vez veremos las opciones de consulta.
Una de las potencialidades de Odata es la capacidad de definir consultas personalizadas y parametrizadas mediante la url, siguiendo nuestros ejemplos anteriores, podemos tener:
http://localhost:1927/Odata/Asignaturas?$orderby=Semestre
A estos parámetros Odata les llamara “query Options”, dentro de las que nos ofrece Odata tenemos:
- $filter: Filtra los resultados, basados en una condición booleana.
- $inlinecount: Le indica al servidor que incluya dentro del resultado el total de entidades que se obtuvieron por medio de la query, eso está pensado en la páginación eficiente del lado del servidor
- $orderby: Ordena los resultado por algún criterio establecido en la query.
- $skip: omite los primeros n resultados, apropiado para la paginación.
- $top: Retorna solo los primeros n resultados.
Antes que nada, debemos habilitar la posibilidad de utilizar estas Query Options, y se debe hacer explícitamente, así que nos vamos al método Register del archivo WebApiConfig y des comentamos la línea que dice : config.EnableQuerySopport();

Si no te aparece esto, es por que debes instalar el WebTools 2012.2 Update, ya que la plantilla Web API incluye este código.
Algo importante de indicar, es que el método EnableQuerySupport habilita las consultas para todos las acciones de los controladores que retornen un tipo IQueryable. Si no quieres que esto suceda, y solo agregar esta característica a algunas acciones, debes agregar el atributo [Queryable] a cada acción:
[Queryable]
public override IQueryable<Asignatura> Get()
{
return asignaturas.AsQueryable();
}
Veamos entonces algunos ejemplos de consultas, si recordamos el artículo anterior teníamos:
http://localhost:1927/Odata/Asignaturas/

Para los filtros tenemos:
Retorna todos las asignaturas con semestre igual a 2:
http://localhost:1927/Odata/Asignaturas?$filter=Semestre eq 2

Retorna todas las asignaturas que tienen el string II dentro de Nombre:
http://localhost:1927/Odata/Asignaturas?$filter=substringof('II',Nombre)

La misma consulta anterior, pero con el retorno de la cantidad de resultados:
http://localhost:1927/Odata/Asignaturas?$filter=substringof('II',Nombre)&$inlinecount=allpages

El mismo ejemplo anterior, le agregamos ordenación descendente por ID
http://localhost:1927/Odata/Asignaturas?$filter=substringof('II',Nombre)&$inlinecount=allpages&$orderby=ID desc

Como vez, bastante útil y fácil, en el próximo articulo revisaremos el tema de la paginación con un completo ejemplo, nos vemos!
@chalalo.
Hola, quería compartir esta grabación del webcast que di hace unas horas, está enfocado a las herramientas que nos da el IDE más que a la programación, con mucha demo, asi que sin más que decir, el video!:
Saludos!
@chalalo
Una de las consultas recurrentes que recibo es sobre como crear pdf en ASP.NET, para esto hay varias respuestas, esta vez voy a mostrar una bastante sencilla de la mano de iTextSharp, que es una biblioteca gratis con muy buenas opciones para la generación pdf a partir de un string que almacena un HTML.
Lo primero que vamos a hacer es , mediante Nuget, obtener la biblioteca:

Una vez instalado, vamos a agregar (esto es opcional) una carpeta en donde estén nuestras plantillas para imprimir nuestro informe:

Este archivo test.html no es nada más que un archivo HTML en donde agregué el siguiente código:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<p>Nombre:[nombre]</p>
<p>Apellido:[apellido]</p>
<p>Edad:[edad]</p>
</body>
</html>
Como puedes ver es bastante simple, y tambien verás que tengo [campos] que son los que vamos a remplazar con los datos que se van a agregar desde la siguiente Pagina aspx:

Ahora en el botón agregamos:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim document = New Document(PageSize.A4, 50, 50, 25, 25)
Dim output = New MemoryStream()
Dim writer = PdfWriter.GetInstance(document, output)
document.Open()
Dim contents As String = File.ReadAllText(Server.MapPath("/HTMLTemplate/Test.html"))
contents = contents.Replace("[nombre]", tx_nombre.Text)
contents = contents.Replace("[apellido]", tx_apellido.Text)
contents = contents.Replace("[edad]", tx_edad.Text)
Dim parsedHtmlElements = HTMLWorker.ParseToList(New StringReader
(contents), Nothing)
For Each var As IElement In parsedHtmlElements
document.Add(TryCast(var, IElement))
Next
document.Close()
Response.ContentType = "application/pdf"
Response.AddHeader("Content-Disposition", "attachment;filename=test.pdf")
Response.BinaryWrite(output.ToArray())
End Sub
Como puedes ver, estamos creando el documento con las dimensiones especificadas en el contructor, luego leemos el contenido del archivo html para finalmente reemplazar el contenido del los campos con [corchetes]. Finalmente escribimos el pdf.

Abrimos y listo!, PDF creado:

Obviamente esto es una simplificación al máximo de lo que se puede realizar , te recomiendo que visites la página del proyecto para muchas más opciones:
http://sourceforge.net/projects/itextsharp/
Saludos!.,
@chalalo
Hola, vamos a seguir revisando este tema de Web API junto con Odata, está vez voy a utilizar una clase para ver algunas potencialidades del sistema de consulta.
Voy a seguir utilizando el ejemplo del artículo anterior, el cual iremos completando poco a poco.
Lo primero que vamos a hacer es agregar una nueva clase al proyecto en la carpeta models:

A esta clase le voy a llamar Asignatura, la cual va a tener la siguiente estructura:
public class Asignatura
{
public int ID { get; set; }
public string Nombre { get; set; }
public int Creditos { set; get; }
public int Semestre { set; get; }
}
A continuación vamos a agregar un controlador específico para esta clase, la cual nos va a proveer del manejo de los HTTP request para esta entidad, vamos a elegir controlador de la API vacío, ya que crearemos a mano las acciones necesarias.

Puedes notar que al agregar el controlador, la clase deriva de APIController, debemos modificar esto a EntitySetController:

Ahora, puede ser que veas que no tienes el ensamblado System.Web.Http.OData , por lo que deberás incluir el ensamblado, yo lo hice mediante Nuget

Podemos crear el endpoint utilizando la clase ODataController directamente, sin embargo EntitySetController maneja los detalles de la creación correcta de las respuesta HTTP en conformidad con OData. Esto nos permetirá centrarnos en el código específico de la aplicación. Lac lase EntitySetController toma dos parámetros de tipo de genérico: El primero es el tipo de la entidad (Asignatura) y el segundo es del tipo clave de la entidad, en nuestro caso , lo definimos con int. El esquema es el siguiente:

Ahora vamos a agregar una lista de asignaturas al controlador:
public class AsignaturaController : EntitySetController<Asignatura, int>
{
static List<Asignatura> asignaturas = new List<Asignatura>()
{
new Asignatura() { ID=1, Nombre="Calculo I", Creditos=6, Semestre=1 },
new Asignatura() { ID=2, Nombre="Algebra I", Creditos=6, Semestre=1 },
new Asignatura() { ID=3, Nombre="Calculo II",Creditos=6, Semestre=2 },
new Asignatura() { ID=4, Nombre="Algebra II",Creditos=6, Semestre=2 },
};
}
Luego veremos un ejemplo con acceso a bases de datos. Para soportar los request GET, que corresponden a lectura general de la colección y la lectura de un objeto en particular de la colección:
public override IQueryable<Asignatura> Get()
{
return asignaturas.AsQueryable();
}
protected override Asignatura GetEntityByKey(int key)
{
return asignaturas.FirstOrDefault(p => p.ID == key);
}
Ahora solo nos faltaría configurar los endpoint, para esto vamos a ir a la carpeta App_start y abrir el archivo WebApiConfig.cs, la cual tiene la configuración del la web api, vamos agregar en el método Register:
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Asignatura>("Asignaturas");
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);
Este código realiza dos cosas:
Crea un Entity Data Model para el Endpoint de Odata
Configura el EndPoint
El EDM es una modelo abstracto de datos, es usado para la creación de la metadata del documento (clase a devolver) para el servicio que creamos.
El método EntitySet agrega la entidad al set EDM:
modelBuilder.EntitySet<Asignatura>("Asignaturas");
El String “Asignaturas” define el nombre del entity Set, el nombre del controlador debe coincidir con el nombre del entity set.
Y ya estamos Listos!, vamos a probarlo con la URL http://localhost:1927/Odata/Asignaturas/
y tenemos:
{
"odata.metadata":"http://localhost:1927/odata/$metadata#Asignaturas","value":[
{
"ID":1,"Nombre":"Calculo I","Creditos":6,"Semestre":1
},{
"ID":2,"Nombre":"Algebra I","Creditos":6,"Semestre":1
},{
"ID":3,"Nombre":"Calculo II","Creditos":6,"Semestre":2
},{
"ID":4,"Nombre":"Algebra II","Creditos":6,"Semestre":2
}
]
}
También podemos probar obteniendo solo un registro con la URL: http://localhost:1927/Odata/Asignaturas(2) y obtendremos:
{
"odata.metadata":"http://localhost:1927/odata/ $metadata#Asignaturas/@Element","ID":2,"Nombre":"Algebra I","Creditos":6,"Semestre":1
}
Como puedes ver consultamos el ID del registro que deseamos con el id entre paréntesis.
Bueno, seguiremos viendo OData con este objeto para que veamos más posibilidades de consulta, espero que te haya servido el artículo!
Saludos,
@chalalo
Hola que tal?, quiero invitarlos a un evento de tipo “conversación” que vamos a dar con el copado Jorge Díaz, sobre Windows Phone 8, el titulo dice mucho del enfoque del evento, vamos a hablar de las ventajas de Windows Phone para escenarios desarrollo (mi aporte) y por su parte Jorge va a estar hablando de la visión de IT, como ven estamos abarcando los dos ámbitos que nos interesan (si, también conversaremos sobre la experiencia de usuario).

Personalmente he desarrollado para blackberry, Android y IPhone, así que podremos establecer comparaciones y compartir experiencias. Eso será el próximo sabado 4 de may0 a las 20:00 horas, es decir es un Saturday Night Webcast 
El Link de la conferencia es:
https://www311.livemeeting.com/cc/mvp/join?id=4GFT4W&role=attend&pw=M*Sk9MMbc
Así que agrégalo en tu agenda
nos vemos por allá.
Saludos,
Gonzalo
Hola, vamos a comenzar una pequeña serie de comenzar a utilizar el protocolo Odata junto a ASP.NET Web API, una combinación realmente potente. Para hacer un poco de memoria, OData es un protocolo abierto que permite tener acceso a un origen de datos, mediante una URL especialmente construida, constituye un enfoque simplificado de como acceder a orígenes de datos remotos. OData usa HTTP ,Atom y JSON, y nos permite a los desarrolladores crear apps que se comunican con variadas fuentes de datos. Lee más sobre este protocolo acá: http://www.odata.org/introduction/
Ahorra bien, ya hemos visto Web API en varias post que puedes encontrar en el siguiente enlace. http://geeks.ms/blogs/gperez/search.aspx?q=web+api
Lo bueno es que el release ASP.NET 2012.2 , agrega el soporte de OData para WebAPI, vamos a comenzar con lo más básico y para entender OData , trabajaremos con la plantilla de Web API que nos provee Visual Studio .
Para realizar el primer ejemplo vamos crear un proyecto de WebApi, para eso elegimos aplicación web de asp.net mvc


Luego vamos a agregar algunos elementos a la colección que ya nos aparece en la acción Get del controlador que crea la plantilla por defecto (ValuesController)
// GET api/values
[Queryable]
public IEnumerable<string> Get()
{
return new string[] { "value0","value1","value2","value3",value4","value5", "value6", "value7", "value8", "value9", "value10" };
}
Fijate que agregué también el atributo Queryable, esto permitirá que podamos hacer las consultas con OData. Si no tienes la referencia la puedes buscar en Nuget o descárgala desde acá:
http://www.nuget.org/packages/microsoft.aspnet.webapi.odata
Ahora ya tenemos algunos elementos más para poder jugar un poco con OData.
Vamos a realizar ejemplos básicos y revisar cual es la respuesta a nuestras peticiones.
Para llamar a la acción por defecto (estoy en mi máquina) hacemos:
http://localhost:1927/Api/Values y el resultado es:

Ahora bien ocupemos un poco más de Odata, si revisar la documentación del core veremos que existen sentencias para hacer querys (revísalas en http://www.odata.org/documentation/odata-v3-documentation/odata-core/#1023_Querying_Collections)
Vamos a ver $top y $skip,la primera nos permite obtener los primeros n elementos de la colección, asi que si hacemos:
http://localhost:1927/Api/Values?$top=2 , el resultado es:

Ahora bien, con $skip no “saltamos” n resultados , asi que si hacemos:
http://localhost:1927/Api/Values?$skip=2

Lo que nos da la pauta para realizar, por ejemplo , paginaciones:
http://localhost:1927/Api/Values?$top=3&$skip=3

Ahora veamos un pequeño ejemplo de como consumir esto con jquery y paginando, voy a tratar de simplificar al máximo el código

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<script src="Scripts/jquery-1.8.2.min.js"></script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script>
$(document).ready(function () {
var skip = 0;
var top = 3;
$("#atras").click(function (e) {
if (skip > 0) {
cargaDatos(skip= skip - top);
}
});
$("#adelante").click(function (e) {
cargaDatos(skip= skip + top);
});
function cargaDatos(skip) {
$("ol").empty();
var url = "$top=" + top + "&$skip=" + skip;
$.getJSON('Api/Values?' + url, function (data) {
$.each(data, function (key, val) {
$("ol").append('<li>' + val + '</li>');
});
});
}
cargaDatos(skip);
});
</script>
</head>
<body>
<h1>Ejemplo con OData</h1>
<button id="atras"><<</button>
<button id="adelante">>></button>
<ol></ol>
</body>
</html>
Como puedes ver hago uso de la función getJSON de jquery para enviarlo los parámetros de skip y top, de manera de ir avanzando el skip para “paginar”. Entonces, cuando se carga por primera vez la página se carga con skip=0 y top=3 , que me posicionan en la primera página, luego cuando presionan el botón adelante o atrás se agrega o disminuye el valor del top. Dentro de la función lo primero que hago es limpiar la lista para que no se vayan agregando los valores a los ya existentes y la variable url nos permite completar la url final que se enviará a la webapi, bastante sencillo!.
Bueno, seguiré con artículos de este tipo, metiéndonos cada vez mas en esta poderosa combinación de asp.net 
Espero que te sirva!
@chalalo
Hola!, esta es la presentación maratónica de tips para el desarrollo de ASP.NET, en donde vimos bastante material y ejemplos:
Puedes descargar también el video de la presentación en el siguiente Link:
http://www.sendspace.com/file/l29gzx
y hacer click en el siguiente gif (estás páginas están llenas de Adds)

Y bajarás 120MB de video
Saludos!
G.
Hola,como te había comentado, son varias las novedades que trae la nueva versión de webmatrix, sobre todo para el trabajo en la nube (más adelante veremos en detalle esto), pero ahora me quiero detener un poco en e soporte para GIT que viene con WebMatrix. Vamos a tener siempre la opción de TFS, en mi caso, tengo GIT instalado en mi equipo, a sí que voy a utilizarlo, vemos en la barra de WM tenemos la opción:

Una vez presionado, vemos que se abren varias opciones:

A simple vista eché de menos el historial de comits,pero bueno , eso puede ir mejorando en el futuro.
Podemos ver los setting de Git:

TAmbién y como era de suponer, podemos crear las Ramas de manera muy sencilla, la estrella al lado del nombre indica el branch activo:

Acá también eché de menos que WebMatrix no indique con el clasico mensaje de que el archivo fue modificado por fuera de la aplicación, también es un punto mejorable, pero sin embargo, es hacer un click más, es decir, la nada misma para el beneficio.

Y obviamente podemos agregar repositorios remotos, de manera de poder hacer extracciones o inserciones en ellos

Para el ejemplo que estaba viendo, ya hice la inserción y ahora esta el archivo de prueba está en mi repositorio (de pruebas) en GitHub 

El historial que te comentaba puede ser remplazado por algo un poco menos organizado, pero útil de todas maneras, que es el log, que te va a mostrar todo lo que ha sucedido con el repositorio:

A mi parecer, cumple su tarea, y me agrada mucho la idea que WebMatrix, que ya me parecía muy potente, ahora vaya a un nuevo nivel con todos las nuevas características, para mi es una herramienta indispensable.
Saludos!
@chalalo

Ya esta disponible para la descarga la versión beta de WebMatrix 3, esta vez con un enfoque mucho más enfocado al desarrollo en la nube, de hecho te pide tus credenciales liveid y puedes acceder a tres meses de desarrollo gratis en la nube
.
Hay excelentes características que entusiasman bastante de esta herramienta que es totalmente gratuita:
Podemos editar remotamente un sitio, desde Windows Azure, o un repositorio de código,lo puedes ver en la siguiente imagen:

Conectarnos a un repositorio Git o TFS, haciendo esta herramienta mucho más poderosa. Con Git tendremos las opciones que necesitamos desde la herramienta, revisa esto acá:

Junto a todas las funcionalidades que esto ya tiene, uff, tremenda herramienta para los developers.
Revisa acá mi post anterior de por que debería interesarte webmatrix:
http://geeks.ms/blogs/gperez/archive/2012/10/29/revisi-243-n-de-por-que-deber-237-a-interesarme-por-webmatrix.aspx
Descárgalo acá:
http://www.microsoft.com/web/webmatrix/next/
Hola!, los quería invitar al siguiente WebCast:
Los 10 mejores trucos para el desarrollo en ASP.NET aprovechando al máximo Visual Studio 2012
 |
Únete a Gonzalo Pérez (Microsoft MVP) en esta sesión online de más de 100 minutos de entrenamiento técnico en donde desclasificaremos los 10 mejores trucos, consejos y demos para desarrolladores de ASP.NET. Te enseñaremos los secretos para optimizar el desarrollo web, acelerar la implementación con Visual Studio 2012 y aprovechar las nuevas características de esta plataforma.
¡Una sesión imperdible!
|
Regístrate acá:
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032546139&Culture=es-CL&community=1
Veremos entre otras cosas:
- SignalR
- Knockout.js + mvvm
- Git + VS2012
- Bundle Scripts
- ASP.NET Web API
- Test de Carga
- Plantillas Api Facebook , Single Page Application
- Visual Studio 2012 Page Inspector
- Productivity Power Tools
- Bing Maps
- CSS Inspector
- Modernizr
- Typescript
Ufff! muchos temas, así que no se lo pierdan, nos vemos ahí!
Saludos,
@chalalo
Hola, vamos a seguir con SignalR, y digo seguir ya que este sería el segundo artículo, el primero lo puedes ver acá http://geeks.ms/blogs/gperez/archive/2013/02/15/tutorial-comenzando-con-signalr-y-razor-view.aspx
Buscando un ejemplo un poco más entretenido que enviar mensajes pensé que hacer una pizarra compartida, utilizando canvas y la posibilidades de signalR era lo adecuado.
La idea, como aparece en la siguiente figura, es crear una pizarra en donde distintos clientes puedan dibujar al mismo tiempo, además de cambiar los colores del trazo.

Backend
Veamos la creación del Backend, el cual está construido como una ASP.NET WEB API muy simple ya que solo es necesario que replique hacia los demás clientes conectados la data que proviene del browser. Esta Data esta constituida por un Trazo que posee muchos puntos, este trazo corresponde a una línea desde el evento mousedown al evento mouseup cuando se está dibujando, veremos como funciona esto después, por ahora lo importante es la estructura que recibe estos datos.
public class Punto
{
public string puntox { get; set; }
public string puntoy { get; set; }
public Punto(string puntox, string puntoy)
{
this.puntox = puntox;
this.puntoy = puntoy;
}
public Punto()
{
}
}
Y la Clase Trazo:
public class Trazo
{
public string color { get; set; }
public List<Punto> puntos { get; set; }
public Trazo(string color)
{
this.color = color;
}
public Trazo()
{
}
}
Ahora revisemos la clase DibujoConn, que se encarga de manejar las peticiones desde el cliente, solo voy a utilizar los métodos onConnected y onReceived para simplificar al máximo el ejemplo:
public class DibujoConn : PersistentConnection
{
protected override Task OnConnected(IRequest request, string connectionId)
{
return Connection.Broadcast(new Trazo("0"));
}
protected override Task OnReceived(IRequest request, string connectionId,
string data)
{
Trazo trazo = JsonConvert.DeserializeObject<Trazo>(data);
return Connection.Broadcast(trazo);
}
}
Como se puede ver, cuando se establece la conexión se devuelve un nuevo trazo con valor 0 en el color, esto lo utilizo para indicarle al cliente que no es un trazo válido , solo una conexión del usuario.
Cuando se recibe datos desde el cliente, se deserializa, se asigna a un objeto trazo y de devuelve a los clientes.
Luego debemos agregar en el global Asax el endpoint:
RouteTable.Routes.MapConnection<DibujoSignalR.Dibujo.DibujoConn>("dibujo", "/dibujo");
Front-End
Estamos con Razor View, por lo que podemos utilizar sus bondades, voy a utilizar el archivo _Layout.cshtml para definir lo necesario.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
@RenderBody()
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
@Scripts.Render("~/bundles/jquerysignalr")
@RenderSection("scripts", required: false)
<script type="text/javascript">
inicializar();
</script>
</body>
</html>
El archivo Index.cshtml que utiliza este layout es el que contiene el canvas para el dibujo:
@{
ViewBag.Title = "Pizarra";
}
<h2>Pizarra - Chalalo Land</h2>
<div id="contenedor">
<div id="no_html5">
<h2>Tu navegado no soporta Canvas-HTML5</h2>
</div>
<div id="contenedor_pizarra">
<canvas id="pizarra" width="600px" height="500px"></canvas>
<br />
<a href="BLOCKED SCRIPTborrar()" id="borrar_bt">Borrar Pizarra</a>
</div>
</div>
<div id="botones">
<div class="paleta">
<button class="boton" id="Black">Negro</button>
<button class="boton"id="Red">Rojo</button>
<button class="boton"id="Green">Verde</button>
<button class="boton" id="Blue">Azul</button>
<button class="boton" id="White">Goma</button>
</div>
</div>
@section Scripts { <script src="~/Scripts/pizarra.js"></script> }
Veamos el archivo pizarra.js que se lleva el peso del funcionamiento, puse la explicación en comentarios:
var pizarra_canvas;
var pizarra_context;
/*Definir el objeto trazo*/
var trazo = {
"color": "#000",
"puntos": []
};
/* Inicializa y determina si el navegador soporta html5- canvas*/
function inicializar() {
if (!Modernizr.canvas) {
document.getElementById("contenedor_pizarra").style.display = "none";
} else {
/* Se establece el ancho de Linea y los Listener para cuando se presiona el mouse
*/
document.getElementById("no_html5").style.display = "none";
pizarra_canvas = document.getElementById("pizarra");
pizarra_context = pizarra_canvas.getContext("2d");
pizarra_context.lineWidth = 3;
pizarra_canvas.addEventListener("mousedown", empezarPintar, false);
pizarra_canvas.addEventListener("mouseup", terminarPintar, false);
/* Este código es para cambiar el color de la linea con respecto a
el botón presionado, el botón tiene su color en el Id, por lo que se
asigna a la propiedad de la linea*/
$(".boton").click(function () {
pizarra_canvas = document.getElementById("pizarra");
pizarra_context.strokeStyle = this.id;
color = this.id;
});
/*Esto es implemente para darle el color al botón*/
$(".boton").each(function (index) {
$(this).css("background-color", this.id);
});
}
}
/*En esta función se almacena el primer punto (posición)con el
que se comenzará a pintar */
function empezarPintar(e) {
pizarra_context.beginPath();
var puntox = e.clientX - pizarra_canvas.offsetLeft;
var puntoy = e.clientY - pizarra_canvas.offsetTop;
pizarra_context.moveTo(puntox, puntoy);
pizarra_context.stroke();
pizarra_canvas.addEventListener("mousemove", pintar, false);
trazo.puntos.length = 0;
var punto = {
"puntox": puntox,
"puntoy": puntoy
};
trazo.puntos.push(punto);
}
/* Al terminar de pintar, se envía la información (color y trazos) mediante la conexión que provee signalr a la web api,*/
function terminarPintar(e) {
pizarra_canvas.removeEventListener("mousemove", pintar, false);
var conn = $.connection("/dibujo");
trazo.color = pizarra_context.strokeStyle;
conn.start()
.promise()
.done(function () {
conn.send(JSON.stringify(trazo));
});
}
/* Esta función genera los puntos del trazo, cada uno se va guardando
en la conexión de puntos del trazo para luego transmitirse */
function pintar(e) {
var puntox = e.clientX - pizarra_canvas.offsetLeft;
var puntoy = e.clientY - pizarra_canvas.offsetTop;
pizarra_context.lineTo(puntox, puntoy);
var mipunto = {
"puntox": puntox,
"puntoy": puntoy
};
pizarra_context.stroke();
trazo.puntos.push(mipunto);
}
function borrar() {
pizarra_canvas.width = pizarra_canvas.width;
pizarra_context.lineWidth = 3;
}
$(function () {
var conn = $.connection("/dibujo");
/*Esta es la función que recibe el trazo de todos los clientes conectados. El objeto trazo contiene el color y los puntos, los que se recorren medianteun ciclo for para dibujarlos en pantalla*/
conn.received(function (data) {
if (data.color != "0") {
pizarra_context.beginPath();
pizarra_context.moveTo(data.puntos[0].puntox , data.puntos[0].puntoy);
pizarra_context.strokeStyle = data.color;
for (var i = 1; i < data.puntos.length; i++) {
pizarra_context.lineTo(data.puntos[i].puntox , data.puntos[i].puntoy );
pizarra_context.stroke();
}
}
});
conn.error(function (error) {
console.warn(error);
});
conn.start();
});
Veamos un video de lo que se puede conseguir con este código, el nivel de abstracción que nos permite signalR es simplemente genial.
Ahora si quieres descargar el ejemplo:
Espero que te sirva:
@chalalo
Hola, en este Post vamos a ver como utilizar Nuget para crear paquetes de con la personalización de un tema para jQueryMobile mediante ThemeRoller.
Lo primero que vamos a hacer es crear un repositorio local en donde vamos a almacenar nuestros paquetes, para esto vamos a ir a HERRAMIENTAS->Administrador de paquetes de biblioteca->Configuración del Administrador de paquetes

Luego podemos agregar nuestro propio repositorio en mi caso hice una carpeta en C:\MyNugetPackages

Tengo creado un proyecto de MVC 4 – Aplicación Móvil,

Esta plantilla tiene jqueryMobile para el render estilo móvil, si pruebo la app mediante el emulador para IPhone que se integra con VS2012, si no lo tienes instalado, puedes hacerlo seleccionando la opción “Más Emuladores” o pueden ir directamente a la siguiente dirección:
http://visualstudiogallery.msdn.microsoft.com/6bed5adb-1d6a-483d-9e22-ae0f88ec4477

Al ejecutar nuestro proyecto MVC veremos lo siguiente:

Ahora a crear nuestro Tema con Themeroller, Ojo, ir a la siguiente URL, no a la que está en la página de jQueryMobile, ya que esta última no tiene la opción de descargar el tema para Nuget:
En el voy a crear mi tema que le llamaré de manera muy original “Verde”:

Ahora vamos a la opción:

Ahora podemos ver la opción Download NuGet:

Entonces guardo el archivo como verde.nupkg en la carpeta C:\MyNugetPackages. Paso siguiente voy a la consola de Nuget, elijo mi repositorio e instalo el paquete, o también lo podemos hacer de manera gráfica mediante el administrador de paquetes:

A continuación veremos que nuestro tema ya está instalado:

Ahora voy a agregar el CSS, al archivo _Layout, para este ejemplo , solo voy a arrastra el archivo para hacer la referencia, pero luego puedes utilizar la característica de utilizar bundle en los css y js.

Y al ejecutar el proyecto nuevamente vemos el tema ya aplicado 

Espero que te sirva
@chalalo
Hola que tal, en este tema veremos como comenzar a utilizar GIT con Visual Studio 2012, primero que nada tenemos que instalar los siguientes componentes en orden:
- Visual Studio 2012 Update 2 CTP 3
- Visual Studio Tools for Git
Recuerda que el VS2012 Update 2 CTP 3 no es un producto final, por lo que queda a tu responsabilidad el utilizarlo.
Bueno, una vez instalado vas a poder seleccionar dentro de la opción se Elegir control de código fuente a Git:

Previamente yo ya tenía instalado Git para Windows y un par de repositorios, también tenía mi cuenta en GitHub para el repositorio remoto, el plugin se configuró automáticamente, si no puedes hacerlo de manera manual, incluso tiene la opción para obtener tu imagen desde gravatar:

También puedes ver la lista de repositorios locales y conectarte a uno, clonarlo , agregar , etc. Un punto importante es que como puedes ver, se conecta a TFS

Ahora vas a tener la opción Commit al seleccionar el menú contextual en el Solution Explorer:

Veremos a continuación en la ventana de Team Explorer la información actual del proyecto, con los branch asociados (que se pueden crear previamente en esta misma ventana), puedes agregar el mensaje del Commit, (para que te ubiques dentro de todos los commits). En mi caso tengo dos Branch (ramas) , la master y la BugFix, puedes cambiar rápidamente entre cualquiera de estas dos, crear nuevas, hacer el merge, hacer el pull, push, incluir o excluir archivos en el commit, como vez, prácticamente todas las acciones recurrentes cuando utilizamos el bash de Git.

Puedes configurar el repositorio remoto, en mi caso GitHub, publiqué los branch locales y funciona sin problemas, de inmediato te pide tus credenciales y listo, ya estaban reflejados los cambios en mi repositorio :
Puedes ver la historia de los archivos en el repositorio:

También podemos ver las diferencias de un archivo entre los distintos commits:

Una de las ventajas principales con Git con otras controles de código , es que podemos crear branch y cambiarnos rápidamente entre ellos sin tener conexión con el repositorio remoto, por ejemplo podemos crear nuevas branch, recorrerlos , hacer merge y estar en un avión sin conexión
.
Si quieres saber a fondo sobre GIT, te recomiendo que leas este tutorial (personalmente me lo leí y es muy bueno)
http://git-scm.com/book/es <- Léelo si o si!
Saludos!
@chalalo
Hola!!, estuve un poco ausente de blog por temas de vacaciones , jejee, todos necesitamos un descanso, pero ya estamos de vuelta , esta vez quiero mostrar un ejemplo de SignalR utilizando las características de Razor engine.
Primero que nada, te recomiendo ver los siguientes artículos sobre SignalR, me fueron de gran ayuda para comprender los fundamentos de SignalR
Paso siguiente de haber leído los artículos veamos como realizar una implementación , con lo denominado “Conexiones Persistentes” (si no conoces el término, revisa el primer artículo).
La idea del proyecto a realizar es un backend (server) que va a enviar mensajes a distintos clientes, el server debe poder ver cuando se conecta y desconectan los clientes:

Vamos a comenzar entonces con la creación de un proyecto de ASP.NET Web API, luego vamos a obtener los archivos necesarios desde el NuGET, recuerda seleccionar la opción “Incluir versión previa” ya que este paquete, a la hora de escribir este artículo se encuentra en RC. Luego buscas signalR y elijes “Microsoft ASP.NET SignalR”

Como voy a usar serialización JSON y quiero compatibilidad con versiones de IE más antiguas, voy a agregar la librería JSON2

Una vez con esto instalado, voy a crear una carpeta Mensaje en donde voy a tener el objeto mensaje, que será pasado entre el cliente y el servidor, además la clase MensajeConn que implementa la comunicación.
El mensaje es bastante sencillo, solo consta de un titulo y un texto, justo lo necesario para el ejemplo 
| Estructura de la solución | Clase Mensaje |
 | using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace SignalDemo1.Mensaje { public class Mensaje { public string Titulo {get;set;} public string Texto{get;set;} public Mensaje(string titulo,string texto){ this.Titulo = titulo; this.Texto = texto; } public Mensaje() { } } } |
Ahora veamos la clase MensajeConn:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SignalDemo1.Mensaje
{
public class MensajeConn : PersistentConnection
{
protected override Task OnConnected(IRequest request,
string connectionId)
{
Mensaje mensaje = new Mensaje("Servidor", "Nueva Conección " +
connectionId);
return Connection.Broadcast(mensaje);
}
protected override Task OnReceived(IRequest request,
string connectionId, string data)
{
Mensaje mensaje = JsonConvert.DeserializeObject<Mensaje>(data);
return Connection.Broadcast(mensaje);
}
protected override Task OnDisconnected(IRequest request,
string connectionId)
{
Mensaje mensaje = new Mensaje("Servidor", "Desconectado " +
connectionId);
return Connection.Broadcast(mensaje);
}
}
}
Importante es notar esta clase hereda de la clase abstracta PersistentConnection que nos brindará la posibilidad de sobrescribir los métodos para la interacción de mensajes.
Es necesario revisar la documentación oficial de SignalR para que veas las posibilidades de sobre escritura de métodos y el uso que podemos darle, revisa el siguiente link:
https://github.com/SignalR/SignalR/wiki/PersistentConnection
En mi caso, solo quiero ejecutar acciones cuando un cliente se conecta, cuando se desconecta y cuando se envía un mensaje hacia los clientes).
Para la conexión y desconexión simplemente envió un mensaje simple junto al connectionId, el cual identifica únicamente la conexión (luego con esto podemos enviar mensajes a clientes en particular)
El método OnReceived permitirá recibir un objeto serializado con JSON y enviar con el método Broadcast a todos los host conectados.
Paso siguiente, y no olvidar, ya que si no, no va a funcionar la conexión (error 404 al momento de tratar de conectarse el cliente js hacia el servidor) es definir en el global.asax la definición del endpoint:
RouteTable.Routes.MapConnection<Mensaje.MensajeConn>("mensaje", "/mensaje");
Un poco de Razor View, Blundes y esas hiervas.
Ya definimos el funcionamiento deseado para la comunicación, ahora veamos algunas cosillas que nos simplificarán la vida en las vistas.
Para la implentación en el cliente debemos agregar dos archivos JS que fueron agregados al proyecto por nuget, ahora con la posibilidad en asp.net 4.5 de hacer bundle (unir,combinar) script para disminuir las llamadas al server, vamos a definir en nuestro archivo blundleConfig:
bundles.Add(new ScriptBundle("~/bundles/jquerysignalr").Include(
"~/Scripts/json2.js",
"~/Scripts/jquery.signalR-{version}-rc2.js"));
Con esto unimos en un solo archivo que se llamará jquerysignalr, los archivos json2 y jquery.signalR-1.0.0-rc2.
Si quieres saber más sobre el tema de combinación y minificación de scripts y css revisa:
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
Interfaz de Usuario
Una de las varias ventaja que tiene Razor es su simpleza, si bien acá no tenemos masterPages propiamente tal, podemos definir la estructura de todas las páginas en nuestro archivo _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
@RenderBody()
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
@Scripts.Render("~/bundles/jquerysignalr")
@RenderSection("scripts", required: false)
</body>
</html>
Como vemos incluimos los scripts según el nombre dado en el archivo BundleConfig. Luego un Rendersection para incluir la sección de script propios del comportamiento que queremos lograr en el cliente.
Básicamente tengo dos vistas en el cliente, Envia.cshtml , que hace de backend, en el cual puede visualizar cuando se conecta y desconecta un cliente y Recibe.cshtml , que recibe los mensajes que envía el backend.
Estructura de Envia.cshtml.
@{
ViewBag.Title = "Envia Mensajes";
}
<h2>BackEnd - Enviar Mensajes</h2>
<h2>Mensaje</h2>
@using (Html.BeginForm()) {
@Html.EditorForModel();
<input id="send" value="Enviar Mensaje" type="button" />
<ul id="mensajeBackEnd" style="list-style:none;"></ul>
}
@section Scripts { <script src="~/Scripts/MensajeSignalR.js"></script> }
Como ves estoy utilizando el helper que a partir del modelo devuelto en el controlador hacia la vista, que permitirá el render del formulario, ahorrándonos el esfuerzo de construirlo, luego un botón para enviar los datos del formulario y una lista en donde se imprimirán los mensajes de conexión o desconexión de los clientes. La UI queda de esta forma:

Estructura de Recibe.cshtml.
Esta vista es mucho más simple, solo tiene la lista para recibir los mensajes:
@{
ViewBag.Title = "Recibe Mensajes";
}
<h2>Cliente - Ver Mensajes</h2>
<ul id="mensajeClient" style="list-style:none;"></ul>
@section Scripts { <script src="~/Scripts/MensajeSignalR.js"></script> }

Recordar que tenemos que agregar las acciones en el controlador definido por defecto HomeController:
public ActionResult Recibe()
{
return View();
}
public ActionResult Envia()
{
var vm = new Mensaje.Mensaje();
return View(vm);
}
Acá ves como se le devuelve a la vista el modelo para que el helper html para crear el formulario pueda hacer el render. Ahora veamos el archivo MensajeSignalR.js, el cual nos da la funcionalidad en el lado del cliente.
$(function () {
var conn = $.connection("/mensaje");
conn.received(function (data) {
if (data.Titulo == "Servidor") {
$("#mensajeBackEnd").append("<li>" + data.Titulo + ':' +
data.Texto + "</li>");
} else {
$("#mensajeClient").append("<li>" + data.Titulo + ':' +
data.Texto + "</li>");
}
});
conn.error(function (error) {
console.warn(error);
});
conn.start()
.promise()
.done(function () {
$("#send").click(function () {
var pTitulo = $("#Titulo").val();
var pTexto = $("#Texto").val();
conn.send(JSON.stringify({ Titulo: pTitulo, Texto: pTexto }));
})
});
});
Como puedes ver , tenemos la función de recibir información “received” dependiendo el titulo decidimos donde imprimir el mensaje (servidor o cliente).
Cuando se inicia una conexión “start”, utilizamos la función promise() de jquery para asegurarnos que la llamada asíncrona se ejecute, si quieres saber más sobre esta función revisa este artículo: http://www.funcion13.com/2012/03/26/comprendiendo-promesas-y-deferreds-en-jquery/. Se presiona el botón (send), y utilizamos el helper JSON para serializar el mensaje.

Funciona perfecto!, más adelante voy a subir otras demos con Hub y algunas un poco más avanzadas.
Puedes descargar la demo completa acá:
Saludos!
@chalalo
Hola, ayer di un WebCast sobre MVVM y Knockout.js, utilizando webmatrix, básicamente repasé y expliqué lo que habíamos visto en este blog, de todas maneras te dejo el video de la grabación.
Los ejemplos están todos disponibles en los artículos sobre el tema que están en el blog. Te dejo la URL
http://geeks.ms/blogs/gperez/archive/2012/09/21/tutorial-comenzado-con-mvvm-y-knockout-js-parte-5-conectar-el-viewmodel-con-el-model-mediante-asp-net-webmatrix-amp-razor.aspx
Saludos!
@chalalo
Hola, como lo había prometido, les dejo el material del WebCast sobre introducción a ASP.NET Web API y mongoDB, una visión pragmática. La idea fue crear una webapi que se consumiera desde Android, Windos Phone y HTML c/jQuery. El esquema es el siguiente:

Descarga acá el archivo, contiene:
- Proyecto para Windows Phone 8
- Proyecto para Android (Necesario Eclipse)
- Proyecto para Asp.NET Web API, incluye CRUD jQuery y código para acceso MongoDB
Espero que te sirva y te animes a crear tus API’s. Cual duda me la puedes hacer a mi twitter @chalalo.
Saludos!
Hola que tal? , por acá de nuevo , entre los trabajos de la maestría que estoy haciendo, el laburo, los proyectos freelance, los estudios me han tenido bastante ocupado, pero siempre hay tiempo para un tip 
Una de las características que encuentro muy útil en VS2012 es la posibilidad de crear test de carga. Para crear una prueba de carga tenemos que ir Archivo > Nuevo Proyecto, y seleccionamos “Proyecto de prueba de carga y rendimiento web”

Ahora vamos a ver un entorno para la creación de las pruebas. En el explorador de soluciones vamos a apretar botón derecho y elegimos agregar>prueba de rendimiento web…

Debería abrirse Internet Explorer con la grabadora de prueba web activada:

Si no aparece esta opción es por que tienes el complemento Microsoft Web Test Recorder deshabilitado, por lo que tienes que habilitarlo para que funcione.

Luego agregamos la URL por ejemplo www.microsoft.com

Luego simplemente presiona Detener y se va a ejecutar el WebTest, en realidad este no es lo que andábamos buscando si no que nos sirve para crear los loadtest. Cuando presiones detener, vas a ver la siguiente ventana, en donde se procesan los parámetros dinámicos.

Con este WebTest podemos realizar pruebas de rendimiento, en donde podemos utilizar distintas configuraciones de browsers, por ejemplo puedes elegir un smartphone de manera de determinar como se comportan las peticiones desde un móvil.

Ahora vamos crear el test de carga, para eso vamos de nuevo al explorador de soluciones y agregamos un test de carga:

Se abrirá un asistente bastante potente, en donde podemos elegir muchas características para crear un test de carga personalizado:

Podemos simular un modelo de carga simulada, contante o cantidad de usuario en intervalos de tiempo por paso.

Podemos hacer una combinación de pruebas a partir de los WebStest que antes habíamos creado, en mi caso seleccione el WebTest2 que fue el que creamos inicialmente:

Luego podemos elegir el tipo de conexión de los clientes:

También podemos configurar el tipo de explorador

Luego podemos establecer la duración de la carga:

Y listo, ahora ejecutamos el test y comenzamos a recibir los resultados!! 

Y Listo! se que son varios pasos, pero esto es muy útil, ahora mismo me ha tocado realizar pruebas de carga a algunas páginas y está herramienta me ha venido de perilla!!
Saludos!
@chalalo
Más artículos
Página siguiente >