Referencia sobre la sintaxis de Razor para ASP.NET Core

Por Rick Anderson, Taylor Mullen y Dan Vicarel

Razor es una sintaxis de marcado para insertar código basado en .NET en páginas web. La sintaxis de Razor consta de marcado de Razor, C# y HTML. Los archivos que contienen Razor suelen tener la extensión de archivo .cshtml. Razor también se encuentra en Razor archivos de componentes (.razor). La sintaxis de Razor es similar a los motores de plantillas de varios marcos de aplicación de página única (SPA) de JavaScript, como Angular, React, VueJs y Svelte. Para obtener más información, consulte Las características descritas en este artículo están obsoletas a partir de ASP.NET Core 3.0.

Introducción a la programación web de ASP.NET mediante la sintaxis de Razor brinda varios ejemplos de programación con la sintaxis de Razor. Aunque el tema se escribió para ASP.NET en lugar de ASP.NET Core, la mayoría de los ejemplos se aplican a ASP.NET Core.

Representación de HTML

El lenguaje predeterminado de Razor es HTML. Representar el HTML del marcado de Razor no difiere mucho de representar el HTML de un archivo HTML. El servidor procesa el marcado HTML en los archivos de .cshtmlRazor sin cambios.

Sintaxis de Razor

Razor admite C# y usa el símbolo @ para realizar la transición de HTML a C#. Razor evalúa las expresiones de C# y las representa en la salida HTML.

Cuando el símbolo @ va seguido de una palabra clave reservada deRazor, realiza una transición a un marcado específico de Razor. En caso contrario, realiza la transición a HTML simple.

Para evitar un símbolo @ en un marcado de Razor, use un segundo símbolo @:

<p>@@Username</p>

El código aparecerá en HTML con un solo símbolo @:

<p>@Username</p>

El contenido y los atributos HTML que tienen direcciones de correo electrónico no tratan el símbolo @ como un carácter de transición. Las direcciones de correo electrónico del siguiente ejemplo no se modifican con el análisis de Razor:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Scalable Vector Graphics (SVG)

Se admiten los elementosSVGforeignObject:

@{
    string message = "foreignObject example with Scalable Vector Graphics (SVG)";
}

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black" 
        fill="none" />
    <foreignObject x="20" y="20" width="160" height="160">
        <p>@message</p>
    </foreignObject>
</svg>

Expresiones implícitas de Razor

Las expresiones implícitas de Razor comienzan por @ seguidas del código C#:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

Con la excepción de la palabra clave de C# await, las expresiones implícitas no deben contener espacios. Si la instrucción de C# tiene un final claro, se pueden entremezclar espacios:

<p>@await DoSomething("hello", "world")</p>

Las expresiones implícitas no pueden contener tipos genéricos de C#, ya que los caracteres dentro de los corchetes (<>) se interpretan como una etiqueta HTML. El siguiente código no es válido:

<p>@GenericMethod<int>()</p>

El código anterior genera un error del compilador similar a uno de los siguientes:

  • El elemento "int" no estaba cerrado. Todos los elementos deben ser de autocierre o tener una etiqueta de fin coincidente.
  • No se puede convertir el grupo de métodos "GenericMethod" en el tipo no delegado "object". ¿Intentó invocar el método?

Las llamadas a método genéricas deben estar incluidas en una expresión explícita de Razor o en un bloque de código de Razor.

Expresiones explícitas de Razor

Las expresiones explícitas Razor constan de un símbolo @ con un paréntesis que abre y otro que cierra. Para representar la hora de la semana pasada, se usa el siguiente marcado de Razor:

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

El contenido que haya entre paréntesis @() se evalúa y se representa en la salida.

Por lo general, las expresiones implícitas (que explicamos en la sección anterior) no pueden contener espacios. En el siguiente código, una semana no se resta de la hora actual:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

El código representa el siguiente HTML:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

Se pueden usar expresiones explícitas para concatenar texto con un resultado de la expresión:

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

