asp.net-mvc @html.editorfor - ASP.NET MVC 3-Plantilla de visualización parcial vs Plantilla de editor vs




example templates (5)

Por lo tanto, el título debe hablar por sí mismo.

Para crear componentes reutilizables en ASP.NET MVC, tenemos 3 opciones (podrían ser otras que no he mencionado):

Vista parcial:

@Html.Partial(Model.Foo, "SomePartial")

Plantilla de editor personalizado:

@Html.EditorFor(model => model.Foo)

Plantilla de visualización personalizada:

@Html.DisplayFor(model => model.Foo)

En términos de la vista real / HTML, las tres implementaciones son idénticas:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

Entonces, mi pregunta es: ¿cuándo / cómo decides cuál de los tres usar?

Lo que realmente estoy buscando es una lista de preguntas que debe hacerse antes de crear una, para la cual las respuestas se pueden usar para decidir qué plantilla usar.

Aquí están las 2 cosas que he encontrado mejor con EditorFor / DisplayFor:

  1. Respetan las jerarquías de modelo cuando representan ayudantes HTML (por ejemplo, si tiene un objeto "Barra" en su modelo "Foo", los elementos HTML para "Barra" se representarán con "Foo.Bar.ElementName", mientras que un parcial tendrá " ElementName ").

  2. Más robusto, por ejemplo, si tenía una List<T> de algo en su ViewModel, podría usar @Html.DisplayFor(model => model.CollectionOfFoo) , y MVC es lo suficientemente inteligente como para ver que es una colección y mostrar la única pantalla. para cada elemento (a diferencia de un parcial, que requeriría un bucle explícito para).

También escuché que DisplayFor muestra una plantilla de "solo lectura", pero no entiendo eso. ¿No puedo lanzar un formulario allí?

¿Puede alguien decirme algunas otras razones? ¿Hay una lista / artículo en algún lugar comparando los tres?


Answers

Solo para dar valor a mi 2c, nuestro proyecto utiliza una vista parcial con varias pestañas jQuery, y cada pestaña representa sus campos con su propia vista parcial. Esto funcionó bien hasta que agregamos una característica por la cual algunas de las pestañas compartían algunos campos comunes. Nuestro primer acercamiento a esto fue crear otra vista parcial con estos campos comunes, pero esto se volvió muy torpe al usar EditorFor y DropDownListFor para renderizar campos y desplegables. Para obtener los identificadores y los nombres únicos, tuvimos que renderizar los campos con un prefijo, dependiendo de la vista parcial primaria que lo representaba:

    <div id="[email protected](idPrefix)2" class="[email protected](idPrefix)" style="display:none">
    <fieldset>
        <label for="@(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label>

        <input name="@(idPrefix).Frequency"
               id="@(idPrefix)_Frequency"
               style="width: 50%;"
               type="text"
               value="@(defaultTimePoint.Frequency)"
               data-bind="value: [email protected](viewStatePrefix).RecurringTimepoints.Frequency"
               data-val="true"
               data-val-required="The Frequency field is required."
               data-val-number="The field Frequency must be a number."
               data-val-range-min="1"
               data-val-range-max="24"
               data-val-range="The field Frequency must be between 1 and 24."
               data-val-ignore="true"/>

        @Html.ValidationMessage(idPrefix + ".Frequency")

        ... etc

    </fieldset>
</div>

Esto se puso bastante feo, así que decidimos usar Plantillas de Editor, lo que resultó mucho más limpio. Agregamos un nuevo modelo de vista con los campos comunes, agregamos una plantilla de editor coincidente y representamos los campos usando la plantilla de editor desde diferentes vistas principales. La plantilla del editor representa correctamente los identificadores y los nombres.

Entonces, en resumen, una razón convincente para que usemos las plantillas del editor fue la necesidad de representar algunos campos comunes en varias pestañas. Las vistas parciales no están diseñadas para esto, pero las Plantillas del Editor manejan el escenario perfectamente.


EditorFor vs DisplayFor es simple. La semántica de los métodos es generar vistas de edición / inserción y visualización / solo lectura (respectivamente). Use DisplayFor cuando muestre datos (es decir, cuando genere divs y spans que contengan los valores del modelo). Use EditorFor cuando EditorFor / inserte datos (es decir, cuando genere etiquetas de entrada dentro de un formulario).

