⬆️ ⬇️

Fighting the inheritance and nesting of the ViewModel when developing lolstore.info

Hello, harabrachitel.

I want to share the implementation of the bike , which came in the process of exploring Asp.Net Mvc and developing lolstore.info . It is convenient for me, it is possible that this will be for you.



First, we formulate the problem / goal:


Make it all hurt. Find a concise and transparent way to transfer several (!) Typed ViewModels from the controller to the View and render them with type checking at the compilation stage.



The situation becomes especially acute when you need one ViewModel (html title, accessible menu, etc.) for the masterpage, another page (for example, a list of anecdotes), and a third page for list (s). Plus it itches to keep easy portability of the same pagelets to other pages.



Well, let's start to understand:
Flight of thought:


What is each ViewModel each separately? - I thought, sipping tea. The answer has matured by itself: just a container for typed data is, if possible, without logic (I also like rendering logic in the HtmlHelper extension methods).

')

How to transfer some model to existing tools from controller to View? - a sip of drink, - mm, so there is ViewData, although at first it refused.



How to make type checking at compile time and get rid of string key search? - Generic to the rescue! - bit a cookie.



How to add the implementation, but that it was not necessary to be inherited from something for use? - Taki extensions.



...


Profit:


In fact, it all boiled down to two methods:

Other extensions are added for convenience only (there are only a couple of them):

public static TModel Model < TModel > ( this Controller controller )

{

return controller. ViewData . Model < TModel > ( ) ;

}



public static TModel Model < TModel > ( this HtmlHelper htmlHelper )

{

return htmlHelper. ViewData . Model < TModel > ( ) ;

}


As a plus, you can highlight:Few cons:
Using:


In the controller:
public ActionResult Default ( )

{

...

// drawn in pagelet

this . Model < TagListViewModel > ( ) . MyBlaBlaBlaProperty = " lolstore.info " ;



// used on the current for action-master page

this . Model < UserMenuViewModel > ( ) . MyBlaBlaBlaProperty2 = "Jokes" ;

}


On View without strong-type inheritance:

<% = this . Model < TagListViewModel > ( ) . MyBlaBlaBlaProperty %>


In HtmlHelper:

public static MvcHtmlString RenderSomething ( this HtmlHelper htmlHelper )

{

if ( ! htmlHelper. ModelExists < TagListViewModel > ( ) )

{

return new MvcHtmlString ( String. Empty ) ;

}



TagListViewModel model = htmlHelper. Model < TagListViewModel > ( ) ;

// render what the thread

}


The whole entire single code file can be downloaded here .



ZY If such experiments are interesting to habravchanam and can be applied not only in my projects, then I will lay out the implementation of concurrent and asynchronous caching, a simple AutoMapper (used to clone one type of objects into another without inheritance, interfaces, but tested at the compilation stage) and other utility .



By EugeneOstapchuk

Source: https://habr.com/ru/post/126212/



All Articles