Sin la expresión explícita, <p>Age@joe.Age</p> se trataría como una dirección de correo electrónico y se mostraría como <p>Age@joe.Age</p>. Pero, si se escribe como una expresión explícita, se representa <p>Age33</p>.

Se pueden usar expresiones explícitas para representar la salida de métodos genéricos en los archivos .cshtml. En el siguiente marcado se muestra cómo corregir el error mostrado anteriormente provocado por el uso de corchetes en un código C# genérico. El código se escribe como una expresión explícita:

<p>@(GenericMethod<int>())</p>

Codificación de expresiones

Las expresiones de C# que se evalúan como una cadena están codificadas en HTML. Las expresiones de C# que se evalúan como IHtmlContent se representan directamente a través de IHtmlContent.WriteTo. Las expresiones de C# que no se evalúan como IHtmlContent se convierten en una cadena por medio de ToString y se codifican antes de que se representen.

@("<span>Hello World</span>")

El código anterior genera el siguiente código HTML:

&lt;span&gt;Hello World&lt;/span&gt;

El código HTML se muestra en el explorador como texto sin formato:

<span>Hola mundo</span>

La salida de HtmlHelper.Raw no está codificada, pero se representa como marcado HTML.

Advertencia

Usar HtmlHelper.Raw en una entrada de usuario no saneada constituye un riesgo de seguridad. Dicha entrada podría contener código JavaScript malintencionado u otras vulnerabilidades de seguridad. Sanear una entrada de usuario es complicado. Evite usar HtmlHelper.Raw con entradas de usuario.

@Html.Raw("<span>Hello World</span>")

El código representa el siguiente HTML:

<span>Hello World</span>

Bloques de código de Razor

Los bloques de código de Razor comienzan con @ y están encerrados por {}. A diferencia de las expresiones, el código de C# dentro de los bloques de código no se representa. Las expresiones y los bloques de código de una vista comparten el mismo ámbito y se definen en orden:

@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

El código representa el siguiente HTML:

<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

En los bloques de código, declare las funciones locales con marcado para utilizarlas como métodos en la creación de plantillas:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

El código representa el siguiente HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Transiciones implícitas

El lenguaje predeterminado de un bloque de código es C#, pero la página de Razor puede volver al HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

Transición delimitada explícita

Para definir una subsección de un bloque de código que deba representar HTML, inserte los caracteres que quiera representar entre etiquetas de Razor<text>:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

Emplee este método para representar HTML que no esté insertado entre etiquetas HTML. Sin una etiqueta HTML o de Razor, se produce un error de tiempo de ejecución de Razor.

La etiqueta <text> es útil para controlar el espacio en blanco al representar el contenido:

  • Solo se representa el contenido entre etiquetas <text>.
  • En la salida HTML no hay espacios en blanco antes o después de la etiqueta <text>.

Transición de línea explícita

Para representar el resto de una línea completa como HTML dentro de un bloque de código, use la sintaxis @::

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

Sin @: en el código, se produce un error de tiempo de ejecución de Razor.

Los caracteres @ de más en un archivo de Razor pueden causar errores del compilador en declaraciones posteriores en el bloque. Estos @ errores adicionales del compilador:

  • Pueden ser difíciles de entender porque el error real ocurre antes del error informado.
  • Es habitual después de combinar varias expresiones implícitas y explícitas en un único bloque de código.

Representación de atributos condicionales

Razor omite automáticamente los atributos que no son necesarios. Si el valor pasado es null o false el atributo no se representa.

Por ejemplo, considere el Razor siguiente:

<div class="@false">False</div>
<div class="@null">Null</div>
<div class="@("")">Empty</div>
<div class="@("false")">False String</div>
<div class="@("active")">String</div>
<input type="checkbox" checked="@true" name="true" />
<input type="checkbox" checked="@false" name="false" />
<input type="checkbox" checked="@null" name="null" />

El marcado anterior de Razor genera el siguiente código HTML:

