Compartir a través de


Migración web

Desplazar su aplicación web desde WebMatrix a ASP.NET MVC 3

Brandon Satrom

Descargar el ejemplo de código

En enero pasado, Microsoft presentó un nuevo modelo de programación para desarrollo web en Microsoft .NET Framework denominado ASP.NET Web Pages. Web Pages, el cual actualmente es compatible de forma predeterminada en WebMatrix (web.ms/WebMatrix), es un modelo de programación centrado en la página que se comporta de manera muy similar a PHP, donde cada página contiene su propia lógica empresarial, acceso de datos y contenido dinámico para representar HTML en el explorador.

Existen varias razones para crear una página web en WebMatrix. Sin embargo, ¿qué pasaría si sabe que querrá optar por Visual Studio en el futuro? ¿Deberá volver a desarrollar el sitio cuando llegue el momento de la migración si ASP.NET MVC 3 es su estado final? Si le preocupa entramparse solo con WebMatrix y Web Pages, sepa que no hay nada que temer.

Web Pages, al ser una parte de la infraestructura base de ASP.NET, se creó teniendo en mente la flexibilidad. Además, si bien no hay limitaciones técnicas en Web Pages que lo pudieran obligar a cambiar a ASP.NET MVC, puede que hayan ocasiones en las que sea razonable para su equipo, producto o compañía.

En este artículo, analizaremos algunas de las razones por las cuales podría querer migrar (y algunas de las razones por las cuales desearía no hacerlo). También discutiré estrategias para cambiar su sitio Web Pages a ASP.NET MVC si desea hacerlo. Revisaremos cómo moverse desde Pages a Views, cómo controlar lógicas comerciales y código auxiliar y cómo introducir Models a su aplicación. Para terminar, analizaremos y mostraremos cómo conservar las URL existentes del sitio mediante enrutamiento y cómo crear compatibilidad para redirecciones permanentes cuando esto sea necesario.

¿Cuándo hacer la migración?

Antes de profundizar en las razones para migrar desde Web Pages a ASP.NET MVC, analicemos algunas razones por las cuales no debiese hacer ese cambio. Para empezar, no debiera cambiar su sitio Web Pages a ASP.NET MVC debido a que le preocupa que no se escale la aplicación. Dado que Web Pages está creado sobre la base de ASP.NET, ofrece varias de las mismas características de rendimiento de las aplicaciones escritas para ASP.NET MVC o Web Forms. Evidentemente, cada tipo de aplicación tiene modelos de ejecución ligeramente distintos, pero no hay nada en ASP.NET MVC de fábrica que lo haga más o menos escalable de forma inherente que una aplicación de Web Pages. La escala y el rendimiento están vinculadas tanto a las decisiones de diseño hechas al crear el sitio como a la infraestructura subyacente escogida.

Tampoco es una buena idea cambiar su sitio Web Pages a ASP.NET MVC debido a que es genial, sexy y es lo que se comenta que está haciendo todo el mundo o sólo porque quiere trabajar con su sitio en Visual Studio. Esto también puede hacerlo con Web Pages. ASP.NET MVC es una opción en arquitectura de aplicaciones web y no es una varita mágica que mejora instantáneamente a su sitio. La migración de Web Pages a ASP.NET MVC es una opción y no una necesidad. Además, si bien Microsoft ha hecho un estupendo trabajo para que la migración sea posible y sin inconvenientes, esto seguirá costándole tiempo, recursos y dinero, tal como lo haría cualquier migración. Por estas razones, es importante asegurarse de que está migrando a ASP.NET MVC por los motivos apropiados.

Una razón válida podría ser debido a que probar las unidades es importante para usted y su equipo. Dado que el modelo de páginas web está centrada en la página, no es posible usar herramientas de prueba de unidad con sitios Web Pages. Todavía es posible realizar pruebas de UI de web (mediante herramientas como WatiN o Selenium), pero no se puede realizar pruebas de unidad en el nivel de código con herramientas como NUnit o MsTest. Si su sitio tuvo un aumento en complejidad y es importante realizar pruebas de unidades, tiene sentido realizar una migración a ASP.NET MVC.

