Friday 6 November 2015

ASP MVC View code reuse techniques



Every good software developer knows that repeating himself in code is a smell. Copy-paste method turns against us as soon as we need to modify copied code. ASP.NET MVC and Razor View Engine give us multiple ways to avoid repetitions in views code, however too many options may make developers confused in what should be used where. In this post I’m trying to compare all of them and point out their typical usage.

To make this review complete, I’m providing solution with examples of all mechanisms usage, it can be found at my GitHub: https://github.com/szabl/AspNetViewsCodeReuseExamples

Overview

Method Brief description Usage
HTML Helpers C#/VB.NET methods returning html as a string Best suits view elements, where quite a lot of logic is necessary to generate short HTML. Rather not good for elements specific to a specific view.
Display/Editor Template View file used as a template for displaying or editing given data type. Great when particular data structure is often displayed or edited in a typical way in multiple places in an app. Both for value and reference types.
Razor Helpers Method defined inside view, using Razor engine. Its result is a piece of HTML rendered in place of method call. Suits view elements that consist of significant amount of HTML as against to logic required to generate it. Can be both local for a single view and global.
Partial View View file that can be rendered inside another view. Should be used when big part of similar HTML is being repeated around application.
Another typical use is to break too big view file on smaller parts.
Child Action Controller Action and associated view that can be executed and their result rendered in another view Should be used to encapsulate specific view features that require access to lower application layers to produce HTML.
They are a kind of MVC style “User Controls”.
Layouts Files that define elements common to multiple or all pages. Content specific for a given page is rendered within this layout. Designed to define high level page layout in a single place and avoid repeating even single line in all views. Usually, layout defines header, global navigation, footer etc.
MVC View UserControl ASP.NET WebForms style User Control. Making use of existing libraries of WebForms UserConrols (ascx).
Pozycje od 1 do 7 z 7 łącznie
HTML Helpers

OVERVIEW

This method is well known due to the fact that standard library contains many predefined, commonly used Helpers such as:

@Html.TextBox("name");
There is no magic in here, those are ordinary functions taking parameters and returning HTML as a string. According to convention, they are defined as Extention Methods for HtmlHelper class or simply as a static method.

REMARKS

This convention is simple and is great for short, repeatable HTML templates. However, when amount of HTML to produce grows, concatenating strings in C# code becomes highly unreadable. What is more, as static methods are global to the whole application, this technique is not suggested to create elements used only on single view. When helper is defined as an extension method to HtmlHelper, it has access to View specific information through this object properties (ViewContext, ViewBag, etc.) Note: If you use Razor View Engine, HTML helpers should return implementation of IHtmlString rather than plain string, otherwise all special characters are encoded.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Helpers
AspNetViewsCodeReuseExamples/Views/HtmlHelper/Index.cshtml
3rd party articles:

http://www.asp.net/mvc/tutorials/older-versions/views/creating-custom-html-helpers-cs
http://stackoverflow.com/questions/8292497/how-can-i-create-a-html-helper-like-html-beginform
Display/Editor Template

OVERVIEW

This technique enables us to create templates for presenting and editing particular types of data. It can be both simple types as well as complex ones. After defining the template (here, for the User class) we can use it through:

@Html.DisplayFor(m => m.User)
REMARKS

The usage of this mechanisms is quite obvious and limited. It will be a perfect choice if we use a standard display or edit template for particular data types. There is possibility of creating global templates as well as the ones with limited scope. Using default conventions, the former should be put in the Shared folder, whereas the latter in a specific view one. What is more, a given type can have several templates. To use template, other than the default one, it is necessary to provide name of the file containing its definition. Default template is the one defined in the file which name is similar to the type name.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Views/DisplayEditorTemplates
AspNetViewsCodeReuseExamples/Views/Shared/DisplayTemplates
AspNetViewsCodeReuseExamples/Views/Shared/EditorTemplates
3rd party articles:

http://www.codeproject.com/Articles/672591/Exploring-Display-and-Editor-Templates-in-ASP-NET
Razor Helpers

OVERVIEW

From the usage point of view, the mechanism is similar to Html helpers. However, when it comes to implementation it is totally different. Instead of C# code, from which we generate HTML string, we write HTML code in cshtml file and use Razor to insert C# logic.

REMARKS

