asp.net-mvc - studio - tutorial asp net mvc
Cómo crear una página maestra fuertemente tipada usando un controlador base en ASP.NET MVC (2)
En lugar de crear un atributo, ¿por qué no simplemente invalidar Controller.OnActionExecuted y colocar el código de inicialización allí? Parece un poco más simple.
Siguiendo el ejemplo de NerdDinners , estoy interesado en crear una página maestra fuertemente tipada. Para lograr esto, uso un controlador base que recupera los datos de la página maestra. Todos los demás controladores heredan esta clase. Del mismo modo, tengo ViewModels
para la página maestra y cualquier otra vista. Las clases de ViewModel
vista heredan de ViewModel
de la página ViewModel
.
Pregunta
¿Cómo debe un controlador secundario asegurarse de que los datos de la página maestra se pasen a la Vista sin establecer las propiedades de su ViewModel
que pertenecen a la página maestra?
Mi página maestra mostrará una serie de botones, que se determinan en un archivo XML, de ahí la clase de Buttons
que estoy llenando.
Fragmento de código de MasterPage ViewModel
using System.Collections.Generic;
namespace Site1.Models
{
public class MasterViewModel
{
public List<Button> Buttons{set; get;}
}
}
Ver ViewModel
namespace Site1.Models
{
public class View1ViewModel : MasterViewModel
{
public SomeDataClass SomeData { get; set; }
}
}
Controlador base
using System.Collections.Generic;
using System.Web.Mvc;
using Site1.Models;
namespace Site1.Controllers
{
public abstract class BaseController : Controller
{
protected MasterViewModel model = new MasterViewModel();
public BaseController()
{
model.Buttons = new List<Button>();
//populate the button classes (doesn''t matter how)
PopulateButtons(model.Buttons);
}
}
}
Controlador de la vista:
using System.Web.Mvc;
namespace Site1.Controllers
{
public class View1Controller : BaseController
{
public ActionResult Index()
{
Models.View1ViewModel viewModel = new Models.View1ViewModel();
SomeDataClass viewData = new SomeDataClass()
//populate data class (doesn''t matter how)
PopulateDataClass(viewData);
viewModel.SomeData = viewData;
//I WANT TO ELIMINATE THE FOLLOWING LINE!
viewModel.Buttons = model.Buttons;
return View("Index", viewModel);
}
}
}
La página maestra hereda System.Web.Mvc.ViewMasterPage<Site1.Models.MasterViewModel>
.
La vista hereda System.Web.Mvc.ViewMasterPage<Site1.Models.View1ViewModel>
.
Podría crear un filtro de acción posterior que busque un modelo de ese tipo y establezca las propiedades en consecuencia, tal vez llamando a una función de controlador base. Luego pondría el filtro en la clase base y todas las acciones lo verían automáticamente.
El atributo de filtro de acción obtiene el ViewModel
del controlador y lo pasa a la función SetModel
del controlador:
using System.Web.Mvc;
using Site1.Controllers;
namespace Site1.Models
{
public class MasterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
MasterViewModel viewModel = (MasterViewModel)((ViewResultBase)filterContext.Result).ViewData.Model;
BaseController controller = (BaseController)filterContext.Controller;
controller.SetModel(viewModel);
}
}
}
Esta función se agrega a BaseController
:
public void SetModel(MasterViewModel childViewModel)
{
childViewModel.Buttons = model.Buttons;
}