Si prefiere hacer pruebas de unidades en su código, lo más probable es que también prefiera tomar alguna medida de separación de asuntos en sus aplicaciones. Además, si bien es posible crear código limpio y separado mediante elementos auxiliares y archivos de código en Web Pages, el modelo no se presta para esta separación tan naturalmente como ASP.NET MVC. Si le resulta importante la separación de asuntos y desea una arquitectura de aplicación que promueva tal separación, la migración es una alternativa legítima.

Fuera de esas dos, existen otras razones para realizar la migración que dependen del contexto de su sitio u organización. Si tiene un equipo en crecimiento y un sitio que aumenta en complejidad y que necesita funcionalidades empresariales más ricas, entonces lo más prudente sería migrar. La migración también puede ser necesaria con el fin de dar un mejor uso a un ecosistema de desarrollo más rico para cosas como control de fuentes, pruebas de carga, etc.

Preparación para la migración

En este artículo, tomaré la plantilla de sitio de Photo Gallery que se envía con WebMatrix y la haré migrar a ASP.NET MVC. La esencia del proceso de migración consiste en el desplazamiento desde Pages a Models, Controllers y Views, pero necesitamos realizar un poco de trabajo previo antes de llegar a esto.

Dado que estamos detallando en pasos relacionados a la migración manual en este corto artículo, no podremos darle el mismo grado de atención a cada paso. Nuestra finalidad es enfocarnos en los pasos más significativos y al menos mencionar las reflexiones menores. También escogimos omitir elementos que no estén relacionados con la conversión general, tales como los procedimientos recomendadas para acceso de datos, estructuras de ensamblado posibles, la inserción de dependencia y otros elementos de esa clase. Estos son importantes, pero varios de ellos se remiten a asuntos de cultura de programación y preferencias personales

También es importante observar que no estamos haciendo uso de la característica Abrir en Visual Studio en WebMatrix en el desarrollo de este artículo, con lo cual se abrirá el sitio actual como un proyecto de sitio web en Visual Studio. Puede usar esa opción, incluso si decide no migrar a ASP.NET MVC, pero preferimos usar el tipo de proyecto Aplicación web de Visual Studio para ASP.NET MVC, empezando con un sitio web para después hacer migrar todo manualmente.

Así, empezaremos la migración al seleccionar Archivo | Nuevo | Proyecto y seleccionaremos Aplicación web de ASP.NET MVC 3 con la plantilla vacía y usaremos Razor como el motor de vistas predeterminado.

Una vez que tenga la aplicación de objetivo establecida, necesitará realizar algo de trabajo inicial de migración. Este es un detalle de los pasos iniciales:

  1. Agregue cualquier paquete que esté usando de su sitio Web Pages en su sitio ASP.NET MVC mediante NuGet (nuget.org).
  2. Agregue referencias a System.Web.Helpers, WebMatrix.Data y WebMatrix.WebData. Configure todos estos con Copy Local = true en el panel de propiedades.
  3. Mueva los contenidos de _AppStart.cshtml en el método Application_Start de Global.asax. Si bien es posible mover y usar _AppStart tal cual, recomendamos centralizar su lógica en Global.asax con código de inicio ASP.NET MVC ya existente.
  4. Agregue <roleManager enabled=true /> a la sección <system.web> del web.config raíz. La aplicación Photo Gallery usa el nuevo proveedor de pertenencia WebSecurity, que se encuentra en WebMatrix.WebData, por lo que necesitaremos esa entrada en el sitio para que funcione.
  5. Mueva todas las hojas de estilo, los archivos de script y las imágenes a las carpetas Content o Scripts de la aplicación. Actualice cualquier vínculo de recursos de esos archivos a sus nuevas rutas.
  6. Modifique el elemento Route predeterminado en Global.asax para que apunte al controlador Gallery y a la acción Default
  7. Copie la base de datos compacta de SQL que está en la carpeta App_Data en la carpeta App_Data de su sitio. Si está usando otra base de datos para su sitio, agregue esa cadena de conexión al archivo Web.Config de su aplicación.