Helpers can be both local for one view, then we can define it in the same file, and global, available in the whole web application. In order to do that, it is necessary to put helper in cshtml file, in App_Code folder. It is a perfect solution if we need to use similar but rather small part of view in many places. This method is available only if we use Razor View Engine. In other cases it can be replaced with a little bit „heavier” Partial Views mechanism.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Views/RazorHelpers/Index.cshtml
AspNetViewsCodeReuseExamples/App_Code/RazorHelpers.cshtml
3rd party articles:

http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
Partial View

OVERVIEW

This mechanism allows to render a different view and insert its output in place of the call.

REMARKS

It may not be clear at first look, but it is very similar to public Razor helpers. Partials, however, are „heavier”, because each of them require new file. For this reason, they are suggested to encapsulate bigger parts of views than Razor helpers. What is more, it is great way to break a very long view into smaller pieces. It is similar technique to extract method refactoring. If we look closer, technically, they are similar to Display Templates, difference is more in purpose of use.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Views/PartialViews/Index.cshtml
AspNetViewsCodeReuseExamples/Views/Shared/SpecialUser.cshtml
3rd party articles:

http://www.codeproject.com/Tips/617361/Partial-View-in-ASP-NET-MVC
Child Action

OVERVIEW

The technique of calling a controller action from view, the result of which is a string or Partial View that after rendering is inserted in place of the call. This action is no different than regular ones, it can gain access to the lower layers of an application and freely process data. Using attribute ChildActionOnly we can limit it, so that it can be only called as Child Action.

REMARKS

A tool mostly for creating independent, fully encapsulated controls, which takes small amount of data as a parameters and make use of data sources and business logic to produce output. Those controls should be independent from the place they are called. Their usage are similar to User Controls from ASP.NET WebForms, with one difference, they fit better to MVC philosophy. Controller action should return the view with the use of PartialView method, so that it doesn’t use a default layout.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Views/ChildAction
AspNetViewsCodeReuseExamples/Controllers/ChildActionController.cs
3rd party articles:

http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx/
Layouts

OVERVIEW

Layout is usually a file containing html and body tags as well as html elements common to all views. To define placeholders for page-specific content use:

@RenderBody – to mark place where all view content is rendered,
@RenderSection – to mark place where specific, named section is rendered.
View layout can be defined by setting it’s Layout property:

@{ Layout = "~/Views/Shared/_Layout.cshtml"; }
This can be done either explicitly in view or in _ViewStart.cshtml file, which is executed before any other view file when calling controller’s View() method.

REMARKS

Usually, there is a default layout, defined in Views/Shared/_Layout.cshtml file and it is made default in_ViewStart file in Views folder. View with non default layout can define it inline, or use _ViewStart.cshtml file local to specific folder. By setting second parameter of @RenderSection to false it can be made optional, so Views that don’t need it, can ignore it. Layouts can be nested. See example and external articles for more information.

EXAMPLES

See examples on Github:

AspNetViewsCodeReuseExamples/Views/Layouts
AspNetViewsCodeReuseExamples/Views/Shared
AspNetViewsCodeReuseExamples/Views/_ViewStart.cshtml
3rd party articles:

http://www.asp.net/mvc/videos/mvc-3/mvc-3-razor-layouts
http://www.mikesdotnetting.com/Article/164/Nested-Layout-Pages-with-Razor
MVC View UserControl

OVERVIEW

The mechanism allowing the usage of user controllers from ASP.NET WebForms in ASP.NET MVC.

REMARKS

I can’t find sources confirming this, but probably the mechanism was put in a ASP.NET MVC just to facilitate the migration of pages from WebForms to MVC and should be used only for this purpose. It doesn’t fit to MVC philosophy, that is why if we create something from the scratch, it is better to choose one of the above mentioned methods.

EXAMPLES

3rd party articles:

http://www.matthidinger.com/archive/2008/02/21/asp.net-mvc-usercontrols-start-to-finish.aspx
http://malvinly.com/2011/02/28/using-web-forms-user-controls-in-an-asp-net-mvc-project/
Summary

ASP.NET MVC has various mechanisms that help us follow DRY principle. However, the big variety comes with little mess, worst we can do is to pick one tool and use it for everything. Since we have such a great number of options let’s apply them where they suits best. Be prepared for that by trying them out now.

1 comment:

  1. Thank you for sharing to us.there are many person searching about that now they will find enough resources by your post.I would like to join your blog anyway so please continue sharing with us.
    voyance totalement gratuit

    ReplyDelete

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...