Reputation: 3389
I have the following method in five controllers:
public ActionResult Index(string page, string title) {
var vm = new BaseViewModel();
vm.Role = GetRoleNumber(User);
vm.MenuItems = contentService.GetMenuItems("00", vm.Role);
vm.Menu = pageService.GetMenu(vm.MenuItems, Request.FilePath);
// difference code here for each controller
}
All my controllers inherit from a controller called BaseController.
Is there a way I could move this code into my base controller and call it? If so then what would be the best way to implement this?
Upvotes: 1
Views: 1374
Reputation:
You could make an abstract ActionResult
method in your base controller:
protected BaseViewModel vm;
public ActionResult Index(string page, string title) {
vm = new BaseViewModel();
vm.Role = GetRoleNumber(User);
vm.MenuItems = contentService.GetMenuItems("00", vm.Role);
vm.Menu = pageService.GetMenu(vm.MenuItems, Request.FilePath);
try
{
return IndexSupplemental();
}
catch(NotImplementedException ex)
{
// Log and move on; the abstract method is not implemented.
}
return View();
}
protected abstract ActionResult IndexSupplemental();
Then every controller would have to implement this abstract method.
Upvotes: 3
Reputation: 5227
In my projects most of my actions will return a viewmodel that inherits from the BaseViewModel but there are exceptions to this. So what I did was something like this in ControllerBase:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var authData = GetUserData();
if (authData != null)
{
var result = filterContext.Result as ViewResult;
if (result != null)
{
var vm = result.Model as ViewModelBase;
if (vm != null)
{
vm.UserId = authData.UserID;
vm.UserName = User.Identity.Name;
}
}
}
}
What you could do otherwise, as I expect your ViewModel to be of different types, is to create a method similar to this in ControllerBase:
NOTE This does not do what you want. I'm just showing a technique for creating a new instance of a derived class with some initialization code.
protected T Command<T>() where T : BaseCommand, new()
{
var command = new T();
command.IP = Request.UserHostAddress;
if (User != null && User.Identity.IsAuthenticated)
{
var authData = GetUserData();
if (authData != null)
{
command.UserId = authData.UserID;
}
}
return command;
}
Which would be used as
var command = Command<CreateUserCommand>();
Upvotes: 1
Reputation: 38488
You can move it to a method in your base controller and call it when you need it.
public class BaseController : Controller
{
protected BaseViewModel _viewModel;
public void InitializeViewModel() {
vm = new BaseViewModel();
vm.Role = GetRoleNumber(User);
vm.MenuItems = contentService.GetMenuItems("00", vm.Role);
vm.Menu = pageService.GetMenu(vm.MenuItems, Request.FilePath);
}
}
An example:
public class MyController : BaseController
{
public ActionResult Index(string page, string title)
{
InitializeViewModel();
DoSomething(_viewModel);
}
}
Upvotes: 2
Reputation: 1407
This is an exact candidate for the Repository Pattern. You could create all of these in your Repository class and call that method in each ActionResult method
public void Repository : IRepository
{
public GetMyBaseViewModel()
{
//..implementation here
}
}
public interface IRepository
{
BaseViewModel GetMyBaseViewModel();
}
.... and in your controllers : ...
public class HomeController : Controller
{
//private repository member
private readonly IRepository _repository;
//controller constructors
//injecting the repository here
public HomeController() : this(new Repository())
{
}
public HomeController(IRepository repository)
{
_repository = repository;
}
//methods that call the repository for the vm data context
public ActionResult Index()
{
var vm = _repository.GetMyBaseViewModel();
return View();
}
}
Upvotes: 4