Personalización del comportamiento de todo el sitio para sitios de ASP.NET Web Pages (Razor)

por Tom FitzMacken

En este artículo se explica cómo establecer la configuración del lado del sitio para las páginas en un sitio web de ASP.NET Web Pages (Razor).

Temas que se abordarán:

  • Cómo ejecutar código que le permita establecer valores (valores globales o configuración del asistente) para todas las páginas de un sitio.
  • Cómo ejecutar código que le permite establecer valores para todas las páginas de una carpeta.
  • Cómo ejecutar código antes y después de que se cargue una página.
  • Cómo enviar errores a una página central de errores.
  • Cómo agregar autenticación a todas las páginas de una carpeta.

Versiones de software usadas en el tutorial

  • ASP.NET Web Pages (Razor) 2
  • WebMatrix 3
  • Biblioteca de asistentes web de ASP.NET (paquete NuGet)

Este tutorial también funciona con ASP.NET Web Pages 3 y Visual Studio 2013 (o Visual Studio Express 2013 para Web), excepto que no puede usar la biblioteca de asistentes web de ASP.NET.

Agregar código de inicio del sitio web para ASP.NET páginas web

Para gran parte del código que escriba en ASP.NET Web Pages, una página individual puede contener todo el código necesario para esa página. Por ejemplo, si una página envía un mensaje de correo electrónico, es posible colocar todo el código de esa operación en una sola página. Esto puede incluir el código para inicializar la configuración para enviar correo electrónico (es decir, para el servidor SMTP) y para enviar el mensaje de correo electrónico.

Sin embargo, en algunas situaciones, es posible que desee ejecutar código antes de que se ejecute cualquier página del sitio. Esto resulta útil para establecer valores que se pueden usar en cualquier lugar del sitio (denominados valores globales ). Por ejemplo, algunos asistentes requieren que proporcione valores como la configuración de correo electrónico o las claves de cuenta. Puede ser útil mantener esta configuración en valores globales.

Para ello, cree una página denominada _AppStart.cshtml en la raíz del sitio. Si esta página existe, se ejecuta la primera vez que se solicita cualquier página del sitio. Por lo tanto, es un buen lugar para ejecutar código para establecer valores globales. (Dado que _AppStart.cshtml tiene un prefijo de subrayado, ASP.NET no enviará la página a un explorador aunque los usuarios lo soliciten directamente).

En el diagrama siguiente se muestra cómo funciona la página _AppStart.cshtml. Cuando una solicitud entra en una página y, si se trata de la primera solicitud de cualquier página del sitio, ASP.NET comprueba primero si existe una página _AppStart.cshtml. Si es así, se ejecuta cualquier código de la página _AppStart.cshtml y, a continuación, se ejecuta la página solicitada.

[Image shows how App Star dot CSHTML works.]

Establecer valores globales para su sitio web

  1. En la carpeta raíz de un sitio web de WebMatrix, cree un archivo denominado _AppStart.cshtml. El archivo debe estar en la raíz del sitio.

  2. Reemplace el contenido existente por lo siguiente:

    @{
      AppState["customAppName"] = "Application Name";
    }
    

    Este código almacena un valor en el diccionario AppState, que está disponible automáticamente para todas las páginas del sitio. Observe que el archivo _AppStart.cshtml no tiene ningún marcado. La página ejecutará el código y, a continuación, le redirigirá a la página que se solicitó originalmente.

    Nota:

    Tenga cuidado al colocar código en el archivo _AppStart.cshtml. Si se produce algún error en el código del archivo _AppStart.cshtml, el sitio web no se iniciará.

  3. En la carpeta raíz, cree una página denominada AppName.cshtml.

  4. Reemplace el código y el marcado predeterminado por lo siguiente:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Show Application Name</title>
        </head>
        <body>
            <h1>@AppState["customAppName"]</h1>
        </body>
    </html>
    

    Este código extrae el valor del objeto AppState que estableció en la página _AppStart.cshtml.

  5. Ejecute la página AppName.cshtml en un explorador. (Asegúrese de que la página está seleccionada en el área de trabajo Archivos antes de ejecutarla). La página muestra el valor global.

    [Screenshot shows the page displaying the global value.]

Establecer valores para asistentes

