asp.net mvc - Where do you like to put MVC view model data transformation logic? -


here scenario, need load view model object several domain objects being returned multiple web service service calls. code transforms domain model objects digestible view model object bit of complex code. 3 places have thought putting are:

  1. internal methods inside of controller load instance view model.
  2. static method or property on view model class returns loaded instance of view model.
  3. an altogether separate builder or helper class has static method, property, or overloaded constructor returns loaded instance of view model.

to clear, don't want use automapper, or tools it. best practices standpoint i'd know logic should go, , why.

edit

so here have far, give me "skinny" controller logic , separation of concerns. how can make 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 category, , re-sort , 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);               // date range 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();         }             ...     } 

1 or 3, not 2. provided if #3, not let static method web service calls, let mapping. domain object(s) in, viewmodel(s) out. prefer extension method overloaded constructor, if object doesn't need track state, there's no benefit making non-static.

why?

as put logic method on model, ceases poco. best practice treat viewmodels boring data buckets as possible. people try mapping in viewmodel constructor not idea once kind of complexity in mapping.

if need mapping in 1 controller, can put in sub-routine. keep in mind if want test sub in isolation , keep internal, project have have internalsvisibleto test project.

update

after looking @ code, kind of inclined agree @c sharper belongs neither in controller, viewmodel, nor helper class / method. composing chartsmodel interesting code, , contains lot of business logic. should in separate layer. controller should call down layer , delegate of interesting , important code abstraction. abstraction should return domain object, @c sharper said. whether use domain object viewmodel, or dto different viewmodel, you. here's how might like:

public class mycontroller : controller {     private readonly icomposechartdata _chartdatacomposer;      public mycontroller(icomposechartdata chartdatacomposer)     {         _chartdatacomposer = chartdatacomposer;     }      public actionresult default()     {         var chartcomposition = new chartcompositionsettings         {             markettype = markettype.spot,             token = ratesprincipal.current.session.token,         };         var chartdata = _chartdatacomposer.composechartdata(chartcomposition);         var chartmodel = mapper.map<chartsmodel>(chartdata);         return view(spotviewurl, chartmodel);     } } 

that nice lean controller body. abstraction might this:

public class chartdatacomposer : icomposechartdata {     public chartdata composechartdata(chartcompositionsettings settings)     {         // of interesting code goes here     } } 

this way, viewmodel not need move out separate layer, need create similar object (chartdata) in layer. interface decouples controller data needs, , object returns cohesive presentation data (viewmodel).

i guess don't see code business logic, more presentation logic. why see business logic?

think of ratehistoryservice class supplier. receive raw materials it, , transform raw materials different, creating value in process. businesses do.

in case, chart visualizations value providing. otherwise, customers have sift through raw data, trim it, categorize it, sort it, group it, etc., before create similar charts.

i should have explained earlier, service calls our own business layer already, , return domain layer business objects. seems weird me have more 1 business layer.

your business layer can have own internal layering. in case, can create ratechartingservice uses ratehistoryservice return ratechartingresult busines object. map chartsmodel (or said before, use directly viewmodel).


Comments

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -