May 2011 - Artículos

Buenas!

Recién realizado el WebCast para AUGES, os comento que he subido el material (el código del proyecto que hemos hecho) en mi skydrive.

Al final diría que no ha estado mal, aunque ahora en retrospectiva se sacan algunas conclusiones…

  1. Sigo sin aclararme con lo de compartir elementos en Live meeting… ahora se ven, ahora no, ahora cambia él, ahora no… Al final tuve que ir compartiendo el escritorio entero, que es lo único que al parecer funciona bien (o yo se hacer, que todo podría ser :p).
  2. A ver si Microsoft mejora el Live meeting… No por lo de compartir sino porque me dejó sin sonido. A ver si ahora que tienen Skype mejora eso un poco, porque no entiendo como el producto puede ser tan, tan y tan malo. No es la primera vez que “me peta” el sonido o bien me desconecta o cualquier cosa rara. Lo peor es que no avisa ni nada de que el sonido “se ha ido”: tienes que desplegar el menú de sonido y entonces sí que te dice que algo ha ido mal y no tienes sonido, en fin…
  3. Sobre la exposición, pues en general creo que fue bien, aunque ahora un día después, habría alguna cosas que cambiaría, y de hecho seguramente haré algun post para aclarar algo que igual no comenté del todo, o pasé demasiado de puntillas por él.

Bueno! Basta de quejas, jejejeee… os dejo el enlace al código fuente. Es un zip con el powerpoint y dos soluciones de VS2010, una con el proyecto “al inicio” y otra con el proyecto finalizado. Destripadlas a gusto, y recordad que es un código de demo! :) (esto es un disclaimer para que me perdonéis cualquier barbaridad que veais, jajajajaaa…)

Si después de ver el webcast os queda alguna duda, os animo a que la pongáis aquí, o bien contacteis conmigo (mandadme un mail o un twitter) y trataré de responderos lo buenamente que pueda!

Y por supuesto: animaros a participar en AUGES, a través la página web, de facebook, de twitter o de Linkedin! Se trata de que todos compartamos, discutamos, hablemos (y algún dia nos tomemos algunas cervecitas)!

Finalmente, muchas gracias a todos por asistir al Webcast, para mi ha sido un auténtico placer!

Un saludo!

PD: Ah sí! El enlace: http://cid-6521c259e9b1bec6.office.live.com/self.aspx/BurbujasNet/ZipsPosts/AUGES%20-%20Un%20paseo%20por%20MVC.zip

con no comments
Archivado en: ,,

En el grupo de linkedin de AUGES, en uno de los debates que tenemos abierto, Javier Giners pregunta estrategias de migración de Webforms hacia ASP.NET MVC. Yo le responde que depende de como esté arquitecturada la aplicación pero que tenga presente que ASP.NET MVC y webforms pueden convivir juntos en una misma aplicación web. No se trata de que una aplicación web hecha en webforms se comunique fácilmente con otra hecha en ASP.NET MVC no. Se trata de que ambas tecnologías pueden combinarse para crear una sola aplicación web.

Y ese es el objetivo de este post ;-)

1. En el inicio sólo existía webforms

Para este post he empezado por desarrollar una aplicación webforms. Es muy chorra, lo único que tiene es una página con una grid que a través de un LinqDataSource se conecta a una base de datos y muestra los datos de una tabla (llamada en un alarde de originalidad “Datos”).

No voy a comentar nada del proyecto Webforms, al final del post hay el enlace para que os lo descarguéis, pero ya veréis que es muy simplón. Esta es una captura de pantalla:

image

Fijaos que la URL termina en .aspx (es un Webform) y también que hay usuario registrado. La configuración de seguridad en web.config está:

<location path="VerDatos.aspx">
<system.web>
<authorization>
<deny users ="?" />
</authorization>
</system.web>
</location>

Vamos, que todo permitido excepto VerDatos.aspx que sólo lo pueden ver usuarios registrados.

Y listos, ya tenemos una aplicación webforms!

2. Preparando la entrada de MVC

Empieza el show. Ahora queremos implementar el método de dar de alta un usuario, y para ello queremos que la funcionalidad de introducir un dato nuevo, esté hecho en ASP.NET MVC.

Lo primero es modificar el web.config para “añadir soporte” a ASP.NET MVC. Si estáis en VS2010 no necesitás hacer mucha cosa, copiar apenas tres pedacitos.

El primer pedacito es para añadir las referencias a los assemblies propios de ASP.NET MVC. Se debe poner dentro del tag <compilation>:

<!-- 1: Añadimos assemblies que se usan en ASP.NET MVC -->
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>