Un buen uso para el archivo _AppStart.cshtml es establecer valores para los asistentes que use en el sitio y que deban inicializarse. Algunos ejemplos típicos son la configuración de correo electrónico para el asistente WebMail y las claves privadas y públicas para el asistente ReCaptcha. En casos como estos, puede establecer los valores una vez en el _AppStart.cshtml y, a continuación, ya estarán establecidos para todas las páginas del sitio.

En este procedimiento se muestra cómo establecer la configuración WebMail globalmente. (Para obtener más información sobre el uso del asistente WebMail, consulte Agregar correo electrónico a un sitio de ASP.NET Web Pages).

  1. Agregue la biblioteca de asistentes web de ASP.NET a su sitio web, tal como se describe en Instalación de asistentes en un sitio de páginas web de ASP.NET, si aún no lo ha agregado.

  2. Si aún no tiene un archivo _AppStart.cshtml, en la carpeta raíz de un sitio web, cree un archivo denominado _AppStart.cshtml.

  3. Agregue la siguiente configuración de WebMail al archivo _AppStart.cshtml:

    @{
         // Initialize WebMail helper
         WebMail.SmtpServer = "your-SMTP-host";
         WebMail.SmtpPort = 25;
         WebMail.UserName = "your-user-name-here";
         WebMail.Password = "your-account-password";
         WebMail.From = "your-email-address-here";
    }
    

    Modifique la siguiente configuración relacionada con el correo electrónico en el código:

  4. Guarde el archivo _AppStart.cshtml y ciérrelo.

  5. En la carpeta raíz de un sitio web, cree una nueva página denominada TestEmail.cshtml.

  6. Reemplace el contenido existente por lo siguiente:

    @{
        var message = "";
        try{
            if(IsPost){
                WebMail.Send(
                    to: Request.Form["emailAddress"],
                    subject: Request.Form["emailSubject"],
                    body:Request.Form["emailBody"]
               );
               message = "Email sent!";
            }
        }
        catch(Exception ex){
            message = "Email could not be sent!";
        }
    }
    <!DOCTYPE html>
    <html lang="en">
      <head>
         <meta charset="utf-8" />
         <title>Test Email</title>
      </head>
      <body>
        <h1>Test Email</h1>
        <form method="post">
          <p>
            <label for="emailAddress">Email address:</label>
            <input type="text" name="emailAddress" />
          </p>
          <p>
            <label for="emailSubject">Subject:</label>
            <input type="text" name="emailSubject" />
          </p>
          <p>
            <label for="emailBody">Text to send:</label><br/>
            <textarea name="emailBody" rows="6"></textarea>
          </p>
        <p><input type="submit" value="Send!" /></p>
        @if(IsPost){
            <p>@message</p>
        }
        </form>
      </body>
    </html>
    
  7. Ejecute la página TestEmail.cshtml en un explorador.

  8. Rellene los campos para enviar a sí mismo un mensaje de correo electrónico y, a continuación, haga clic en Enviar.

  9. Consulte el correo electrónico para asegurarse de que ha recibido el mensaje.

La parte importante de este ejemplo es que la configuración que normalmente no cambia,como el nombre del servidor SMTP y las credenciales de correo electrónico, se establecen en el archivo _AppStart.cshtml. De esta forma no tendrá que volver a configurarlos en cada página en la que envíe correo electrónico. (Aunque si por algún motivo necesita cambiar esos ajustes, puede configurarlos individualmente en una página). En la página, solo se establecen los valores que normalmente cambian cada vez, como el destinatario y el cuerpo del mensaje de correo electrónico.

Ejecutar código antes y después de archivos en una carpeta

Al igual que puede usar _AppStart.cshtml para escribir código antes de que las páginas del sitio se ejecuten, puede escribir código que se ejecute antes (y después) de cualquier página de una ejecución de carpeta determinada. Esto resulta útil para cosas como establecer la misma página de diseño para todas las páginas de una carpeta o para comprobar que un usuario ha iniciado sesión antes de ejecutar una página en la carpeta.

Para páginas en carpetas concretas, puede crear código en un archivo denominado _PageStart.cshtml. En el diagrama siguiente se muestra cómo funciona la página _AppStart.cshtml. Cuando una solicitud entra en una página, ASP.NET primero comprueba si hay una página _AppStart.cshtml y la ejecuta. A continuación, ASP.NET comprueba si hay una página _PageStart.cshtml y, si es así, la ejecuta. A continuación, ejecuta la página solicitada.