Cambiar de Pages a Views

Al completar la configuración inicial de su sitio ASP.NET MVC, estará listo para migrar la esencia de su sitio: las Pages. En Web Pages, una página (.[cs/vb]html) contiene marcado, lógica comercial y todos los datos de accesos necesarios para esa página. El componente esencial de su trabajo durante una migración a ASP.NET MVC será separar cada página y dividir sus contenidos en acciones de Controller (lógica empresarial), clases de acceso a datos (acceso a datos) y Views (marcado).

Primero, necesita migrar el diseño de su sitio. Las páginas Layout, de manera similar a las páginas principales de Web Forms y ASP.NET MVC, son archivos que especifican la estructura de diseño del sitio. Tanto Web Pages como ASP.NET MVC 3 (cuando se usa en conjunto con el motor de vistas Razor) usan el mismo subsistema Layout, por lo que esta etapa de la migración debiese ser sencilla. En el sitio de Photo Gallery, el archivo root _SiteLayout.cshtml contiene la estructura del sitio. Copie los contenidos y navegue al sitio ASP.NET MVC. Abra el archivo Layout ubicado en Views/Shared/_Layout.cshtml y pegue los contenidos de _SiteLayout.cshtml.

Al terminar, necesitará realizar un par de cambios menores a _Layout.cshtml. Primero, cambie el vínculo de su hoja de estilo a la nueva ubicación en la aplicación ASP.NET MVC (~/Content/Site.css en lugar de ~/Styles/Site.css). Segundo, necesitará cambiar @Page.Title a @ViewBag.Title. Ambos son objetos dinámicos que contienen visualizaciones u otros datos para las páginas de su sitio y, como podrá adivinar, Page se usa en Web Pages, mientras ViewBag se usa en ASP.NET MVC.

Lo último que necesitará cambiar en _Layout.cshtml debe tenerlo en cuenta para todas las páginas que haga migrar a ASP.NET MVC. Observe que _Layout.cshtml usa llamadas a @Href para insertar URL en la página. Cualquier llamada que haga referencia a contenidos estáticos (scripts, CSS, etc.) puede dejarla sin cambios. Por otra parte, probablemente querrá cambiar todas las llamadas a @Href que apunten a las páginas del sitio. Si bien seguirán funcionando después de concluir la migración, estas apuntarán a URL estáticas. En ASP.NET MVC, se considera un procedimiento más recomendable usar enrutamiento de ASP.NET para crear URL cuando se crean las vistas. Esto tiene como resultado vínculos más limpios y menos frágiles que están atados a sus definiciones de tabla de enrutamiento y no codificados directamente en el sitio.

Por esta razón, deseará modificar cualquier vínculo parecido a los siguientes:

<div id="banner">
  <p class="site-title">
    <a href="@Href("~/")">Photo Gallery</a>
  </p>
...
</div>

En lugar de ellos, usará @Url.RouteUrl o @Url.Action:

<div id="banner">
  <p class="site-title">
    <a href="@Url.Action("Default", "Gallery")">Photo Gallery</a>
  </p>
...
</div>

Una vez que haya movido su diseño de sitio, podrá empezar a migrar desde Pages a Views. Si tiene en su aplicación de Web Pages alguna página .cshtml que se esté ejecutando por llamadas de RenderPage, muévalas a Views/Shared en el caso de páginas de todo el sitio o en la subcarpeta de Views adecuada para páginas compartidas por un controlador, como es el caso de Account. Cada página que llame a una de las siguientes páginas parciales se debe actualizar para que refleje la nueva ubicación.

