asp.net-mvc-4 diferencias - Pasar datos al diseño que son comunes a todas las páginas





entre web (10)


No creo que ninguna de estas respuestas sea lo suficientemente flexible para una aplicación de nivel empresarial grande. No soy fanático de usar en exceso el ViewBag, pero en este caso, por flexibilidad, haría una excepción. Esto es lo que haría ...

Deberías tener un controlador base en todos tus controladores. Agregue sus datos de diseño OnActionExecuting en su controlador base (u OnActionExecuted si desea diferir eso) ...

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext     
        filterContext)
    {
        ViewBag.LayoutViewModel = MyLayoutViewModel;
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View(homeModel);
    }
}

Luego, en su _Layout.cshtml extraiga su ViewModel del ViewBag ...

@{
  LayoutViewModel model = (LayoutViewModel)ViewBag.LayoutViewModel;
}

<h1>@model.Title</h1>

O...

<h1>@ViewBag.LayoutViewModel.Title</h1>

Hacer esto no interfiere con la codificación de los controladores de su página o ver modelos.

Tengo un sitio web que tiene una página de diseño. Sin embargo, esta página de diseño tiene datos que el modelo de todas las páginas debe proporcionar el título de la página, el nombre de la página y la ubicación en la que realmente estamos para una ayuda HTML que realicé y que realiza alguna acción. Además, cada página tiene sus propias propiedades de modelos de vista.

¿Cómo puedo hacer esto? Parece que es una mala idea escribir un diseño, pero ¿cómo paso las informaciones de tesis?




Crear una vista base que represente el modelo de vista Diseño es un enfoque terrible. Imagine que desea tener un modelo que represente la navegación definida en el diseño. ¿Haría CustomersViewModel : LayoutNavigationViewModel ? ¿Por qué? ¿Por qué debería pasar los datos del modelo de navegación a través de cada modelo de vista que tiene en la solución?

El modelo de vista Diseño debe ser exclusivo, y no debe obligar al resto de los modelos de visualización a depender de él.

En cambio, puede hacer esto en su archivo _Layout.cshtml :

@{ var model = DependencyResolver.Current.GetService<MyNamespace.LayoutViewModel>(); }

Lo más importante es que no necesitamos un new LayoutViewModel() y obtendremos todas las dependencias que LayoutViewModel tiene, resueltas para nosotros.

p.ej

public class LayoutViewModel
{
    private readonly DataContext dataContext;
    private readonly ApplicationUserManager userManager;

    public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
    {
    }
}



Otra opción es crear una clase LayoutModel por separado con todas las propiedades que necesitará en el diseño, y luego agregar una instancia de esta clase en ViewBag. Uso el método Controller.OnActionExecuting para poblarlo. Luego, al inicio del diseño, puede retirar este objeto de ViewBag y continuar accediendo a este objeto fuertemente tipado.




si quieres pasar un modelo completo, ve así en el diseño:

@model ViewAsModelBase
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8"/>
    <link href="/img/phytech_icon.ico" rel="shortcut icon" type="image/x-icon" />
    <title>@ViewBag.Title</title>
    @RenderSection("styles", required: false)    
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    @RenderSection("scripts", required: false)
    @RenderSection("head", required: false)
</head>
<body>
    @Html.Action("_Header","Controller", new {model = Model})
    <section id="content">
        @RenderBody()
    </section>      
    @RenderSection("footer", required: false)
</body>
</html>

y agregue esto en el controlador:

public ActionResult _Header(ViewAsModelBase model)



Otras respuestas han cubierto casi todo sobre cómo podemos pasar el modelo a nuestra página de diseño. Pero he encontrado una manera mediante la cual puedes pasar variables a tu página de diseño dinámicamente sin usar ningún modelo o vista parcial en tu diseño. Digamos que tienes este modelo:

public class SubLocationsViewModel
{
    public string city { get; set; }
    public string state { get; set; }
}

Y desea obtener la ciudad y el estado de forma dinámica. Por ej.

en su index.cshtml puede poner estas dos variables en ViewBag

@model  MyProject.Models.ViewModel.SubLocationsViewModel
@{
    ViewBag.City = Model.city;
    ViewBag.State = Model.state;
}

Y luego en su layout.cshtml puede acceder a esas variables viewbag

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>



Presumiblemente, el caso de uso primario para esto es obtener un modelo base para la vista para todas (o la mayoría de) las acciones del controlador.