Dentro de la página _PageStart.cshtml, puede especificar en qué momento del proceso desea que se ejecute la página solicitada incluyendo un método RunPage. Esto le permite ejecutar código antes de que se ejecute la página solicitada y de nuevo después. Si no incluye RunPage, se ejecuta todo el código de _PageStart.cshtml y, a continuación, la página solicitada se ejecuta automáticamente.

[Image shows how the requested page will run automatically.]

ASP.NET permite crear una jerarquía de archivos _PageStart.cshtml. Puede colocar un archivo _PageStart.cshtml en la raíz del sitio y en cualquier subcarpeta. Cuando se solicita una página, se ejecuta el archivo _PageStart.cshtml en el nivel más alto (más cercano a la raíz del sitio), seguido del archivo _PageStart.cshtml en la siguiente subcarpeta, y así sucesivamente por la estructura de subcarpeta hasta que la solicitud llegue a la carpeta que contiene la página solicitada. Una vez ejecutados todos los archivos _PageStart.cshtml aplicables, se ejecuta la página solicitada.

Por ejemplo, puede tener la siguiente combinación de archivos _PageStart.cshtml y Default.cshtml:

@* ~/_PageStart.cshtml *@
@{
  PageData["Color1"] = "Red";
  PageData["Color2"] = "Blue";
}
@* ~/myfolder/_PageStart.cshtml *@
@{
  PageData["Color2"] = "Yellow";
  PageData["Color3"] = "Green";
}
@* ~/myfolder/default.cshtml *@
@PageData["Color1"]
<br/>
@PageData["Color2"]
<br/>
@PageData["Color3"]

Al ejecutar /myfolder/default.cshtml, verá lo siguiente:

Red

Yellow

Green

Ejecutar código de inicialización para todas las páginas de una carpeta

Un buen uso para los archivos _PageStart.cshtml es inicializar la misma página de diseño para todos los archivos de una sola carpeta.

  1. En la carpeta raíz, cree una carpeta nueva denominada InitPages.

  2. En la carpeta InitPages de su sitio web, cree un archivo denominado _PageStart.cshtml y reemplace el marcado y el código predeterminados por lo siguiente:

    @{
        // Sets the layout page for all pages in the folder.
        Layout = "~/Shared/_Layout1.cshtml";
    
        // Sets a variable available to all pages in the folder.
        PageData["MyBackground"] = "Yellow";
    }
    
  3. En la raíz del sitio web, cree una carpeta denominada Shared.

  4. En la carpeta Shared, cree un archivo denominado _Layout1.cshtml y reemplace el marcado y el código predeterminados por lo siguiente:

    @{
      var backgroundColor = PageData["MyBackground"];
    }
    <!DOCTYPE html>
    <html>
    <head>
      <title>Page Title</title>
      <link type="text/css" href="/Styles/Site.css" rel="stylesheet" />
    </head>
    <body>
      <div id="header">
        Using the _PageStart.cshtml file
      </div>
      <div id="main" style="background-color:@backgroundColor">
        @RenderBody()
      </div>
    <div id="footer">
      &copy; 2012 Contoso. All rights reserved
    </div>
    </body>
    </html>
    
  5. En la carpeta InitPages, cree un archivo denominado Content1.cshtml y reemplace el contenido existente por lo siguiente:

    <p>This is content page 1.</p>
    
  6. En la carpeta InitPages, cree otro archivo denominado Content2.cshtml y reemplace el marcado predeterminado por lo siguiente:

    <p>This is content page 2.</p>
    
  7. Ejecute Content1.cshtml en un explorador.

    [Image shows running Content 1 dot CSHTML in a browser.]

    Cuando se ejecuta la página Content1.cshtml, el archivo _PageStart.cshtml establece Layout y PageData["MyBackground"] en un color. En Content1.cshtml, se aplican el diseño y el color.

  8. Visualice Content2.cshtml en un explorador.

    El diseño es el mismo, ya que ambas páginas usan el mismo diseño de página y color que se inicializó en _PageStart.cshtml.

Uso de _PageStart.cshtml para controlar errores