<div>False</div>
<div>Null</div>
<div class="">Empty</div>
<div class="false">False String</div>
<div class="active">String</div>
<input type="checkbox" checked="checked" name="true">
<input type="checkbox" name="false">
<input type="checkbox" name="null">

Estructuras de control

Las estructuras de control son una extensión de los bloques de código. Todos los aspectos de los bloques de código (transición a marcado, C# en línea) son válidos también en las siguientes estructuras:

Condicionales @if, else if, else, and @switch

@if controla cuándo se ejecuta el código:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

else y else if no necesitan el símbolo @:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

En el siguiente marcado se muestra cómo usar una instrucción switch:

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

En bucle @for, @foreach, @while, and @do while

El HTML con plantilla se puede representar con instrucciones de control en bucle. Para representar una lista de personas:

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}

Se permiten las siguientes instrucciones en bucle:

@for

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@foreach

@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@while

@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}

@do while

@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);

Instrucción @using compuesta

En C#, las instrucciones using se usan para garantizar que un objeto se elimina. En Razor, el mismo mecanismo se emplea para crear asistentes de HTML que incluyen contenido adicional. En el siguiente código, los asistentes de HTML representan una etiqueta <form> con la instrucción @using:

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally

El control de excepciones es similar a C#:

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor tiene la capacidad de proteger las secciones más importantes con instrucciones de bloqueo:

@lock (SomeLock)
{
    // Do critical section work
}

Comentarios

Razor admite comentarios tanto de C# como HTML:

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

El código representa el siguiente HTML:

<!-- HTML comment -->

El servidor quitará los comentarios de Razor antes de mostrar la página web. Razor usa @* *@ ra delimitar comentarios. El siguiente código está comentado, de modo que el servidor no representa ningún marcado:

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

Directivas

Las directivas de Razor se representan en las expresiones implícitas con palabras clave reservadas seguidas del símbolo @. Normalmente, una directiva cambia la forma en que una vista se analiza, o bien habilita una funcionalidad diferente.

Conocer el modo en que Razor genera el código de una vista hace que sea más fácil comprender cómo funcionan las directivas.

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

El código genera una clase similar a la siguiente:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

Más adelante en este artículo, en la sección Inspección de la clase de C# de Razor generada por una vista, se explica cómo ver esta clase generada.

@attribute

La directiva @attribute agrega el atributo especificado a la clase de la página o vista generada. En el ejemplo siguiente se agrega el atributo [Authorize]:

@attribute [Authorize]

La directiva @attribute también se puede usar para proporcionar una plantilla de ruta basada en constantes en un componente de Razor. En el ejemplo siguiente, la directiva @page de un componente se reemplaza por la directiva @attribute y la plantilla de ruta basada en constantes en Constants.CounterRoute, que se establece en otra parte de la aplicación en "/counter”:

- @page "/counter"
+ @attribute [Route(Constants.CounterRoute)]

@code

Este escenario solo se aplica a los componentes de Razor (.razor).

El bloque @code habilita un componente de Razor para que agregue miembros de C# (campos, propiedades y métodos) a un componente:

@code {
    // C# members (fields, properties, and methods)
}

En el caso de los componentes de Razor, @code es un alias para @functions y se recomienda en lugar de @functions. Se permite emplear más de un bloque @code.

@functions

La directiva @functions permite agregar miembros de C# (campos, propiedades y métodos) a la clase generada:

@functions {
    // C# members (fields, properties, and methods)
}

En los componentes de Razor, use @code en lugar de @functions para agregar miembros de C#.

Por ejemplo:

@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

El código genera el siguiente marcado HTML:

<div>From method: Hello</div>

El siguiente código es la clase C# de Razor generada:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998

Los métodos @functions se pueden usar para la creación de plantillas si están marcados:

@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

El código representa el siguiente HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

La directiva @implements implementa una interfaz para la clase generada.