El segundo pedazo de código es para registrar los namespaces propios de ASP.NET MVC. Para ello dentro de la etiqueta <system.web> que cuelga directamente de <configuration> ponemos:

<!-- 2: Registramos namespaces de ASP.NET MVC -->
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>

Y finalmente sólo nos queda añadir las referencias a ASP.NET MVC en el proyecto. Para ello le dais a Add Reference –> Browse y donde tengáis ASP.NET MVC3 instalado y añadís la referencia a System.Web.Mvc.dll (Si quereis usar Razor también podemos añadir la referencia a System.Web.WebPages.dll).

3. Inicializando ASP.NET MVC

Para inicializar ASP.NET MVC es muy sencillo, basta con añadir algunas líneas en Global.asax.cs:

private void MvcInit()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", "{controller}/{action}/{id}",
new {action = "index", id = UrlParameter.Optional});
}

Y añadir la llamada a ese método MvcInit() dentro del Application_Start.

Con eso ya tenemos ASP.NET MVC inicializado dentro de nuestro proyecto webforms Y hemos dado de alta las rutas estándard de ASP.NET MVC. Si ahora ejecutamos de nuevo vemos que todo sigue funcionando.

Nota: ¿Te sorprende que siga funcionando todo? Ahora ya tenemos ASP.NET MVC y las URLs de tipo /controlador/acción ya están habilitadas gracias a la tabla de rutas. Si conoces algo de ASP.NET MVC igual te preguntas: si ya tenemos URLs bonitas… cómo es que siguen funcionando las URLs que terminan con .aspx?

La respuesta es muy sencilla: Las rutas, en principio, no se aplican si existe un fichero físico que coincida con la URL. La razón no es facilitar la interoperabilidad con webforms (aunque ayuda), la razón es mucho más simple: Si no fuese así, deberíamos crear controladores para devolver imágenes, css, ficheros javascript y multitud de elementos estáticos más.

Así pues recuerda: Si existe un fichero en la ruta física que indica la URL, las rutas no se tienen en cuenta (a menos que se indique lo contrario). Es por eso que ahora una URL /VerDatos.aspx nos funciona, porque tenemos un fichero físico llamado VerDatos.aspx en la raíz de la aplicación web.

4. Creando un controlador y una vista

Bueno… ahora ya podemos crear el controlador. Dado que partimos de un proyecto de Webforms no tenemos el soporte de tooling de Visual Studio disponible (no hay el menú “Add Controller” p.ej.). Por suerte añadirlo es muy simple.

Para ello abrimos el fichero .csproj con un editor de texto y busca el tag <ProjectGuids>. En mi caso tenía ese valor:

<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

Estos GUIDs son los que indican el tipo (o tipos) del proyecto y por lo tanto indican que herramientas aplica Visual Studio. Como no sabía el GUID de un proyecto de ASP.NET MVC3, cree uno de vacío y miré esa misma línea. En el caso de ASP.NET MVC3 el valor de ProjectTypeGuids es:

<ProjectTypeGuids>{E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

Veo que de los tres GUIDs que hay en la segunda línea, dos son los mismos que antes y que hay uno de nuevo ({E53F8FEA-EAE0-44A6-8774-FFD645390401}), así que simplemente copio el GUID nuevo en la etiqueta ProjectTypeGuids del .csproj de Webforms.

¡Y voilá! Ya tenemos el tooling de VS2010 en nuestro proyecto webforms!

Nota importante: El orden de los GUIDs dentro de ProjectTypeGuids parece que importa! El GUID “nuevo” (el que hemos copiado del proyecto MVC3 al de Webforms) tiene que estar en la primera posición. Si no está en la primera posición no podréis abrir el proyecto en VS2010!

Ahora añadimos manualmente las carpetas Controllers y Views. Una vez creada ya podemos añadir el controlador. En este caso vamos a añadir un controlador para añadir datos nuevos:

public class DatosController : Controller
{
public ActionResult Add()
{
return View();
}

[HttpPost]
public ActionResult Add(DatosViewModel datos)
{
if (ModelState.IsValid)
{
using (var database = new DatosDataContext())
{
var nuevoDato = new Dato();
nuevoDato.id = datos.Id;
nuevoDato.nombre = datos.Nombre;
nuevoDato.twitter = datos.Twitter;
database.Datos.InsertOnSubmit(nuevoDato);
database.SubmitChanges();
}
return Redirect("/");
}
else
{
return View();
}
}
}

DatosViewModel es una clase que me he creado yo, que me servirá para hacer binding de los datos que entre el usuario:

public class DatosViewModel
{
public int Id { get; set; }
public string Nombre { get; set; }
public string Twitter { get; set; }
}

Ahora toca crear la vista de alta. Antes que nada nos toca crear la vista Layout (la equivalente de la master en Razor).

Nota: Podríamos usar el View Engine de aspx para reutilizar la master. Pero vamos a ver como hacerlo en Razor, porque (en mi opinión) Razor es una mejora sustancial respecto el View Engine de aspx.

Podemos crear un página de Layout y establecerla en cada vista (lo mismo que hacemos en el caso de webforms o el view engine de aspx) o bien podemos no establecer el Layout en cada vista y hacerlo a través del _ViewStart.cshtml (que se ejecuta antes de ejecutar cada vista).

Creamos un archivo llamado _ViewStart.cshtml que esté en /Views y que tenga el código:

@{
Layout = "~/Views/Shared/Layout.cshtml";
}

Con eso establecemos /Views/Shared/Layout.cshtml como la página de layout de todas nuestras vistas.

Ahora podemos crear la página (Add New Item –> MVC3 Layout Page (Razor)). El código que VS2010 nos genera por defecto ya es suficiente:

<!DOCTYPE html>

<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

Recordad de guardar esa vista en /Views/Shared con el nombre de Layout.cshtml.

Ahora ya podemos añadir nuestra vista. Añadimos una vista llamada “Add” que esté en /Views/Datos. En mi caso he creado la vista con esos parámetros:

image

Y el código que por defecto genera VS2010 ya es suficiente ;-)