Dado eso, he usado una combinación de varias de estas respuestas, respaldo primario en la respuesta de Colin Bacon.

Es correcto que sigue siendo lógica de controlador porque estamos rellenando un modelo de vista para volver a una vista. Por lo tanto, el lugar correcto para poner esto es en el controlador.

Queremos que esto suceda en todos los controladores porque lo usamos para la página de diseño. Lo estoy usando para vistas parciales que se muestran en la página de diseño.

También queremos el beneficio adicional de un modelo de vista fuertemente tipificado

Por lo tanto, he creado un BaseViewModel y BaseController. Todos los controladores ViewModels heredarán de BaseViewModel y BaseController, respectivamente.

El código:

BaseController

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;

        model.AwesomeModelProperty = "Awesome Property Value";
        model.FooterModel = this.getFooterModel();
    }

    protected FooterModel getFooterModel()
    {
        FooterModel model = new FooterModel();
        model.FooterModelProperty = "OMG Becky!!! Another Awesome Property!";
    }
}

Tenga en cuenta el uso de OnActionExecuted como tomado de esta publicación SO

HomeController

public class HomeController : BaseController
{
    public ActionResult Index(string id)
    {
        HomeIndexModel model = new HomeIndexModel();

        // populate HomeIndexModel ...

        return View(model);
    }
}

BaseViewModel

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}

HomeViewModel

public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}

FooterModel

public class FooterModel
{
    public string FooterModelProperty { get; set; }
}

Layout.cshtml

@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>

_Nav.cshtml

@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>

Espero que esto ayude.




Si tiene que pasar las mismas propiedades a cada página, entonces sería prudente crear un modelo de vista base que sea utilizado por todos sus modelos de vista. Su página de diseño puede tomar este modelo base.

Si se requiere lógica detrás de estos datos, entonces esto debe colocarse en un controlador base que sea utilizado por todos sus controladores.

Hay muchas cosas que podrías hacer, el enfoque importante es no repetir el mismo código en varios lugares.

Editar: actualización de los comentarios a continuación

Aquí hay un ejemplo simple para demostrar el concepto.

Cree un modelo de vista base del que heredarán todos los modelos de vista.

public abstract class ViewModelBase
{
    public string Name { get; set; }
}

public class HomeViewModel : ViewModelBase
{
}

Su página de diseño puede tomar esto como su modelo.

@model ViewModelBase
<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Test</title>
    </head>
    <body>
        <header>
            Hello @Model.Name
        </header>
        <div>
            @this.RenderBody()
        </div>
    </body>
</html>

Finalmente establece los datos en el método de acción.

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}



en lugar de pasar por esto siempre puedes usar otro enfoque que también es rápido

cree una nueva vista parcial en el Directorio compartido y llame a su vista parcial en su diseño como

@Html.Partial("MyPartialView")

en su vista parcial puede llamar a su base de datos y realizar lo que quiera hacer

@{
    IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
}

<div>
//do what ever here
</div>

asumiendo que ha agregado su base de datos de Entity Framework




Utilicé RenderAction html helper para la maquinilla de afeitar en el diseño.

@{
   Html.RenderAction("Action", "Controller");
 }

Lo necesitaba para una cadena simple. Entonces mi acción devuelve una cadena y la escribe fácilmente a la vista. Pero si necesita datos complejos, puede devolver PartialViewResult y modelar.

 public PartialViewResult Action()
    {
        var model = someList;
        return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
    }

Solo debe poner su modelo comenzando con la vista parcial '_maPartialView.cshtml' que creó

@model List<WhatEverYourObjeIs>

Luego puede usar datos en el modelo en esa vista parcial con html.




En realidad puedes (¡y deberías!) Escribir el código AngularJS para que sea "seguro para la minificación". Los detalles se describen en la sección "Anotación de dependencia" de http://docs.angularjs.org/guide/di pero en resumen, para los controladores definidos globalmente puede escribir:

MyController.$inject = ['$scope'];

Tenga en cuenta que los controladores definidos globalmente están contaminando el espacio de nombres global (vea this para más detalles) y deben evitarse. Si declara un controlador en un nivel de módulo, también puede hacerlo seguro para la minificación:

angular.module('mymodule', []).controller('MyController', ['$scope', function($scope){
//controller code goes here
}]);




asp.net-mvc-4