En el ejemplo siguiente se implementa System.IDisposable para que se pueda llamar al método Dispose:

@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

La directiva @inherits proporciona control total sobre la clase que la vista hereda:

@inherits TypeNameOfClassToInheritFrom

El siguiente código es un tipo personalizado de página de Razor:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

CustomText se muestra en una vista:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

El código representa el siguiente HTML:

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@model y @inherits se pueden usar en la misma vista. @inherits puede estar en un archivo _ViewImports.cshtml que importa la vista:

@inherits CustomRazorPage<TModel>

El siguiente código es un ejemplo de una vista fuertemente tipada:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

Si "rick@contoso.com" se pasa en el modelo, la vista genera el siguiente marcado HTML:

<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@inject

La directiva @inject permite a la página de Razor insertar un servicio del contenedor en una vista. Para más información, vea Dependency injection into views (Inserción de dependencias en vistas).

@layout

Este escenario solo se aplica a los componentes de Razor (.razor).

La directiva @layout especifica un diseño para los componentes enrutables de Razor que tienen una @page directiva. Los componentes de diseño se usan para evitar incoherencias y contenido duplicado en el código. Para obtener más información, consulte Diseños de ASP.NET Core Blazor.

@model

Este escenario solo se aplica a las vistas de MVC y a Razor Pages (.cshtml).

La directiva @model especifica el tipo del modelo que se pasa a una vista o página:

@model TypeNameOfModel

En una aplicación de ASP.NET Core MVC o de Razor Pages creada con cuentas de usuario individuales, Views/Account/Login.cshtml contiene la declaración de modelo siguiente:

@model LoginViewModel

La clase generada se hereda de RazorPage<LoginViewModel>:

public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>

Razor expone una propiedad Model para tener acceso al modelo que se ha pasado a la vista:

<div>The Login Email: @Model.Email</div>

La directiva @model especifica el tipo de la propiedad Model. La directiva especifica el elemento T en RazorPage<T> de la clase generada de la que se deriva la vista. Si la directiva @model no se especifica, la propiedad Model es de tipo dynamic. Para obtener más información, vea Strongly typed models and the @model keyword.

@namespace

Directiva @namespace:

  • Establece el espacio de nombres de la clase de la página de Razor, la vista MVC o el componente Razor generado.
  • Establece los espacios de nombres de las clases de páginas, vistas o componentes derivados de la raíz del archivo de importaciones más cercano en el árbol de directorios, _ViewImports.cshtml (vistas o páginas) o _Imports.razor (componentes de Razor).
@namespace Your.Namespace.Here

En el ejemplo de Razor Pages que se muestra en la tabla siguiente:

  • Cada página importa Pages/_ViewImports.cshtml.
  • Pages/_ViewImports.cshtml contiene @namespace Hello.World.
  • Cada página tiene Hello.World como raíz de su espacio de nombres.
Page Espacio de nombres
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Hello.World.MorePages.EvenMorePages

Las relaciones anteriores se aplican a los archivos de importación usados con las vistas de MVC y los componentes de Razor.

Cuando varios archivos de importación tienen una directiva @namespace, se usa el archivo más cercano a la página, vista o componente en el árbol de directorios para establecer el espacio de nombres raíz.

Si la carpeta EvenMorePages del ejemplo anterior tiene un archivo de importaciones con @namespace Another.Planet (o el archivo Pages/MorePages/EvenMorePages/Page.cshtml contiene @namespace Another.Planet), el resultado es el que se muestra en la tabla siguiente.

Page Espacio de nombres
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Another.Planet

@page

La directiva @page tiene efectos diferentes en función del tipo de archivo en el que aparece. Directiva:

@preservewhitespace

Este escenario solo se aplica a los componentes de Razor (.razor).

Cuando se establece en false (valor predeterminado), el espacio en blanco en el marcado representado de los componentes Razor (.razor) se quita si:

  • Está delante o detrás de un elemento.
  • Está delante o detrás de un parámetro RenderFragment. Por ejemplo, el contenido secundario se pasa a otro componente.
  • Precede o sigue a un bloque de código de C#, como @if o @foreach.