Ahora ya podemos probarlo, a ver que tal… Para ello, el Webform VerDatos.aspx tiene al final un <asp:Hyperlink> al que le añado la propiedad NavigateUrl con valor “/Datos/Add”. Ahora ya podemos probarlo!

5. Zas! En toda la boca! :p

Si al probar el proyecto os aparece un error como este:

Compilation Error

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0103: The name 'model' does not exist in the current context
Source Error:

Line 1:  @model WebApp.DatosDataContext
Line 2:  
Line 3:  @{

Tranquilos… es normal.  Nos falta configurar ASP.NET para que use también el motor de Razor. Eso se hace… en el web.config. Pero no en el web.config general, sino en un web.config que esté dentro de /Views.

La forma más rápida de tenerlo es cojerlo de un proyecto nuevo de MVC3 que os creeis, pero si estáis perezoso, este os puede servir (recordad, va en View/web.config):

<?xml version="1.0"?>

<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>

<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>

</pages>
</system.web.webPages.razor>

<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>

<system.web>
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

Si ahora lo probáis el error es otro: un error de compilación de que deberíamos añadir una referencia a System.Data.Linq. Recordad que cuando ASP.NET compila una vista, usa las referencias que esten indicadas en el web.config. Así pues añadimos la siguiente línea dentro del tag <assemblies> del web.config principal:

<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Ok. Ya estamos listos!Ya Aparece nuestra vista Razor.

Para evitar que cualquiera pueda añadir usuarios, recordad de colocar [Authorize] en el controlador! Aunque el login se haya hecho con webforms, como son la misma aplicación, un usuario autenticado en webforms lo está en MVC y viceversa! :D

Por supuesto hay muchos más temas que podríamos tratar, pero al menos espero que este post os sirva para ver que Webforms y MVC van de la mano sin ningún problema!

Un saludo!

PD: Os dejo el código del proyecto en: http://cid-6521c259e9b1bec6.office.live.com/self.aspx/BurbujasNet/ZipsPosts/webformsAndMvc.zip

con 2 comment(s)
Archivado en:

Seguramente la mayoría ya sabréis que gracias al empuje del maestro Luis Ruiz Pavón (que nos ha ido convenciendo a varios), se ha creado AUGES, el grupo de usuarios de ASP.NET de España.

Para mi es un honor y un placer poder formar parte de este grupo, pero todavía es un placer más grande inaugurar la agenda de eventos del grupo. Y como no podía ser de otro modo el evento será un Webcast de ASP.NET MVC. :)

La fecha? El Miércoles 18. La hora? A las 19:30 (hora española peninsular).

La idea es hacer un evento 100% introductorio: explicar que es esto de ASP.NET MVC, ver ejemplos y comentar cosillas básicas. Más adelante ya tendremos tiempo de hacer eventos más hardcore sobre el tema! ;-)

Así que, ya sabes… si has oído a hablar de MVC y quieres ver de que se trata, o si conoces implementaciones de MVC en otros sistemas y quieres ver la de Microsoft, o si simplmente quieres escucharme un rato (mmmm…. :p) pásate por la web de registro y… nos conectamos el miércoles!!

Saludos… y nos vemos! ;-)