Todas las páginas restantes se deben mover a Views y se deben organizar por carpetas según Controller. Dado que el sitio Web Pages no maneja el concepto de Controller, deberá introducir los controladores durante la migración. Lo bueno es que se trasluce alguna clase de estructura de Controller en la aplicación Photo Gallery, lo que ilustra un procedimiento recomendable a seguir en sus sitios.

Por ejemplo, la plantilla de sitio Photo Gallery usa las siguientes carpetas para agrupar páginas: Account, Gallery, Photo, Tag y User. Cada carpeta contiene páginas que habilitan alguna funcionalidad relacionada a tal agrupación. Por ejemplo, la carpeta Account contiene páginas para iniciar y cerrar sesión en el sitio y para registrar usuarios. La carpeta Gallery contiene una página de listado de galería, una página para agregar una nueva galería y una página para visualizar fotos en una galería. Las carpetas restantes están organizadas de forma parecida. Si bien esta estructura no es necesaria en sitios Web Pages, ella permite una migración más sencilla a ASP.NET MVC. En este caso, cada carpeta se asigna a un Controller y cada archivo .cshtml se asigna a una Action y View de forma sencilla.

Empecemos moviendo la carpeta Account y sus tres páginas; Login, Logout y Register; en la aplicación ASP.NET MVC en el directorio Views. En términos de ASP.NET MVC, las Pages se volverán Views instantáneamente según la naturaleza de su ubicación en la aplicación. Sin embargo, aún no está listo, puesto que su aplicación necesita un control y una acción para poder entregar esas vistas al usuario cuando lo necesite.

Presentación a Controllers

Por convención de MVC, el hecho que tiene una carpeta Account implica que debe tener un Controller llamado AccountController, de manera que el siguiente paso es crear dicho controlador en la carpeta Controllers. Tan solo haga clic con el botón secundario del mouse y seleccione Agregar | Controller. Desde este Controller vacío se puede crear métodos de acción que contienen la lógica que reside actualmente en el extremo superior de cada página .cshtml que movimos a la aplicación.

Primero enfrentaremos a Login.cshtml, que contiene el código en la figura 1.

Figura 1 Lógica empresarial contenida en Login.cshtml

Page.Title = "Login";
if (IsPost) {
  var email = Request["email"];
  if (email.IsEmpty()) {
    ModelState.AddError(
      "email", "You must specify an email address.");
  }
  var password = Request["password"];
  if (password.IsEmpty()) {
    ModelState.AddError(
      "password", "You must specify a password.");
  }

  if (ModelState.IsValid) {
    var rememberMe = Request["rememberMe"].AsBool();
    if (WebSecurity.Login(email, password, rememberMe)) { 
      string returnUrl = Request["returnUrl"];        
      if (!returnUrl.IsEmpty()) {
        Context.RedirectLocal(returnUrl);
      } else{
        Response.Redirect("~/");
      }
    } else {
      ModelState.AddFormError(
        "The email or password provided is incorrect.");
    }
  }
}

Observe que se están controlando dos escenarios aquí. El primero es para el momento en el que el usuario carga la página de inicio por primera vez. En este escenario, Page configura su título y transición directamente en el marcado. El segundo escenario está contenido en el condicional IsPost y representa la lógica que se ejecuta cuando el usuario completa el formulario de inicio de sesión y hace clic en el botón Login.

En ASP.NET MVC se controlan los proceso para proporcionar un formulario vacío y aceptar un envío de formulario mediante dos métodos de acción en un control, uno para el formulario vacío y otro para controlar el envío. La primera acción configura el título de la página y devuelve la vista de inicio de sesión, mientras que en la segunda estará contenida la lógica que estará dentro del condicional IsPost. Estas acciones están contenidas en la figura 2. Después de agregar ambas acciones, elimine el código del encabezado de Login.cshtml.

Figura 2 Acciones del Controller de inicio de sesión

public ActionResult Login() {
  ViewBag.Title = "Login";
  return View();
}

[HttpPost]
public ActionResult Login(string email, string password, 
  bool? rememberMe, string returnUrl) {
  if (email.IsEmpty())
    ModelState.AddModelError("email", 
      "You must specify an email address.");
  if (password.IsEmpty())
    ModelState.AddModelError("password", 
      "You must specify a password.");
  if (!ModelState.IsValid)
    return View();
  if (WebSecurity.Login(email, password, 
    rememberMe.HasValue ? rememberMe.Value : false)) {
    if (!string.IsNullOrEmpty(returnUrl))
      return Redirect(returnUrl);
    return RedirectToAction("Default", "Gallery");
  }

  ModelState.AddModelError("_FORM", 
    "The email or password provided is incorrect");
  return View();
}

Existen varias diferencias claves entre la página original y los métodos de acción que quedan como resultado que se deben observar. Para empezar, notará que el condicional IsPost no es necesario. En ASP.NET MVC, creamos una acción de entrada para la página de inicio al crear un segundo método de acción Login y lo decoramos con el atributo [HttpPost]. El método Login que teníamos antes ahora no hace más que configurar la propiedad ViewBag.Title y devolver ViewResult, el cual buscará una página de vista en Views/Account denominada Login.cshtml.

Lo segundo que podría notar es que la acción Post contiene varios parámetros y que todas las llamadas Request que se usaban en la página original ya no están. Al poner parámetros en el método que se corresponden a nombres de campo en el formulario Login (email, password y rememberMe), podemos usar el enlazador de modelo predeterminado de ASP.NET MVC para hacer que se pasen esos elementos como parámetros de la acción, lo que nos evita tener que llamar al objeto Request nosotros mismos y hace que la acción lógica sea mas concisa.

Por último, existen algunas diferencias menores en la manera en la que se controla la validación y en como se realizan las redirecciones en las aplicaciones de Web Pages y de ASP.NET MVC. En el sitio Web Pages, se usan las llamadas ModelState.AddError y .AddFormError para notificar la página en la que encontramos datos de formulario no válidos. En las aplicaciones de ASP.NET MVC, usamos ModelState.AddModelError, lo cual es escasamente distinto, pero es un cambio necesario para todas las páginas. Para las redirecciones, nuestro sitio Web Pages llama a Response.Redirect al volver a enrutar al usuario. En ASP.NET MVC se llama al retorno RedirectToRoute(“Default”) puesto que las acciones del controlador debiesen devolver a ActionResult, lo cual genera el mismo resultado.

Una vez que hicimos la migración de la página de inicio de sesión, podremos tratar rápidamente a Logout.cshtml. En Web Pages, algunas páginas pueden contener lógica sin marcado si están destinadas a realizar una acción y después redirigir al usuario, como se aprecia en Logout.cshtml:

@{
  WebSecurity.Logout();
  Response.Redirect("~/");
}

En ASP.NET MVC, agregaremos una acción Logout que realiza este trabajo por nosotros:

public ActionResult Logout() {
  WebSecurity.Logout();
  return RedirectToAction("Default", "Gallery");
}

Puesto que Views representa sólo los elementos visuales de una página y no una funcionalidad, además de que creamos una acción que controla el cierre de sesión del usuario con una redirección, se puede eliminar el View de Logout.cshtml de la aplicación.

Hasta ahora, transformamos nuestras páginas Account a vistas al copiarlas a la carpeta Views/Account, creamos a AccountController para controlar solicitudes para las páginas Account e implementamos métodos de acción para controlar los escenarios de inicio y cierre de sesión. En este punto, puede crear y poner en marcha el sitio y agregar Account/Login a la barra de direcciones en el explorador (observe que la página de inicio predeterminada apunta a Gallery/Default y que no la hemos implementado aún, por lo cual no se mostrará).

La otra parte de la funcionalidad del sitio que deseará tratar en este momento es el código y los auxiliares que contuvo en el directorio App_Code, en su sitio Web Pages. En el inicio de la migración, podía mover este directorio por completo a su aplicación ASP.NET MVC e incluirla en su proyecto. Si el directorio contiene cualquier archivo de código (.cs o .vb), puede conservarlos en App_Code o moverlos a otra parte. En cualquier caso, necesitará cambiar la propiedad Build Action de cada archivo a Compile en lugar de Content. Si el directorio contiene archivos .cshtml con declaraciones del método @helper, podrá dejarlos y usarlos tal cual están en su aplicación ASP.NET MVC.

