Published: 20 Aug 2010
By: Brian Mains

At times, every developer has a web forms page or MVC view that ends up getting pretty complex, for various reasons. Whether it pulls in and integrates a lot of data (such as a portal page) or allows users to edit a lot of information, applications require data, and the amount of data grows over time. It’s a simple reality. We’re going to examine what a larger ASP.NET MVC view looks like, and some actions we can take to keep the model instantiation code as slim as possible.

Contents [hide]

The ASP.NET MVC 2 Series

  • Introduction to ASP.NET MVC 2.0 In this article, we'll begin examining the new features of ASP.NET MVC 2.0 by comparing what ASP.NET MVC offers against its predecessor, ASP.NET web forms.
  • ASP.NET MVC 2.0 User Interfaces The next part to this article series on MVC 2.0 is the user interface. We saw in the last article some basics on the changes of the user interface, which we'll delve into more in this article series. Here we will begin to look at how developers can construct the view user interface.
  • ASP.NET MVC 2.0 Using Multiple Actions Brian Mains explains how to use multiple actions in ASP.NET MVC 2.0.
  • ASP.NET MVC 2.0 Templating Templating is now in the ASP.NET MVC 2.0 framework, for .NET framework 3.5 and 4.0. We are going to take a look at these features.
  • ASP.NET MVC 2.0 Attributes An overview of ASP.NET MVC 2.0 Attributes.
  • ASP.NET MVC 2.0 Validation An overview of validation in ASP.NET MVC 2.0.
  • ASP.NET MVC 2.0 Areas A look at ASP.NET MVC 2.0 Areas.
  • ASP.NET MVC 2.0 and AJAX Part 1 ASP.NET MVC makes working with AJAX really easy; it's quite impressive how powerful the framework can be. JQuery adds extra features and makes AJAX calls really easy; we'll see that all here soon.
  • ASP.NET MVC 2.0 and AJAX Part 2 In this article, we are going to look at how you can utilize AJAX in your views, and utilize a concept called unobtrusive JavaScript to take advantage of a variety of situations. ASP.NET MVC provides AJAX features very easily as we previously saw, but this comes with a caveat, and it has mostly to do with the planning of the implementation. We’re going to examine these concerns in this article.
  • ASP.NET MVC 2.0 and ADO.NET Entity Framework - Part 1 In this article, we'll examine using the ADO.NET Entity Framework (ADO.NET EF). The 4.0 version has received some major upgrades, with some major API enhancements and fixes for most of the pain points within the designer.
  • ASP.NET MVC 2.0 and ADO.NET Entity Framework - Part 2 Out of the .NET framework 4.0 comes many great enhancements, the ADO.NET entity framework (ADO.NET EF) is among the top. The framework has improved upon some of the previous bugs (in version 1), as well as enhanced the API, including many new LINQ-to-SQL-like improvements. We're going to examine using these API features to create a generic version of of a data repository.
  • Complexity in ASP.NET MVC, Part 1: Dealing With Large Models At times, every developer has a web forms page or MVC view that ends up getting pretty complex, for various reasons. Whether it pulls in and integrates a lot of data (such as a portal page) or allows users to edit a lot of information, applications require data, and the amount of data grows over time. It’s a simple reality. We’re going to examine what a larger ASP.NET MVC view looks like, and some actions we can take to keep the model instantiation code as slim as possible.
  • Complexity in ASP.NET MVC, Part 2: Plan your AJAX Carefully Brian Mains discusses management of Ajax requests in ASP.NET MVC.
  • Using DI Containers in ASP.NET MVC How to use Dependency Injection containers in ASP.NET MVC.
  • Using Microsoft Unity in ASP.NET MVC Brian Mains continues his asp.net series with the unity application block.
  • Introduction

    At times, every developer has a web forms page or MVC view that ends up getting pretty complex, for various reasons. Whether it pulls in and integrates a lot of data (such as a portal page) or allows users to edit a lot of information, applications require data, and the amount of data grows over time. It's a simple reality.

    We're going to examine what a larger ASP.NET MVC view looks like, and some actions we can take to keep the model instantiation code as slim as possible. I mean slim not as reduced features, but as reduced lines of code in a single file, as a means to help maintenance and increase readability.

    Passing Model Data

    Our first sample creates a portal page that displays information about a disc golf team (disc golf is a recreational sport, but it is also a professional one too). This page makes use of a variety of data sources and displays it all on one page. In web forms, we typically would load this data during the Page's init or load lifecycle. The ASP.NET MVC example does something similar; it loads it in the controller's action method, which creates the view with the following data as in Listing 1.

    Listing 1: Sample Portal Page Action Method

    While still a small example, you can see what it would be like if we had 15 to 20 properties with data sets that needed passed to the underlying view. You can see embedding all that code in one action method would make maintenance harder and bloat the method. The first step is to make a new method for each result set, as our first refactoring, which would yield the Listing 2 result.

    Listing 2: Extracting Method Refactoring

    But even then, we still are dealing with a lot of methods in the same object.

    The controller could apply the Singular Responsibility Principle and move these methods outside of the controller to an object responsible for loading each result set. Then our action method can instantiate these objects to get the data it needs, reducing many lines of code to two (one for instantiating the object, and a second to return the data from a method call). Alternatively, we could look at making the controller class a partial class, and spread out the method calls to a second file. This would greatly reduce the lines of code in one single file.

    Partial Views vs. Action

    While this all would work, we are going to look at other practical alternatives to this issue. The first of the options being the Html.Action method this article series discussed previously. This helper injects a controller's response directly into the view (such as rendering a partial view, general content, etc.). This, however, does not pass a model to it directly.

    Let's look at the difference between a view with a bunch of partial views, and a series of Html.Action calls. If we were to implement both implementations within the view, each would look like the following examples. Starting with partial view implementations, the view is changed to look like the following:

    Listing 3: Using Partial Views

    Here the main view has to supply data to each of the partial view references. The model also explicitly defines the partial view to use by specifying its identifier to use for routing.

    Using Html.Action, this changes the view to look like the following:

    Listing 4: Using Actions

    Actions work much differently; actions don't specify the partial view to use, but the name of the action method to call on the server. The action method then is responsible for returning the correct partial view. Additionally, the model isn't supplied to Html.Action; rather, routing parameters are passed through a routing dictionary or anonymous class.

    If each of these actions queried against a database, using this approach may result in more queries against the database (since each model is loaded separately); yet, each region is isolated from the main view, and thus the main view isn't responsible for loading its data. In fact, it could load data from alternative controllers, thus keeping the controller small.

    Dependency Injection

    Getting into the ALT.NET realm, another approach that could save us some time is using Dependency Injection (DI). Say for instance, we are loading reference data in our controller to pass to a view drop down, list, etc. Instead of manually writing code to load it, we could write our own code or use a DI container to inject the additional references, saving us work.

    I'm going to choose to write my own code sample to illustrate the process of DI. When working with DI, we need to have two things: an identifier to specify where to inject values into, and the object to inject. For instance, suppose the TeamPortalModel class had reference table of string values stored in a property called DiscTypes, (a List<string>). This reference data will always be the same, so rather than potentially writing the same code in different controllers, let's link it via injection. To start, we need to identify properties within a model, using an identifier that says "inject something into this property's setter", which is the purpose of the ModelInjectionAttribute class:

    Listing 5: ModelInjectionAttribute definition and its usage

    Other DI containers can also inject references through a constructor, but I'm choosing to skip that option in this article. The ModelInjection attribute identifies that the DiscTypes will be the target of an injection. Next, something needs to perform the injection: I delegate this to a class to do the work. The IModelInjector interface defines the structure that will return the injected values. Here our reference data is returned.

    Listing 6: Code/Interface for Injected Results

    Note that ModelSettings contains the information about the model and about the property being injected into, including the type (if we wanted to ensure type safeness, but in this case, I know that the property defines a List<string> type). Here I could simply wrap a DI container like Unity or Castle, but this injection was simple to do without the need for one.

    The identifier attribute is defined for the property, and we have an object that will return the reference data, but how do we know Property DiscTypes in the model needs data from injector DiscTypesModelInjector? In comes the manager for this.

    Listing 7: The Repository of Mappings and Its Usage

    This is the key to the relationship aspect of DI mapping. The manager maps a key to the injector that will do the work, something our action method will use soon. This allows for us to embed register statements within the global.asax file.

    Lastly, to use dynamic injection means giving up the rights to use an object directly. We need to run the model through a static class before we can return it directly. Enter the ModelChecker class (yes, I'm bad with class naming). The following shows the action method with our new class.

    Listing 8: Performing the Injection

    ModelChecker does the actual work of supplying the DiscTypes property in the model with a list of values. ModelChecker loops through each property one by one, and performs a series of checks:

    1. Find the properties with our ModelInjectionAttribute
    2. Looping through the properties, access the attribute.
    3. The attribute stores the IModelInjector type in the attribute directly, as shown above. The object is instantiated.
    4. If the object is not null and an IModelInjector, the Inject method is called.
    5. The returned value is injected into the property's setter.

    Take a look at how that happens below.

    Listing 9: Injecting Data into Properties

    The TypeDescriptor class is handy; using LINQ, it's very easy to get the properties of a model, and then check the attributes collection for our specific collection. Once we have the property/attribute mapping, the injector loops through the results, gets the injector, and calls SetValue on the property to pass on the final results.

    While this may seem like a lot, it's very easy. It only used 6 files, and we can write less code within the controller. Furthermore, it's a testable solution as we can test each and every component individually, then test the final result through the action result. Or, we can inject fake model injectors in the test environment, and test an action method in a controlled environment.

    Room to Grow

    There are ways to grow this solution; after all, how do we make dependency injection sensitive to the context of the action method to include DI into other areas of the model? There can be ways to make it more than just about reference data, but there are challenges with that.

    Refactoring ModelChecker

    Instead of calling ModelChecker.Check every time, we could also add an extension method or a method to a custom controller base class that does the same work as the View() method, but wraps the model with the ModelChecker.Check method, reducing the same code being called over and over again.

    DI Containers

    Can I use a Dependency Injection container to do this? Certainly you can, but I found one complexity with using a DI container like Unity. These containers use a contract type to define when to inject the real value. Typically, an interface is used to identify the contract, and then the actual value gets injected at runtime, though a contract isn't required to be an interface. The problem here is that we are dealing with List<string> as the model type, using the same type for every contract and separating each one by a key. I'm not discounting a DI container; these components are very handy and helpful in developing applications.

    Conclusion

    We looked at a few ways to reduce the complexity of controller action methods, or at least ways to deal with growing large actions and their models due to more and more features within the page.

    The ASP.NET MVC 2 Series

  • Introduction to ASP.NET MVC 2.0 In this article, we'll begin examining the new features of ASP.NET MVC 2.0 by comparing what ASP.NET MVC offers against its predecessor, ASP.NET web forms.
  • ASP.NET MVC 2.0 User Interfaces The next part to this article series on MVC 2.0 is the user interface. We saw in the last article some basics on the changes of the user interface, which we'll delve into more in this article series. Here we will begin to look at how developers can construct the view user interface.
  • ASP.NET MVC 2.0 Using Multiple Actions Brian Mains explains how to use multiple actions in ASP.NET MVC 2.0.
  • ASP.NET MVC 2.0 Templating Templating is now in the ASP.NET MVC 2.0 framework, for .NET framework 3.5 and 4.0. We are going to take a look at these features.
  • ASP.NET MVC 2.0 Attributes An overview of ASP.NET MVC 2.0 Attributes.
  • ASP.NET MVC 2.0 Validation An overview of validation in ASP.NET MVC 2.0.
  • ASP.NET MVC 2.0 Areas A look at ASP.NET MVC 2.0 Areas.
  • ASP.NET MVC 2.0 and AJAX Part 1 ASP.NET MVC makes working with AJAX really easy; it's quite impressive how powerful the framework can be. JQuery adds extra features and makes AJAX calls really easy; we'll see that all here soon.
  • ASP.NET MVC 2.0 and AJAX Part 2 In this article, we are going to look at how you can utilize AJAX in your views, and utilize a concept called unobtrusive JavaScript to take advantage of a variety of situations. ASP.NET MVC provides AJAX features very easily as we previously saw, but this comes with a caveat, and it has mostly to do with the planning of the implementation. We’re going to examine these concerns in this article.
  • ASP.NET MVC 2.0 and ADO.NET Entity Framework - Part 1 In this article, we'll examine using the ADO.NET Entity Framework (ADO.NET EF). The 4.0 version has received some major upgrades, with some major API enhancements and fixes for most of the pain points within the designer.
  • ASP.NET MVC 2.0 and ADO.NET Entity Framework - Part 2 Out of the .NET framework 4.0 comes many great enhancements, the ADO.NET entity framework (ADO.NET EF) is among the top. The framework has improved upon some of the previous bugs (in version 1), as well as enhanced the API, including many new LINQ-to-SQL-like improvements. We're going to examine using these API features to create a generic version of of a data repository.
  • Complexity in ASP.NET MVC, Part 1: Dealing With Large Models At times, every developer has a web forms page or MVC view that ends up getting pretty complex, for various reasons. Whether it pulls in and integrates a lot of data (such as a portal page) or allows users to edit a lot of information, applications require data, and the amount of data grows over time. It’s a simple reality. We’re going to examine what a larger ASP.NET MVC view looks like, and some actions we can take to keep the model instantiation code as slim as possible.
  • Complexity in ASP.NET MVC, Part 2: Plan your AJAX Carefully Brian Mains discusses management of Ajax requests in ASP.NET MVC.
  • Using DI Containers in ASP.NET MVC How to use Dependency Injection containers in ASP.NET MVC.
  • Using Microsoft Unity in ASP.NET MVC Brian Mains continues his asp.net series with the unity application block.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Brian Mains

    Brian Mains is an application developer consultant with Computer Aid Inc. He formerly worked with the Department of Public Welfare. In both places of business, he developed both windows and web applications, small and large, using the latest .NET technologies. In addition, he had spent many hou...

    This author has published 73 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Code First Approach using Entity Framework 4.1, Inversion of Control, Unity Framework, Repository and Unit of Work Patterns, and MVC3 Razor View
    A detailed introduction about the code first approach using Entity Framework 4.1, Inversion of Contr...
    Exception Handling and .Net (A practical approach)
    Error Handling has always been crucial for an application in a number of ways. It may affect the exe...
    jQuery Mobile ListView
    In this article, we're going to look at what JQuery Mobile uses to represent lists, and how capable ...
    Book Review: SignalR: Real-time Application Development
    A book review of SignalR by Simone.
    JQuery Mobile Widgets Overview
    An overview of widgets in jQuery Mobile.

    You might also be interested in the following related blog posts


    MvcContrib working on Portable Areas read more
    ASP.NET MVC and the templated partial view (death to ASCX) read more
    Microsoft The Talent Killer read more
    MvcContrib latest release now with SubController support read more
    Tell Me Your Unit Testing Pains read more
    Staples Launches Nationwide Computer and Office Technology Recycling Program read more
    Tech Ed 2006 Summary read more
    Web Parts in SUB V2 read more
    05 Apr 2005: On Release Dates read more
    Keep Writing SharePoint Web Parts Until (at least) 2006 read more
    Top
     
     
     

    Please login to rate or to leave a comment.