Coding Standards (MVC)
Coding Standards (MVC)
Coding Standards (MVC)
Net MVC
India Engineering
Document Approval
Revision History
Index
General Information
Coding Standard Guideline would help to write reliable, maintainable and efficient code to deliver best
quality software.
The naming conventions, coding standards and best practices described in this document are compiled
from our own experience and by referring to various Microsoft and non-Microsoft guidelines.
Model Recommendations
The model is where the domain-specific objects are defined. These definitions should include business
logic (how objects behave and relate), validation logic (what is a valid value for a given object), data logic
(how data objects are persisted) and session logic (tracking user state for the application).
However, you would have to duplicate this logic in every place this business requirement was needed.
Instead, you could put the business logic the "display last name first" rule in the model by adding a
property to the model that encapsulates the business logic as follows:
You can use ModelState to add validation checking. The following example shows how to add validation
checks to ModelState explicitly:
if (String.IsNullOrEmpty(userName))
{
ModelState.AddModelError("username", Resources.SignUp.UserNameError);
}
Consider using the Entity Framework or LINQ to SQL as the means of creating wrappers around calls to a
database. Both Entity Framework and LINQ to SQL allow the use of stored procedures as well
Session Lightweight service runs on each machine Session data is lost if the service goes
State in a web farm down
Service Faster than database session storage
View Recommendations
The primary concern of a view is presentation of the model. The view is chosen by the controller.
Business logic does not belong in the view, because business logic is the concern of the model layer. The
view mechanism can be extremely flexible. For example, a view of the model for a web page can be
rendered using HTML. Another view of the same model (same data), can be presented in XML and act as
a web service.
...
<div id="items">
<% Html.RenderPartial ("ItemsByName");%>
</div>
</asp:content>
The partial view is a powerful extensibility and reuse mechanism. For example, we can include the same
view in an admin view, without writing another line of code
ViewData dictionary (property bag), which enables you to enter any data into the dictionary in
an action method (ViewData[“key”] = value), and then access that same dictionary from within
the view.
Whenever possible, you should use ViewData Model instead of the ViewData dictionary because it
provides better type safety. Additionally, you should use either data access mechanism rather than
accessing the Request/Session state directly in the view template.
If you have an object for which you are going to display multiple properties, you should use
ViewData.Model and create a strongly typed view for that object type. If you have a seller’s details
page, for example, and the seller class has the name, phone, address, email, etc. properties. Then you
would assign a seller instance to ViewData.Model in the controller before rendering the view. If you
have disparate data such as page #, a user’s name, and the current time, use ViewData dictionary.
Avoid data access in the view when using model binding. In other words, do the data retrieval from the
database in the controller. Then populate lightweight view model objects from the retrieved data in the
controller before executing the view. So the lightweight view model objects do not retrieve data during
view execution.
Add data validation in the model layer as described in the section titled DO put all business login
in the model.
Ensure the following JavaScript files are in Scripts directory in your project:
o MicrosoftAjax.js
o MicrosoftMvcValidation.js
Add the following lines to your form submission page:
Now if you try to edit a form field which does not match the data annotation, the client side validation
will fail and immediate feedback is given to the user.
These HTML helpers should be utilized as much as possible. For example, the following code creates
a link using the route table back to the default action on the controller from which the view is called.
Controller Recommendations
The controller (and a specified action method) is invoked by the routing system given a pattern match
on the URL. The controller receives input from the routing system, which includes the HTTP request
context (session, cookies, browser, etc.).
ASP.NET MVC abstracts much of the rote code of object deserialization by using model binding. Model
binding is a mechanism by which request context data is marshaled through reflection into the object
type defined on the action method.
The following example shows a Seller class that defines the data that might be submitted from a
form for signing up sellers:
{
public Int64 ID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
}
The form submitting the seller’s data could be contained in a Register view with code similar to the
following:
The controller would need a Register action method that would provide the model binding as shown:
The default model binder will look for each property in the class given the following order (using
Name as example):
1. Request.Form["Name"], if it exists
2. RouteData.Values["Name"], if it exists
3. Request.QueryString["Namel"], if it exists
4. Otherwise, null
As you can see from the Register action method, there are several attributes which can be placed on
an object that will be invoked using the default model binder
The model binding system also runs the validation logic that has been applied to the model object,
such as the data annotations attributes.
The model binding system has a rich extensibility mechanism that allows full customization of how
objects are created, populated, and validated.
To avoid confusion, explicitly name the view, such as "return View("explicitViewName")", in the action
method. This allows you to call List from a different action, without the framework looking for a
different view.
Given this clear delineation, when receiving form data in your post back action method, return
RedirectToAction(<actionName>), which will result in a HTTP 302 (temporary redirect) and will
generate a GET on the <actionName>. This results in Post-Redirect-Get pattern.
Therefore, do not use HTTP GET for posting form data, as this is a violation of the purpose of HTTP
GET verb.
Additionally, classic ASP.NET postbacks can be the cause of a problematic feedback loop when
posting forms.
For example, in the diagram below using a standard postback, you do a GET and POST against the
same url (create.aspx). This is a problem when a user of the site gets impatient waiting on the form
post to complete. If they hit the browser refresh button, there is the potential of submitting duplicate
data which your web site will have to handle. You can solve this problem in MVC using the Post-
Redirect-Get pattern.
However, this pattern does come with client side performance penalty, because the redirect causes
further requests to the server. This performance cost has to weighed against the usability benefits of
this pattern during the decision making process.
The default response for an unknown action is 404 (Not Found) error. If you override
the HandleUnknownAction class in a controller, you can implement a “default” view in this error.
Additionally, put the HandleError attribute on an action and/or controller and you can provide a
standard error view for when an uncaught exception is thrown.
Routing Recommendations
Routing is used in ASP.NET MVC to map URLs directly to a controller, rather than a specific file. This
is especially useful for readability, as the developer can focus on designing URLs that are human
readable (for example, product support and search engine indexing).
The default routes are added to a RouteTable which is located inside of Application_Start section of
the Global.asax file. The table allows you to map a specific URL to a controller and action.
Consider the following example. Suppose you have a product catalog for which you would like to
create URLs of the following forms:
http://sellmyproducts/
http://sellmyproducts/Page#
http://sellmyproducts/category
http://sellmyproducts/category/Page#
Given the following signature of the List method (on ProductsController class):
The following routing specification will correctly route the user to the correct views, given the
previously specified schema:
routes.MapRoute(
null,
"",
new { controller = "Products", action = "List", category = (string)null
, page = 1 }
);
routes.MapRoute(
null,
"Page{page}",
new { controller = "Products", action = "List", category = (string)null
},
new { page = @"\d+" }
);
routes.MapRoute(
null,
"{category}",
new { controller = "Products", action = "List", page = 1}
);
routes.MapRoute(
null,
"{category}/Page{page}",
new { controller = "Products", action = "List"},
new { page = @"\d+" }
);
routes.MapRoute(
"Default",
"",
new { controller = "Products", action = "List", category = (string)null
, page = 1 }
);
routes.MapRoute(
"PageRoute",
"Page{page}",
new { controller = "Products", action = "List", category = (string)null
},
new { page = @"\d+" }
);
Using these route definitions, you can create a link which resolves to "PageRoute" as follows:
Extensibility Recommendations
Inside of the ASP.NET MVC framework there are many points for extension. You can replace any of
the core components, a partial list of which includes the following:
For example, you might want to write your own controller factory that uses an inversion of control
container.
Rewriting core components is outside the scope of this topic. However, you could extend the
framework by adding custom behaviors in the form of filters. Some of the standard filters included in
the framework are: OutputCache, HandleError, and Authorize.
Filters can be applied to a specific action method to alter its behavior. Alternatively, a filter can be
applied to a controller class, in which case it will take effect on every action method in the controller
class. Base classes can be used to define common behavior patterns by applying filters to the base
controller class and then ensuring that other controllers derive from that base class.
For example, suppose that you want to add functionality to log information for each request to
debug a problem with HTTP headers. The following code define class that derives from
the ActionFilterAttribute class.
In order to add this filter to a given action method, you simply place the LogHeadersFilter attribute
at the top of the action (or controller) that you want to filter.
Testability Recommendations
One of the major strengths of the MVC pattern is the improved testability of the designs by keeping
concerns separated and decoupled. In ASP.NET MVC you can cleanly separate and test the business
logic in the model. For example, you could test the logic for adding a bid to the auction site without
depending upon either the controller or the view.
ASP.NET MVC provides many of the tools developers need to create testable applications. In
addition, it is relatively easy add a third-party unit test framework, mocking framework, or
dependency injection framework. It is beyond the scope of this topic to tell you how to create unit
tests for your application. However, ASP.NET MVC provides a flexible architecture that allows for easy
testing. Unit testing is easier because of features like pluggable view engines, controller factories,
action result types, and wrappers around the ASP.NET context types. For more information about
unit testing an ASP.NET MVC application, see Unit Testing in MVC Applications.
Security Recommendations
Disable request validation through use of the ValidateInput attribute. This attribute will
falsely reject valid HTML input.
Add Html.Encode for all user input data that is displayed, whether immediately rendered or
the data is put into the database and then displayed later.
Set the HttpOnly flag on cookies. This will prevent JavaScript from reading and sending
cookies.
Use the Html.AntiForgeryToken class in forms to protect against cross-site forgery request.
On the action which takes the post request, place the ValidateAntiForgeryToken attribute
Explicitly call out with which members of a class you're model binding to, use the
[Bind(Include=explicit members here)] attribute above the class declaration. For example, if
there is an IsAdmin field on a class, automatic binding without Bind directives would allow it
to bind to this class.
Alternatively, create so-called view models, which are model objects specifically designed to
accept input from external sources. View models contain only properties that are safe for
external input. After model binding has created, populated, and validated these objects, the
property values of these objects can be mapped to the application model or data model for
further processing.
This code was need to protect against XSS (cross-site scripting) attacks.
If you are using .NET 4, do not use the above syntax. Use the following syntax instead.
This new syntax automatically HTML encodes the string (if necessary), and is preferred.
Visual Studio converts this text mapping class into a global class that you can call using the following
syntax:
Resources.<resource_filename>.<string_name>
Then you would access the resource in the view like this:
When the translated resource files become available, you should name each file using the following
format: <filename>.<language>.resx.
For example, the German version of the resource file would be named: SubmissionPipeline.de.resx.
Performance Recommendations
Performance is a multi-faceted problem for web-sites, as a myriad of bottlenecks can affect
performance including:
Database
o Inefficient queries
o Incorrectly placed indexes
o Non-normalized design
Bandwidth problems
o Large request size (affected by individual large images, .css, .js, .html, etc.)
o Content that references many other items, such as multiple script, CSS, or image files
o Slow connection speed
Processing power
o Server: expensive operations
o Client: poorly written javascript
This section will focus solely on server processing and request size.
The following example explains how to partial page updates using AJAX:
Choose what portion of HTML you want to update, and mark it with an ID.
Add the Javascript files that enable AJAX to the HTML (typically in the master view):
In the view you want to update, add an AJAX link that references an action method (in the
example the action method is named RetrieveItems).
Implement the controller action, and have it return the partial view.
DON'T overuse session, instead use TempData for short lived (intra-request) storage
It is tempting when creating websites to add objects to the Session object, so that they are readily
available. The problem with placing these objects in the Session object is that it can bog down the
server by having to store extra information that may only be necessary across a redirect. The correct
way to store these temporary variables across a redirect is by using the TempData dictionary.
For example, suppose you receive form data from a POST at login. The action method that procedure
the POST might be something like the following:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogIn(Seller person)
{
...
TempData["name"] = person.Name;
return RedirectToAction("ItemUpload");
In this example, before redirecting to the ItemUpload action, the name of the seller is placed in the
TempData dictionary. In the ItemUpload action method, the seller name is retrieved from the
TempData dictionary and placed in the ViewData dictionary so it can be referenced in the view.
return View();
}
For example, the OutputCache attribute is attached to Dashboard action method in the following
code.
In ASP.NET 4 the number of concurrent threads is set by default to 5000. While it is possible to
increase the default limits, there is a better way to mitigate long running requests from tying up
threads, modifying the long running requests to run asynchronously. ASP.NET MVC enables you to
implement asynchronous controllers for this purpose. For more information about how to implement
an asynchronous controller, see Using an Asynchronous Controller in ASP.NET MVC