Los métodos anteriores son centrados en el modelo. Esto significa que tomarán en cuenta los metadatos del modelo (por ejemplo, podría anotar su clase de modelo con [UIHintAttribute] o [DisplayAttribute] y esto influiría en qué plantilla se elige para generar la interfaz de usuario para el modelo. También se usan generalmente para modelos de datos (es decir, modelos que representan filas en una base de datos, etc.)

Por otra parte, Partial está centrado en la vista, ya que le preocupa más la elección de la vista parcial correcta. La vista no necesariamente necesita un modelo para funcionar correctamente. Simplemente puede tener un conjunto común de marcas que se reutiliza en todo el sitio. Por supuesto, muchas veces desea afectar el comportamiento de este parcial, en cuyo caso es posible que desee pasar un modelo de vista apropiado.

No preguntaste sobre @Html.Action que también merece una mención aquí. Podría pensar que es una versión más potente de Partial que ejecuta una acción secundaria del controlador y luego presenta una vista (que generalmente es una vista parcial). Esto es importante porque la acción secundaria puede ejecutar lógica de negocios adicional que no pertenece a una vista parcial. Por ejemplo, podría representar un componente del carrito de compras. La razón para usarlo es evitar realizar el trabajo relacionado con el carrito de compras en cada controlador de su aplicación.

En última instancia, la elección depende de qué es lo que está modelando en su aplicación. También recuerda que puedes mezclar y combinar. Por ejemplo, podría tener una vista parcial que llame al EditorFor helper. Realmente depende de lo que sea su aplicación y cómo factorizarla para fomentar la reutilización máxima del código y evitar la repetición.


Sin duda, puede personalizar DisplayFor para mostrar un formulario editable. Pero la convención es que DisplayFor sea ​​de readonly y EditorFor que sea para edición. Cumplir con la convención asegurará que no importa lo que pase en DisplayFor , hará el mismo tipo de cosas.


Otra diferencia que no se ha mencionado hasta ahora es que una vista parcial no agrega prefijos de modelo mientras que una plantilla sí. Here es el problema.


ACTUALIZACIÓN: EN UNA APLICACIÓN MVC4

Cree una nueva aplicación MVC4 en blanco y agregue un área llamada Test, con una vista Test.cshtml y un controlador TestController.cs.

Así que descubrí algo ... aunque no estoy seguro de que sea una solución razonable. Después de jugar con las rutinas de registro de ruta, tener las áreas en el proyecto no rompe la funcionalidad de minúsculas.

namespace MvcApplication1.Areas.Test
{
public class TestAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Test";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        //This line breaks the functionality in the area registration.
        context.MapRoute(
            "Test_default", // Route name
            "Test/{controller}/{action}/{id}", // URL with parameters
            new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
            new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
            );
    }
}
}

Una solución:

Comenta las líneas

        //context.Routes.LowercaseUrls = true;
        //context.MapRoute(
        //    "Test_default", // Route name
        //    "Test/{controller}/{action}/{id}", // URL with parameters
        //    new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
        //    new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
        //    );

En RouteConfig.cs

namespace MvcApplication1
{
public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;

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

        routes.MapRoute(
            "Test_default", // Route name
            "Test/{controller}/{action}/{id}", // URL with parameters
            new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
            new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
            );
    }
}
}

En el método de acción del controlador de área

    public ActionResult Index()
    {
        // Key if statement to make sure the area maps correctly
        if (!this.ControllerContext.RouteData.DataTokens.ContainsKey("area"))
        {
            this.ControllerContext.RouteData.DataTokens.Add("area", "Test");
        }
        return View("Test");
    }

Resultado HTML para los enlaces en la página principal del proyecto.

 <ul id="menu">
   <li><a href="/">Home</a></li>
   <li><a href="/home/about">About</a></li>
   <li><a href="/home/contact">Contact</a></li>
   <li><a href="/test?area=Test">Test</a></li>
 </ul>

Sin embargo, tenga en cuenta que las variables de la cadena de consulta no están en minúsculas y no es una URL amigable para seo. Sin embargo, encuentra la vista. Esto es lo más cerca que he podido de usar esa bandera y hacer que las direcciones URL vayan en minúsculas.





asp.net-mvc asp.net-mvc-3 razor asp.net-mvc-partialview editortemplates