@rendermode

Este escenario solo se aplica a los componentes de Razor (.razor).

Establece el modo de representación de un componente Razor:

  • InteractiveServer: aplica la representación interactiva del servidor mediante Blazor Server.
  • InteractiveWebAssembly: : Aplica el renderizado interactivo WebAssembly utilizando Blazor WebAssembly.
  • InteractiveAuto: Inicialmente aplica el renderizado interactivo de WebAssembly usando Blazor Server, y luego aplica el renderizado interactivo de WebAssembly usando WebAssembly en visitas posteriores luego de descargar el conjunto Blazor.

Para una instancia de componente:

<... @rendermode="InteractiveServer" />

En la definición del componente:

@rendermode InteractiveServer

Nota:

Las plantillas Blazor incluyen una directiva estática using para RenderMode en el archivo de _Imports la aplicación (Components/_Imports.razor) para una sintaxis más corta @rendermode:

@using static Microsoft.AspNetCore.Components.Web.RenderMode

Sin la directiva anterior, los componentes deben especificar la clase estática RenderMode en la sintaxis @rendermode explícitamente:

<Dialog @rendermode="RenderMode.InteractiveServer" />

Para obtener más información, incluidas instrucciones sobre cómo deshabilitar la representación previa con el atributo de directiva o directiva, consulte ASP.NET Core Blazor modos de representación.

@section

Este escenario solo se aplica a las vistas de MVC y a Razor Pages (.cshtml).

La directiva @section se usa junto con los diseños de MVC y Razor Pages para permitir que las vistas o las páginas representen el contenido en diferentes partes de la página HTML. Para obtener más información, consulte Diseño en ASP.NET Core.

@typeparam

Este escenario solo se aplica a los componentes de Razor (.razor).

La directiva @typeparam declara un parámetro de tipo genérico para la clase de componente generada:

@typeparam TEntity

Se admiten los tipos genéricos con restricciones de tipo where:

@typeparam TEntity where TEntity : IEntity

Para más información, consulte los siguientes artículos.

@using

La directiva @using agrega la directiva using de C# a la vista generada:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

En los componentes de Razor, @using también controla qué componentes están en el ámbito.

Atributos de la directiva

Las directivas de Razor están representadas por las expresiones implícitas con palabras clave reservadas seguidas del símbolo @. Un atributo de directiva generalmente cambia la forma en que se analiza un elemento o habilita una funcionalidad diferente.

@attributes

Este escenario solo se aplica a los componentes de Razor (.razor).

@attributes permite que un componente represente atributos no declarados. Para más información, consulte Parámetros arbitrarios y de expansión de atributos de ASP.NET Core Blazor.

@bind

Este escenario solo se aplica a los componentes de Razor (.razor).

El enlace de datos en los componentes se logra mediante el atributo @bind. Para obtener más información, consulte Enlace de datos ASP.NET Core Blazor.

@bind:culture

Este escenario solo se aplica a los componentes de Razor (.razor).

Use el atributo @bind:culture con el atributo @bind para proporcionar un System.Globalization.CultureInfo para analizar y dar formato al valor. Para más información, vea Globalización y localización de Blazor de ASP.NET Core.

@formname

Este escenario solo se aplica a los componentes de Razor (.razor).

@formname asigna un nombre de formulario a un formulario HTML sin formato del componente Razor o a un formulario basado en EditForm (Editform documentación). El valor de @formname debe ser único, lo que evita colisiones de forma en las situaciones siguientes:

  • Un formulario se coloca en un componente con varios formularios.
  • Un formulario se origina desde una biblioteca de clases externa, normalmente un paquete NuGet, para un componente con varios formularios y el autor de la aplicación no controla el código fuente de la biblioteca para establecer un nombre de formulario externo diferente al de otro formulario del componente.

