Here is the scenario, I need to load up a view model object from a several domain objects that are being returned from multiple web service service calls. The code that transforms the domain model objects into the digestible view model object is a bit of fairly complex code. The three places that I have thought about putting it are:
- Internal methods inside of the controller to load up an instance view model.
- Static get method or property on the view model class itself that returns a loaded instance of view model.
- An altogether separate builder or helper class that has a Static get method, property, or overloaded constructor that returns the loaded instance of view model.
To be clear, I don't want to use AutoMapper, or tools like it. From a best practices standpoint I'd like to know where this logic should go, and why.
EDIT
So here is what I have so far, this does give me "skinny" controller logic and separation of concerns. How can I make it better though?
// ** Controller **
public ActionResult Default()
{
var viewModel = MyViewModelBuilder.BuildViewModel(MarketType.Spot);
return View(SpotViewUrl, viewModel);
}
// ** Builder **
// Lives in MVC project under ViewModelBuilders folder
public class MyViewModelBuilder
{
public static ChartsModel BuildViewModel(MarketType rateMarket)
{
var result = new ChartsModel
{
RateMarket = rateMarket,
DateRange = new DateRange()
};
LoadGroupedRateLists(result, rateMarket);
LoadCoorespondingRates(result);
return result;
}
private static void LoadGroupedRateLists(ChartsModel model, RateMarket rateMarket)
{
var rateHistSvc = new RateHistoryService(RatesPrincipal.Current.Session.Token);
var serviceResult = (rateMarket == RateMarket.Spot)
? rateHistSvc.GetSpotNationalRateHistory()
: rateHistSvc.GetContractNationalRateHistory();
// Break lists apart by category, and re-sort and trim.
model.Cat1Rates = CategorizeTrimAndSort("cat1", false, serviceResult);
model.Cat2Rates = CategorizeTrimAndSort("cat2", true, serviceResult);
model.Cat3Rates = CategorizeTrimAndSort("cat3", false, serviceResult);
model.Cat4Rates = CategorizeTrimAndSort("cat4", true, serviceResult);
model.Cat5Rates = CategorizeTrimAndSort("cat5", false, serviceResult);
model.Cat6Rates = CategorizeTrimAndSort("cat6", true, serviceResult);
// Get Date range from results.
var sortedRateMonths = serviceResultNational
.Select(rate => rate.YearMonth)
.OrderBy(ym => ym.Year)
.ThenBy(ym => ym.Month);
model.DateRange.Start = sortedRateMonths.First();
model.DateRange.End = sortedRateMonths.Last();
}
...
}
custom
presentation transform code, because realistically every transform/mapping problem cannot be solved by Automapper. – Osseous