Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the best practices for Asp.net MVC page construction, allowing for parallelism and efficiency?

I found it difficult to argue with anything in this critique of ASP.net MVC's framework for page composition.

http://www.matlus.com/problems-with-asp-net-mvc-framework-design/

Particularly these points:

  • No access to view or partial view instances
  • ViewData is your loosely typed information carrier
  • Controller is not really in control
  • Child Actions have no sense of the Request Context
  • Views are coupled to controllers

For small applications, I don't think that a lot of these prove to be much of a problem, but in large applications where you want to reuse a lot of shared components, or even if you just have a large application that depends on multiple backend sources of information to obtain all of the information necessary to render a view, it starts to break down.

Various half-solutions to these problems have been proposed but they do not appear to scale well or have undesirable design constraints.

Here is an example application scenario:

  1. 50% of page content is common across all pages within an application (header, footer, menus, etc.)
  2. Your application may actually be comprised of multiple areas, each with their own controllers, etc. for independent development.
  3. A number of the page elements (menus, page header information, footers, disclosures) that are in the common page content require one or more service calls to fill out the data for rendering.

Okay, so in asp.net mvc3, let's say that you decide that you want to share a common Razor layout that contains the 50% common UI markup. This assists with Separation of Concerns in that application developers don't need to be concerned about common ui and can focus on the logic and views specific to their domain of expertise.

However, this completely breaks down in the case that this shared layout needs data (some semblance of one or more model types) to render itself completely. You may have independent elements on the page that each need a particular data model, such as: * primary menu model * secondary menu model * footer links model * authorization model * footer disclaimers model

And each of these models may have separate sources. So although you can share the template, there is not an easy way to share the logic to build each of these models -- and there is definitely not one that is generic, extensible, and performant that I have seen.

Some approaches to this problem that I have seen are:

  • Strongly type the common layout, which requires all view models to subclass a common base model class. (but there is no general solution to populating such a meta-model, and this is limiting in design and makes models huge and harder to test) Additionally, model population still falls to every controller, violating the Separation of Concerns and Single Responsibility Principle and complicating unit testing controllers by piling on lots of extra logic to populate the meta-model in addition to the view-specific model information.
  • Leave the common layout untyped, so you don't have to inherit from a common base model, but this requires you to use ViewData or ViewBag to communicate all of the disparate models that the template needs so you lose strong typing benefits and end up with a loose data contract. You still have the problem of a lack of a general solution to populating the meta-model and all that goes along with that.
  • Every controller has to subclass a common base controller class to support a common layout and model. Logic for building the common aspects of the meta-model goes here. But this is not always a desirable architecture or design constraint. This does at least resolve the Separation of Concerns issues.
  • Instead of a meta-model, use child actions via RenderAction() in your common layout to make reusable "portlet" style widgets that each know independently how to build their data model and provide it to their view. This is really good for Separation of Concerns, but has its own litany of downsides: views effectively making service calls during rendering via the child actions, child actions are completely unaware of the original request context, violates DRY principle as each child action is unaware of what has gone before it so each could make the same service calls over and over again in the same http request, and others. Imagine 20-30 elements of a page that all needed to invoke RenderAction() independently...

There are additional cases (some seen on stackoverflow as well) where there are other problems with RenderAction() as a solution. e.g. the fact that issuing multiple RenderAction() calls in a loop results in serial execution of all of those controller methods. There is no opportunity for parallelism with RenderAction(). I/O bound service calls in each child controller action cause the whole rendering process to wait on I/O. A controller only has knowledge of its immediate view and model and nothing has a complete picture of what is going to be inside the view in order to parallelize some operations.

The author of the above critique developed a different UI model on top of ASP.Net mvc called Quartz that allows a God Controller to have intimate knowledge of the views and can hand each of them a view model so has the opportunity to parallelize service calls in a central place to build those view models. I don't know if this is the best design to provide hooks for overcoming the problems but looks promising.

My question is, what is the best practice for building a complex application on top of ASP.Net MVC that cleanly solves these problems? I have thought of a couple possibilities (although none may be practical within ASP.Net MVC--that is TBD) but someone else must have ran into this already. What are the design patterns within ASP.Net MVC or what is coming down the pike that could make this a tractable problem?

like image 1000
core24 Avatar asked Dec 21 '11 23:12

core24


People also ask

What is MVC architecture in asp net with C# with example?

The Model-View-Controller (MVC) architectural pattern separates an application into three main components: the model, the view, and the controller. The ASP.NET MVC framework provides an alternative to the ASP.NET Web Forms pattern for creating MVC-based Web applications.

How do you execute a method in ASP.NET MVC for every 24 hours?

You can create an external trigger that calls into your MVC action method every 24 hours. So you are executing your code every 24 hours. There are multiple ways and services to do that, i have used different services. Or you can create your own if you do not want to use third party.


2 Answers

Personally, I think that the advantages of using Child Actions via RenderAction outweigh the disadvantages.

You can create 'widget' sort of elements, and wrap up their logic in a controller action - this way the view calling the widget can remain quite ignorant of what the Child Action is doing and how it is doing it - leading to a nice separation of concerns.

You have detailed the disadvantages of this approach, however I think that the negative impact can be minimised with a reasonable caching strategy.

like image 120
StanK Avatar answered Oct 19 '22 23:10

StanK


I'm not sure there's really much more I can contribute to this "question". I think you have a good understanding of the problems and solutions, advantages and disadvantages.

In the app I'm currently working on, we utilize a couple of these approaches by having both a base model object as well as a base controller. In order to minimize roundtrips, we store some data in session and re-populate in the model by overriding the OnActionExecuted in the base controller and grab the model out of the context and set properties out of session.

I'd certainly like to hear any wonderful solutions as well, but I think these are just the tradeoffs to deal with.

like image 35
Matt Klinker Avatar answered Oct 19 '22 23:10

Matt Klinker