Para el resto de su sitio Web Pages, seguirá un ciclo similar de creación de un Controller para cada carpeta Views, creación de acciones para cada Page y mover el código del encabezado de cada página a una o más acciones. En poco tiempo, debiera tener todas sus páginas separadas ordenadamente en acciones de Controller y Views. Sin embargo, sigue existiendo una parte del patrón MVC que no hemos descrito en este artículo aún: Model.

Migración de acceso a datos a clases de repositorio

El proceso para llevar la lógica empresarial de cada página y moverla a una o más acciones Controller es bastante directo, con una sola excepción: el acceso de datos. Si bien algunas de las páginas pueden ser similares a las páginas de inicio y cierre de sesión y contener un poco de lógica sin acceso de datos, probablemente la mayor parte de su sitio Web Pages usa una base de datos.

Un ejemplo de esto es la página Account/Register.cshtml. Cuando el usuario completa el formulario de registro y hace clic en Register, la página hace dos llamadas a base de datos, lo cual se ilustra en la figura 3.

Figura 3 Lógica de base de datos de Register.cshtml

var db = Database.Open("PhotoGallery");
      
var user = db.QuerySingle("SELECT Email FROM 
UserProfiles WHERE LOWER(Email) = LOWER(@0)", email);
       
if (user == null) {      
  db.Execute(
    "INSERT INTO UserProfiles (Email, DisplayName, Bio) 
    VALUES (@0, @1, @2)", email, email, "");

  try {
    WebSecurity.CreateAccount(email, password);
    WebSecurity.Login(email, password);
    Response.Redirect("~/");
  } catch (System.Web.Security.MembershipCreateUserException e) {
    ModelState.AddFormError(e.ToString());
  }
} else {
  ModelState.AddFormError("Email address is already in use.");
}

Primero, la página de registro abre la base de datos PhotoGallery y devuelve un objeto WebMatrix.Data.Database que representa la base de datos. Después, la página usa el objeto para buscar una dirección de correo electrónico existente con el valor proporcionado por el usuario. Si la dirección no existe, se creará un registro UserProfile y se creará una cuenta para el usuario mediante el proveedor de pertenencia WebSecurity.

Mientras hayamos agregado una referencia a WebMatrix.Data y configuremos la propiedad Copy Local como true, podremos usar esta lógica de base de datos sin cambios y el sitio funcionará normalmente. Dado que está en la mitad de la migración, puede que este sea el enfoque que desee tomar como un paso estratégico para mantener funcional al sitio.

Sin embargo, en este artículo daremos un paso más allá y crearemos objetos adicionales que contengan su acceso a datos, tal como lo haríamos con una aplicación de ASP.NET MVC creada desde cero. Hay muchos patrones a su disposición para separar al Controller de la lógica de acceso de datos. Usaremos el patrón Repository para Photo Gallery y, al abstraer el acceso de datos como clases de repositorio, podremos encapsular esta lógica y minimizar el impacto que ocurriría si escogemos agregar objetos Model formales o un sistema de asignación de objetos relacional (ORM) como Entity Framework más adelante.

Comenzaremos por crear una carpeta Repositorios en nuestra aplicación, junto con una clase simple llamada AccountRepository.cs. Después, recorreremos cada llamada de base de datos en la acción Register y moveremos esa lógica al repositorio, como se muestra en la figura 4.

Figura 4 AccountRepository

public class AccountRepository {
  readonly Database _database;
  public AccountRepository() {
    database = Database.Open("PhotoGallery");
  }

  public dynamic GetAccountEmail(string email) { 
    return _database.QuerySingle(
      "SELECT Email FROM UserProfiles 
      WHERE LOWER(Email) = LOWER(@0)", email);
  }
 
  public void CreateAccount(string email) {
    _database.Execute(
      "INSERT INTO UserProfiles 
      (Email, DisplayName, Bio) VALUES (@0, @1, @2)", 
      email, email, "");
  }
}

Agregamos la llamada a Database.Open al constructor del repositorio y creamos dos métodos, uno para buscar una cuenta de correo electrónico y otra para crear la cuenta.

Observe que el tipo de regreso de GetAccountEmail es dinámico. En WebMatrix.Data, muchos de los métodos query tienen regresos dinámicos o IEnumerable<dynamic> y no hay ninguna razón por la cual no pueda continuar esta práctica en sus repositorios mientras la práctica sea sostenible. 

El nuevo método Register, que usa a AccountRespository, se ilustra en la figura 5.

Figura 5 Acción Register usando a AccountRepository

[HttpPost]
public ActionResult Register(string email, string password, 
  string confirmPassword) {

  // Check Parameters (omitted)

  if (!ModelState.IsValid)
    return View();
 
  var db = new AccountRepository();
  var user = db.GetAccountEmail(email);
 
  if (user == null) {
    db.CreateAccount(email);
 
    try {
      WebSecurity.CreateAccount(email, password);
      WebSecurity.Login(email, password);
      return RedirectToAction("Default", "Gallery");
    }
    catch (System.Web.Security.MembershipCreateUserException e) {
      ModelState.AddModelError("_FORM", e.ToString());
    }
  }
  else {
    ModelState.AddModelError("_FORM", 
      "Email address is already in use.");
  }
 
  return View();
}

Es totalmente posible usar tipos de regreso dinámicos y, incluso, puede ser prudente hacerlo durante una migración al poner el sitio en marcha como una aplicación ASP.NET MVC completa. No se le exige usar modelos tipados fuertemente en una aplicación ASP.NET MVC, de manera que podrá usar esta estrategia cuanto sea necesario, mientras no necesite una definición estructurada por código en su modelo de datos. La lógica Controller y Views de su aplicación ASP.NET MVC de modelo de dinámica funcionará de forma normal, salvo por una sola excepción.

Notará que, en la aplicación Web Pages, los campos de formulario se definen explícitamente usando marcado estándar:

<input type="text" />
<input type="submit" />
...

En ASP.NET MVC, la manera preferible de usar controles de formulario es mediante métodos auxiliares Html como Html.TextBox o Html.TextBoxFor, puesto que estos métodos usan el Model que se pasa por Views para configurar los valores actuales y controlar la validación de formularios. Si desea usar estos métodos auxiliares en Views después de la migración, deberá introducir objetos Model tipados fuertemente y dejar de usar tipos dinámicos en sus repositorios, puesto que estos métodos auxiliares no funcionan con modelos dinámicos.

Conservación de URL de sitio

Las URL del sitio son importantes. Sin importar el estado del sitio, muchas fuentes externas dependen de las URL existentes: motores de búsqueda, documentación, comunicaciones, scripts de prueba y otros similares. Debido a estas dependencias, no debiese cambiar de forma arbitraria sus URL, incluso para una migración.

Considere usar enrutamiento de ASP.NET para asegurar que se conserven las URL existentes. El enrutamiento de ASP.NET facilita la consulta y la hace coincidir con el recurso correcto, en este caso con un Controller y una Action. Web Pages usa un sistema de enrutamiento distinto de ASP.NET MVC, por lo que necesitará pasar algo de tiempo asegurándose de que se conserven sus URL existentes.

Las aplicaciones Web Pages pueden controlar URL con o sin extensiones. Por ejemplo, estas dos URL se resuelven en la misma página:

http://mysite/Gallery/Default.cshtml

http://mysite/Gallery/Default

Sin embargo, una aplicación de ASP.NET MVC no controlará la primera URL mediante la extensión .cshtml. Al usar URL sin extensión en su sitio se asegurará que los motores de búsqueda y otros sitios dependientes hagan lo mismo, lo que minimizará el impacto de la migración de su sitio. Sin embargo, si necesita controlar URL existentes con extensiones, puede crear rutas en la aplicación de ASP.NET MVC para asegurarse de que no estén rotas.

Por ejemplo, considere la ruta predeterminada para la aplicación Photo Gallery:

routes.MapRoute(
  "Default", 
  "{controller}/{action}/{id}", 
  new { controller = "Home", 
    action = "Index", id = "" } 
);

Para brindar compatibilidad a las URL heredadas del sistema, será necesario agregar rutas adicionales a la tabla de rutas sobre esta definición en el archivo Global.asax. Aquí hay un ejemplo de una de esas definiciones:

routes.MapRoute(
  "LegacyUrl",
  "{controller}/{action}.cshtml/{id}",
  new { controller = "Gallery", 
    action = "Default", id = "" }
);

En la ruta de esta entrada, las URL que contienen la extensión .cshtml se controlan y se envían al Controller y a la Action adecuadas, dando por sentado que su estructura de sitio Web Pages existente se asigna claramente a una estructura Controller/Action.

Al planear una migración, tenga en mente que su aplicación puede requerir un cambio a la ruta predeterminada o incluso pude necesitar rutas adicionales para admitir las direcciones URL existentes. Sin embargo, si decide romper una URL existente, asegúrese de incluir las Action que controlen las redirecciones permanentes para los usuarios.

Conclusión

Demos un vistazo a las estructuras anterior y posterior del sitio de Photo Gallery para destacar el impacto de una migración desde Web Pages a ASP.NET MVC. En la figura 6, verá la estructura del sitio Web Pages en WebMatrix en el lado izquierdo. El lado derecho muestra el sitio después de una migración completa a ASP.NET MVC. Observe que, si bien hay diferencias en estructura, la mayor parte del resultado final le será familiar.

Application Layout Before and After

Figura 6 Diseño de la aplicación anterior y posterior

Hoy, los desarrolladores de ASP.NET tienen tres opciones de marco que escoger: Web Forms, Web Pages y ASP.NET MVC. Si bien cada uno tiene sus fortalezas, escoger uno no le impide aprovechar a otro o incluso migrar a otro en el futuro. Además, dado que se crearon los tres a partir de ASP.NET, cambiarse de uno a otro no debiera fundamentarse jamás por razones técnicas. Si decide hacer el cambio, las similitudes entre Web Pages y ASP.NET MVC deberían ayudarle a continuar usando tecnologías como NuGet, Razor, Web Deploy, IIS Express y SQL Compact sin modificación.

Si crea su aplicación mediante Web Pages y decide que el cambio es una buena idea, la migración Web Pages a ASP.NET MVC es el camino que ofrecerá menor resistencia, especialmente si toma decisiones de diseño iniciales en su sitio Web Pages para agrupar páginas en carpetas según funcionalidad, use URL relativas para todos los recursos y ponga toda la lógica comercial al inicio de cada página. Cuando llegue el momento de la migración, descubrirá que el desplazamiento desde Web Pages a ASP.NET MVC es simple y directo, tal como debe ser.

Podrá encontrar vínculos a muchas de las técnicas y tecnologías usadas en este artículo y mucho más en bit.ly/WebMatrixToMVC.

Brandon Satrom es un evangelista desarrollador senior de Microsoft radicado en las afueras de Austin, Texas. Él escribe en su blog, userInexperience.com, transmite podcasts en DeveloperSmackdown.com y mantiene una cuenta de Twitter, twitter.com/BrandonSatrom.

Clark Sell es un evangelista desarrollador senior de Microsoft radicado en las afueras de Chicago. Él escribe en su blog, csell.net, transmite podcasts en DeveloperSmackdown.com y mantiene una cuenta de Twitter, twitter.com/csell5.

Gracias a los siguientes expertos técnicos por su ayuda en la revisión de este artículo: Phil Haack y Erik Porter