ASP.NET MVC - Typed ViewData proposal -


in project i'm working on, have lot of "read-only" pages don't have <form>s in; have lot of form pages have lot of readonly data pulled in controller.

ordinarily you'd use viewmodels , have 1 viewmodel per view , viewmodel contains of data view. seems fair enough, except there's problem:

in head, see viewmodel being representation , encapsulation of entire data sent view controller, viewmodel might contain data populated controller (such selectlistitem[] html.dropdownlistfor() data) cannot populated view , sent controller.

sure, possible have data part of viewmodel , manually re-populate before returning view in controller's httppost-handling method, feel needlessly complicates controller's code (and you'd have use updatemodel() instead of automatic updates happen when specify model argument action method).

my solution typed viewdata object. derive viewpage<tmodel> give viewpage2<tmodel,tdata> tdata : viewdatadictionary<tmodel> , override (or shadow) .viewdata property return instance of tdata instead..

my questions twofold:

  • subclassing viewpage seems easy enough, put logic handle initialisation of viewpage2<tmodel,tdata> class?
  • is there wrong approach?

i found way implement viewdata / viewmodel approach without messing asp.net mvc.

here's how did it:

this viewpage2 class exposes strongly-typed viewdata object views. unfortunately need use reflection avoid viewpage's behaviour of creating brand new viewdatadictionary, statically cached fieldinfo objects it's no more expensive mvc's dynamic controller/action lookup in routing.

public class viewpage2<tmodel,tdata> : viewpage<tmodel> tdata : viewdatadictionary<tmodel> { public viewpage2() : base() { } private boolean _datapresent; private tdata _data; public new tdata viewdata { { if( _datapresent && _data == null ) { _data = (tdata)base.viewdata; } return _data; } } // cached in static class state performance. private static readonly fieldinfo _viewpage1viewdata; private static readonly fieldinfo _viewpage2viewdata; static viewpage2() { type viewpage1 = typeof(viewpage<tmodel>); _viewpage1viewdata = viewpage1.getfield("_viewdata", bindingflags.instance | bindingflags.nonpublic ); type viewpage2 = typeof(viewpage); _viewpage2viewdata = viewpage2.getfield("_viewdata", bindingflags.instance | bindingflags.nonpublic ); } protected override void setviewdata(viewdatadictionary viewdata) { // viewpage<tmodel> creates new viewdatadictionary<tmodel> when method called, if viewdata of correct type. // trick reimplement setviewdata , set base._viewdata , basebase._viewdata if( viewdata tdata ) { _viewpage1viewdata.setvalue( this, viewdata ); _viewpage2viewdata.setvalue( this, viewdata ); _datapresent = true; } else { base.setviewdata( viewdata ); } } } 

then each *.aspx file (i use webformviewengine) change @page directive:

<%@ page language="c#" masterpagefile="~/site.master" inherits="me.viewpage2<me.formmodel,me.formdata>" %> 

i'll admit 2 generic type specifiers make bit fiddly, it's need set once.

then in each controller it's matter of doing this:

public actionresult edit() { formdata data = new formdata(); data.somestronglytypedfield = "foo"; this.viewdata = data; } 

in each view can benefit strongly-typed view data:

<p><%= viewdata.somestronglytypedfield %></p> 

and because viewdata not part of model there's separation of concerns when dealing post-submitted data , benefits of automatic binding:

 [httppost] public actionresult edit(editmodel model) { if( !modelstate.isvalid ) { // see how can return model object without modifying it. need re-create view data. formdata data = new formdata(); data.somestronglytypedfield = "foo"; this.viewdata = data; return view( model ); } // persist db here return redirecttoaction("view"); } 

in practice use common basecontroller class handles automatic creation , setting of viewdata objects don't need 3 lines (formdata data... etc) in every action.


Comments

Popular posts from this blog

javascript - backbone.js Collection.add() doesn't `construct` (`initialize`) an object -

php - Get uncommon values from two or more arrays -

Adding duplicate array rows in Php -