Question

I am working on a large ASP.NET MVC Project(about 15 separate projects). We are using a Facade Design Pattern to call Business logic as well as other Projects.

Question: in MVC application is it a best practice to call a Facade from the ViewModel?

I am using single facade instances to call all the functions. I create a ViewModel for each Action and populate it with data from within the ViewModel. These results are making the ViewModel larger, but the Controller Action gets thinner because we are doing the work in the ViewModel now. In the ViewModel constructor I pass the facade instance and take what's needed from the business logic layer.

public class MyViewModel
{
    private Facade _Facade;
    public IEnumerable<SomeModel> Collection { get; set; }
    public IEnumerable<SelectListItem> Years { get; set; }
    public IEnumerable<SelectListItem> Quarters { get; set; }
    public int SelectedYear { get; set; }
    public int SelectedQuarter { get; set; }


     public BottomUpForecastViewModel(EXFacade facade)
    {
        this._Facade = facade;
        this.Years = GetFinancialYears();
        this.Quarters = GetFinancialQuarters();
        this.SelectedYear = DateTime.Now.Year;
        this.SelectedQuarter = TimePeriods.GetQuarterNoForDate(DateTime.Now);
        Collection = GetMonthlyCollection(SelectedYear, SelectedQuarter);// Take data     from the _Facade(call facade)

    }

}

  public class MyController : Controller
  {


    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult BottomUpForecast()
    {

        return View(new MyViewModel(facade));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult BottomUpForecast(MyViewModel model)
    {

        return View();

    }

}

Is this good practice?

Do you have a suggestion for a better approach taking into consideration that we don't need to worry about Dependencies?

UPDATE : I found an interesting article about how to make controllers Lean "Put them on a diet": http://lostechies.com/jimmybogard/2013/12/19/put-your-controllers-on-a-diet-posts-and-commands/**

Was it helpful?

Solution

Your idea is correct. Perfectly acceptable to call business logic from View Model. I do it all the time.

Unfortunately, your current implementation is strongly coupled to concrete types. You could use a little abstract refactoring:

In stead, in your Business layer, create an Interface, IEXFacade to pass bind your object and pass to your ViewModel:

public interface IEXFacade
{
   public IEnumerable<SomeModel> GetMonthlyCollection(int SelectedYear, int SelectedQuarter);
   public IEnumerable<SelectListItem> GetFinancialYears();
   public IEnumerable<SelectListItem> GetFinancialQuarters();
   public int getSelectedYear();
   public int getSelectedQuarter(DateTime dateTime);
}

and your EXFacade definition would look something like:

public class EXFacade : IEXFacade
{
   private TimePeriods _timePeriods = new TimePeriods();

   public int getSelectedYear()
   {
       return DateTime.Now.Year;
   }

   public int getSelectedQuarter (DateTime dateTime)
   {
       return _timePeriods.GetQuarterNoForDate(dateTime);
   }


   public IEnumerable<SomeModel> GetMonthlyCollection()
   {
           ....
           return MonthlyCollection;
   }

   public IEnumerable<SelectListItem> GetFinancialYears();
   {
           ....
           return MonthlyCollection;
   }

   public IEnumerable<SelectListItem> GetFinancialQuarters();
   {
           ....
           return MonthlyCollection;
   }

}

Now your View Model would take IEXFacade and would be more tolerant of change

public class MyViewModel
{
     MyViewModel(IEXFacade facade)
     {
        Years = facade.GetFinancialYears();
        Quarters = facade.GetFinancialQuarters();
        SelectedYear = facade.getSelectedYear();
        SelectedQuarter = facade.getSelectedQuarter (DateTime.Now);
        Collection = facade.GetMonthlyCollection(SelectedYear, SelectedQuarter);
    }


    //Keeping the Facade Object seems extraneous (unless I'm missing something)
    //private Facade _Facade;
    public IEnumerable<SomeModel> Collection { get; set; }
    public IEnumerable<SelectListItem> Years { get; set; }
    public IEnumerable<SelectListItem> Quarters { get; set; }
    public int SelectedYear { get; set; }
    public int SelectedQuarter { get; set; }
}

The goal is to de-couple dependence on your specific implementation of your EXFacade class by passing an interface. Now your EXFacade methods logic can change without breaking your view model. As long as the Interface (properties and signatures) remain the same.


Conclusion:

I'm not partial to calling logic directly from my ViewModel, as opposed to my Controller. But, it's often more convenient as it saves a step. Conversely, logic injected directly into your model is less obvious than if you consolidate it into your controllers. But the argument about "Fat Controllers" vs "Fat Models" is pretty even sided and I don't think either side is more correct.

What's more important is to understand that the Facade Pattern is meant to be an interface between your "Chatty" Logic Layer and your Presentation Layer. For the sake of Abstraction and de-coupling, the pattern calls for an Interface. As soon as you abstract your Facade with an Interface you can further de-couple by using an IOC container like NInject to Inject your Facade into your controllers or Models.

I strongly recommend using the Dependency Injection pattern in a large project like this.

OTHER TIPS

You'll be breaking the MVC pattern if you put business logic in the ViewModel. It's controller's job to construct the view, not the view constructing itself by receiving depenencies.

The ViewModel should be ignorant of other layers(View and Controller), thereby promoting loosely coupled architecture.

If your ViewModel becomes too large, you can create helper methods or classes just for constructing the ViewModel.

public class MyController : Controller
{
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult BottomUpForecast()
    {
        return View(this.GetMyViewModel());
    }


    private MyViewModel GetMyViewModel()
    {
        var viewModel = new MyViewModel()
        {
            Years = this.facade.GetFinancialYears();
            Quarters = this.facade.GetFinancialQuarters();
            SelectedYear = DateTime.Now.Year;
            SelectedQuarter = this.facade.TimePeriods.GetQuarterNoForDate(DateTime.Now);
            Collection = this.facade.GetMonthlyCollection(SelectedYear, SelectedQuarter);
        }

        return viewModel;
    }
}

// Thin ViewModel
public class MyViewModel
{
    public IEnumerable<SomeModel> Collection { get; set; }
    public IEnumerable<SelectListItem> Years { get; set; }
    public IEnumerable<SelectListItem> Quarters { get; set; }
    public int SelectedYear { get; set; }
    public int SelectedQuarter { get; set; }
}

Interesting discussion about this topic here: https://stackoverflow.com/a/1464030/1027250

The view model is a model for the view. It should contain data (model) and any logic required to move that data into and out of the view. It shouldn't know anything about any other layers. It shouldn't even depend on the controller, never mind anything below that. It's the job of the controller to populate that view model so the job of the controller to invoke the business logic.

Just to add to @Yorro post, MVVM actually uses this pattern where VM is responsible for all such activities. It will be preferred to use Controller for such actions in MVC.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top