Para más información y ejemplos, consulte ASP.NET Core Blazor descripción general de los formularios.

@on{EVENT}

Este escenario solo se aplica a los componentes de Razor (.razor).

Razor proporciona características de control de eventos para los componentes. Para más información, vea Control de eventos de Blazor en ASP.NET Core.

@on{EVENT}:preventDefault

Este escenario solo se aplica a los componentes de Razor (.razor).

Impide la acción predeterminada para el evento.

@on{EVENT}:stopPropagation

Este escenario solo se aplica a los componentes de Razor (.razor).

Detiene la propagación de eventos para el evento.

@key

Este escenario solo se aplica a los componentes de Razor (.razor).

El atributo de directiva @key hace que el algoritmo de comparación de componentes garantice la preservación de elementos o componentes en función del valor de la clave. Para obtener más información, consulte Conservar las relaciones entre elementos, componentes y modelos en ASP.NET Core Blazor.

@ref

Este escenario solo se aplica a los componentes de Razor (.razor).

Las referencias de componentes (@ref) proporcionan una forma de hacer referencia a la instancia de un componente para poder emitir comandos a dicha instancia. Para más información, vea Componentes Razor de ASP.NET Core.

Delegados de Razor con plantilla

Este escenario solo se aplica a las vistas de MVC y a Razor Pages (.cshtml).

La plantillas deRazor permiten definir un fragmento de la interfaz de usuario con el formato siguiente:

@<tag>...</tag>

En el ejemplo siguiente se muestra cómo especificar un delegado de Razor como Func<T,TResult>. El tipo dinámico se especifica para el parámetro del método encapsulado por el delegado. Se especifica un tipo de objeto como el valor devuelto del delegado. La plantilla se usa con un elemento List<T> de Pet que tiene una propiedad Name.

public class Pet
{
    public string Name { get; set; }
}
@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };
}

La plantilla se representa con el elemento pets proporcionado por una instrucción foreach:

@foreach (var pet in pets)
{
    @petTemplate(pet)
}

Salida representada:

<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

También se puede proporcionar una plantilla de Razor como un argumneto para un método. En el ejemplo siguiente, el método Repeat recibe una plantilla de Razor. El método usa la plantilla para generar contenido HTML con repeticiones de elementos proporcionados a partir de una lista:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

Con la lista de mascotas del ejemplo anterior, se llama al método Repeat con:

  • List<T> de Pet.
  • Número de veces que se repite cada mascota.
  • Plantilla insertada que se va a usar para los elementos de una lista sin ordenar.
<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

Salida representada:

<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>

Asistentes de etiquetas

Este escenario solo se aplica a las vistas de MVC y a Razor Pages (.cshtml).

Hay tres directivas que pertenecen a los asistentes de etiquetas.

Directiva Función
@addTagHelper Pone los asistentes de etiquetas a disposición de una vista.
@removeTagHelper Quita los asistentes de etiquetas agregadas anteriormente desde una vista.
@tagHelperPrefix Especifica una cadena de prefijo de etiqueta para permitir la compatibilidad con el asistente de etiquetas y hacer explícito su uso.

Palabras clave reservadas de Razor

Palabras clave de Razor

  • page
  • namespace
  • functions
  • inherits
  • model
  • section
  • helper (no admitida en ASP.NET Core actualmente)

Las palabras clave de Razor se evitan con @(Razor Keyword) (por ejemplo, @(functions)).

Palabras clave de C# de Razor

  • case
  • do
  • default
  • for
  • foreach
  • if
  • else
  • lock
  • switch
  • try
  • catch
  • finally
  • using
  • while

Las palabras clave C# de Razor deben evitarse dos veces con @(@C# Razor Keyword) (por ejemplo, @(@case)). El primer carácter @ evita el analizador de Razor. y el segundo @, en el analizador de C#.

Palabras clave reservadas no usadas en Razor

  • class

Inspección de la clase C# de Razor generado para una vista