Otro buen uso para el archivo _PageStart.cshtml es crear una manera de controlar los errores de programación (excepciones) que pueden producirse en cualquier página .cshtml de una carpeta. En este ejemplo se muestra una manera de hacerlo.

  1. En la carpeta raíz, cree una carpeta denominada InitCatch.

  2. En la carpeta InitCatch de su sitio web, cree un archivo denominado _PageStart.cshtml y reemplace el marcado y el código existentes por lo siguiente:

    @{
        try
        {
            RunPage();
        }
        catch (Exception ex)
        {
            Response.Redirect("~/Error.cshtml?source=" +
                HttpUtility.UrlEncode(Request.AppRelativeCurrentExecutionFilePath));
        }
    }
    

    En este código, intentará ejecutar la página solicitada explícitamente llamando al método RunPage dentro de un bloque try. Si se producen errores de programación en la página solicitada, se ejecuta el código dentro del bloque catch. En este caso, el código se redirige a una página (Error.cshtml) y pasa el nombre del archivo que experimentó el error como parte de la dirección URL. (Creará la página en breve).

  3. En la carpeta InitCatch de su sitio web, cree un archivo denominado Exception.cshtml y reemplace el marcado y el código existentes por lo siguiente:

    @{
        var db = Database.Open("invalidDatabaseFile");
    }
    

    A efectos de este ejemplo, lo que está haciendo en esta página es crear deliberadamente un error al intentar abrir un archivo de base de datos que no existe.

  4. En la carpeta raíz, cree un archivo denominado Error.cshtml y reemplace el marcado y el código existentes por lo siguiente:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Error Page</title>
        </head>
        <body>
    <h1>Error report</h1>
    <p>An error occurred while running the following file: @Request["source"]</p>
        </body>
    </html>
    

    En esta página, la expresión @Request["source"] obtiene el valor de la dirección URL y lo muestra.

  5. En la barra de herramientas, haga clic en Guardar.

  6. Ejecute Exception.cshtml en un explorador.

    [Screenshot shows running Exception dot CSHTML in a browser.]

    Dado que se produce un error en Exception.cshtml, la página _PageStart.cshtml redirige al archivo Error.cshtml, que muestra el mensaje.

    Para obtener más información sobre las excepciones, consulte Introducción a la programación web de ASP.NET usando la sintaxis Razor.

Uso de _PageStart.cshtml para restringir el acceso a carpetas

También puede usar el archivo _PageStart.cshtml para restringir el acceso a todos los archivos de una carpeta.

  1. En WebMatrix, cree un nuevo sitio web mediante la opción Site From Template.

  2. En las plantillas disponibles, seleccione Sitio de inicio.

  3. En la carpeta raíz, cree una carpeta denominada AuthenticatedContent.

  4. En la carpeta AuthenticatedContent, cree un archivo denominado _PageStart.cshtml y reemplace el marcado y el código existentes por lo siguiente:

    @{
        Response.CacheControl = "no-cache";
        if (!WebSecurity.IsAuthenticated) {
            var returnUrl = "~/Account/Login?ReturnUrl=" + Request.Url.LocalPath;
            Response.Redirect(returnUrl);
        }
    }
    

    El código comienza evitando que todos los archivos de la carpeta se almacenen en caché. (Esto es necesario para escenarios como equipos públicos, donde no se quiere que las páginas almacenadas en caché de un usuario estén disponibles para el siguiente usuario). A continuación, el código determina si el usuario ha iniciado sesión en el sitio antes de que pueda ver cualquiera de las páginas de la carpeta. Si el usuario no ha iniciado sesión, el código redirige a la página de inicio de sesión. La página de inicio de sesión puede devolver al usuario a la página que se solicitó originalmente si incluye un valor de cadena de consulta denominado ReturnUrl.

  5. Cree una nueva página en la carpeta AuthenticatedContent denominada Page.cshtml.

  6. Reemplace el marcado predeterminado por lo siguiente:

    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Authenticated Content";
    }
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
      </head>
      <body>
        Thank you for authenticating!
      </body>
    </html>
    
  7. Ejecute Page.cshtml en un explorador. El código le redirige a una página de inicio de sesión. Debe registrarse antes de iniciar sesión. Después de registrarse e iniciar sesión, puede ir a la página y ver su contenido.

Recursos adicionales

Introducción a la programación de ASP.NET Web Pages usando la sintaxis Razor