El Razor SDK controla la compilación de archivos de Razor. De manera predeterminada, no se emiten los archivos de código generados. Para habilitar la emisión de los archivos de código, establezca la directiva EmitCompilerGeneratedFiles en el archivo de proyecto (.csproj) a true:

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

Al compilar un proyecto 6.0 (net6.0) en la configuración de compilación Debug, el Razor SDK genera un directorio obj/Debug/net6.0/generated/ en la raíz del proyecto. Su subdirectorio contiene los archivos de código de la página de Razor emitidos.

El Razor SDK controla la compilación de archivos de Razor. Al compilar un proyecto, el Razor SDK genera el directorio obj/{BUILD CONFIGURATION}/{TARGET FRAMEWORK MONIKER}/Razor en la raíz del proyecto. La estructura de directorios dentro del directorio de Razor refleja la estructura de directorios del proyecto.

Considere la siguiente estructura de directorios en un proyecto ASP.NET Core Razor Pages 2.1:

 Areas/
   Admin/
     Pages/
       Index.cshtml
       Index.cshtml.cs
 Pages/
   Shared/
     _Layout.cshtml
   _ViewImports.cshtml
   _ViewStart.cshtml
   Index.cshtml
   Index.cshtml.cs

Al compilar el proyecto en la configuración Debug crea el siguiente directorio obj:

 obj/
   Debug/
     netcoreapp2.1/
       Razor/
         Areas/
           Admin/
             Pages/
               Index.g.cshtml.cs
         Pages/
           Shared/
             _Layout.g.cshtml.cs
           _ViewImports.g.cshtml.cs
           _ViewStart.g.cshtml.cs
           Index.g.cshtml.cs

Para ver la clase generada para Pages/Index.cshtml, abra obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs.

Búsquedas de vistas y distinción entre mayúsculas y minúsculas

El motor de vista de Razor realiza búsquedas de vistas en las que se distingue entre mayúsculas y minúsculas. Pero la búsqueda real viene determinada por el sistema de archivos subyacente:

  • Origen basado en archivos:
    • En los sistemas operativos con sistemas de archivos que no distinguen entre mayúsculas y minúsculas (por ejemplo, Windows), las búsquedas de proveedor de archivos físicos no distinguirán mayúsculas de minúsculas. Por ejemplo, return View("Test") da como resultado coincidencias para /Views/Home/Test.cshtml, /Views/home/test.cshtml y cualquier otra variante de mayúsculas y minúsculas.
    • En los sistemas de archivos en los que sí se distingue entre mayúsculas y minúsculas (por ejemplo, Linux, OSX y al usar EmbeddedFileProvider), las búsquedas distinguirán mayúsculas de minúsculas. Por ejemplo, return View("Test") coincide específicamente con /Views/Home/Test.cshtml.
  • Vistas precompiladas: En ASP.NET Core 2.0 y versiones posteriores, las búsquedas de vistas precompiladas no distinguen mayúsculas de minúsculas en todos los sistemas operativos. Este comportamiento es idéntico al comportamiento del proveedor de archivos físicos en Windows. Si dos vistas precompiladas difieren solo por sus mayúsculas o minúsculas, el resultado de la búsqueda será no determinante.

Por tanto, se anima a todos los desarrolladores a intentar que las mayúsculas y minúsculas de los nombres de archivo y de directorio sean las mismas que las mayúsculas y minúsculas de:

  • Nombres de acciones, controladores y áreas.
  • Razor Pages.

La coincidencia de mayúsculas y minúsculas garantiza que las implementaciones van a encontrar sus vistas, independientemente de cuál sea el sistema de archivos subyacente.

Importaciones utilizadas por Razor

Las siguientes importaciones las generan las plantillas web de ASP.NET Core para admitir archivos de Razor:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

Recursos adicionales

Introducción a la programación web de ASP.NET mediante la sintaxis de Razor brinda varios ejemplos de programación con la sintaxis de Razor.