barbarian meets coding

WebDev, UX & a Pinch of Fantasy

Notes for the 70-486 ASP.NET MVC Certification

This article is part of my personal wiki where I write personal notes while I am learning new technologies. You are welcome to use it for your own learning!

Hi! As I was studying for the 70-486 I compiled a bunch of notes and links for the different sections that go into the exam. I find that I learn things better when I read them and write them down with my own words and explanations. Most of the notes are a summary/paraphrasing of the exam reference book and documentation sites on the internet. Hope they help!

These are the topics covered in this certification:

Design the application architecture (15-20%)

Plan the application layers (Basic Stuff)

Plan data access

Plan for SOC: separation of concern

Appropriate use of MVC architecture

Choose btw client side and server side processing

Design for scalability

Design a distributed application

Integrating web services

  • TODO
    - **EXERCISE** Create basic Web API service
    - **EXERCISE** Consume REST service using `HttpService`
    

Design a hybrid application (on-premise vs off-premise)

Summary of Bindings in Azure Service Bus
  • NetEventRelayBinding: Allows publishers to broadcast one-way messages to multiple subscribers
  • BasicHttpRelayBinding: Used to communicate with services that adhere to WS-I basic profile 1.1. Comparable to WCF BasicHttpBinding
  • NetTcpRelayBinding: Efficient bi-directional binding. Supports both relayed and hybrid connection modes. The relayed connection mode routes all traffic through the service bus with no direct connection between the client and the service. The hybrid connection however begins the connect in relay mode and then attemps to switch to a direct connection if possible. It is comparable to the WCF NetTcpBinding.
  • WebHttpRelayBinding: It is used to epose REST-like endpoints to clients. It is comparable to the WCF WebHttpBinding.

Plan for session management in distributed environments

A session is stored on a server and is unique for a user’s collection of interactions with the server. It is identified by a uniqur identifier sessionId that can be sent from the browser to the server either in as a cookie or a query parameter.

You can approach sessions in ASP.NET MVC in two ways: either use sessions to store small pieces or data, or follow the statelessness advocated by MVC, forego sessions and send all the information needed for the server to perform an operation on the request itself.

Session management in distributed environments is even more difficult as a web site may be served from different servers or domains, and a server may be unaware that a user has previously interacted with another server (you need a way to synchronize sessions in different machines). That’s why statelessness is even more interesting in these scenarios and we should favor the use of query strings, hidden fields or other mechanisms to transfer all the information needed.

If we still want to provide support for sessions, it is good to know that there are three modes of session management available in IIS: InProc, StateServer and SQLServer (both of these are also called OutProc). InProc is the default setting in which a session is stored in the web server’s local memory (good performance, not good in distributed environments). With StateServer the session state is stored within a separate server and shared across all other servers which access the state server through a connection string. SQLServer mode works in a similar fashion to StateServer but for the fact that the session state is stored in a SQL server database and the additional performance impact of making an additional database call.

Some examples of session state handling:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--
    Example of a possible single server configuration.
    The session state is persisted in memory on the web server that hosts the web application. 
    If this configuration were to be maintained in a web farm scenario a user session state wouldn't be maintained when connecting to a different server.

-->
<sessionState mode="InProc" />

<!-- 
    Example of possible configuration of state management within a Web Farm.
    Session state persisted in memory within a server. 
    All other servers within a server farm can contact that server via the stateConnectionString.
    The cookieless="false" stores the sessionId within the browser cookies whereas cookieless="true" uses the query string.
-->
<sessionState mode="StateServer" cookieless="false" stateConnectionString="someConnectionString"/>

Planning Web Farms

Web farms are groups of web servers that share the load of serving a web application and handling web requests. Since ASP.NET MVC is built with separation of concerns is mind it is very suited for web farms scenarios.

Some of the advantages inherent to web farms are:

  • High availability: if a server in the farm goes down, the load balancer redirects incoming requests to other servers
  • Improved performance: since the load balancer reduces the load each server handles, hence decreasing contention issues
  • High scalability: as we add more servers to the web farm

It is important to note that within web farm configuration we cannot assume that the session will be available, as different user requests can be handled by different servers. This can be solved either by using session affinity (sticky sessions where a user is served by the same server) or using an OutProc session mode like StateServer or SQLServer.

Design and Implement the Azure Role Life Cycle

Microsoft Azure is Microsoft’s cloud computing platform that allows you to build, deploy and manage your applications and provides a myriad of services to ease development, application lifecycle management, services, machine learning, etc.

Microsoft Azure offers both IaaS (infrastructure as a service) and PaaS (platform as a service) solution. Virtual Machines (IaaS) allow you to have complete control over the environment in which your applications work. Web apps (formerly known as WebSites – PaaS) provide a higher level of abstraction over Virtual Machines and allow you to easily host and scale your web applications. Cloud Services (with roles) provides a PaaS solution that is a middle ground between web apps and VMs via worker and web roles.

Identify Startup Tasks (IIS Configuration [app pool] and registry configuration)

Microsoft Azure startup tasks are used to perform actions before a role starts. There are three types of roles: Web roles, worker roles and virtual machine roles. They are suitable in different cases:

  • web roles: used to host IIS in Azure
  • worker roles: used to host middle tier applications without IIS
  • virtual machine roles: when what you want to do is more complicated that just hosting a web site on IIS or a middle tier application.

Startups tasks are only available for Web and Worker roles and are defined within the task element of the ServiceDefinition.csdef file. A typical startup task could be to run a console application or PowerShell scripts. Startup tasks have the following characteristics:

  • You can pass information to a task by using environment variables
  • you can receive information from them by making the task save that information on disk
  • The run when the server reboots and each time a role is recycled
  • They have to end with an error level 0 for the startup process to complete, and if they don’t the role does not start

The process by which a role starts in Microsoft Azure is as follows:

  1. A role instace is marked as Starting and will no longer receive traffic
  2. Startup tasks are then executed according to taskType:
    1. simple tasks are executed synchronously
    2. background and foreground tasks are started async (in parallel)
  3. The role host process is started and a site is created in IIS
  4. The task calls the Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint.OnStart method
  5. The role instance is marked as Ready and traffic is routed to it
  6. The task calls the Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint.Run method

Some examples of common startup tasks can be:

  • Configuring your IIS server using the AppCmd.exe tool
  • Adding/Modifying registry variables through a script

Whenever you write startup tasks to handle these configurations you have to be aware that they may be executed several times, so a configuration may be applied twice, and we have to be extra careful so that this event won’t affect the startup process negatively. Additionally, Microsoft Azure roles are stateless, this means that they are wiped clean every time a role restarts so you have to be ready to add all your role setup to Startup tasks and store information in external services such as Azure Storage and not in the local disk.

Finally, it is important to note that declaring tasks as background tasks (taskType="background") will prevent Azure from waiting until the start completes before completing the role startup process. An example of such a task could be:

1
2
3
4
5
<Startup>
    <Task commandline="StartPerfMonitors.exe"
          executionContext="elevated"
          taskType="background" />
</Startup>

Identify and Implement Start, Run and Stop Events

Once the startup process has completed successfully the role itself starts its lifecycle and goes through the Start, Run and Stop steps. You can suscribe to either of these events if you want to perform additional tasks before the role starts running, during its lifetime and when it is about to be terminated.

The Start event and the Startup tasks are very similar: both have the same time-out (if you are not out of either function the role startup continues), they both are executed every time the role is recycled and you can configure both ahead of the role. However there are significant differences between them: * A startup task runs in a different process that the role and, as such, can be executed with a different privilege level. * State can be shared between the OnStart method (that handles the Start event) and the Run method because they are both part of the same AppDomain. * A startup task can be configured asynchronously as a background/foreground task and run parallel with the role

To subscribe to the Start event you can override the OnStart method:

1
2
3
4
5
6
public class WorkerRole : RoleEntryPoint{
   public override bool OnStart(){
   // do stuff
   return base.OnStart;
   }
}

Note that if these method returns false the startup process of the role will stop.

Additionally you can override the Run method to run code that will be executed during the lifetime of the role. When the Run method returns something the role termination process will start. You can override the OnEnd to perform clean-up tasks but be aware that all processing will be terminated within 5 minutes of that method being called.

Web roles also provide the Application_Start method for initialization logic that is run immediately after the role OnStart method.

  • TODO

Configure State Management

Choose a State Management Mechanism (InProc or OutProc)

The first thing that you have to think about when you want to implement a state management mechanism in your ASP.NET MVC application is to ask yourself whether you want state or not. ASP.NET MVC is built to support the statelessness of the web, in which each request provides all the information an application needs to perform an operation, and which allows servers to handle as many concurrent users as possible since there’s no need for long running connections, and to freely scale your solution as requests are independent from each other and can be handled by different servers.

That being said, there are different ways to manage state within your ASP.NET MVC 4 application either in the client or in the server:

  • using the Cache which is a memory pool stored on the server and shared across users. It enables you to store key-value pairs and is essentially available within an applicatin domain. If planning to use this system within a web farm scenario each server would need to have a copy of the cache.
  • using the Session, that is stored on the server and unique for each user. It can be configured to use InProc or OutProc configurations (StateServer, SQLState), or it can be customized by inheriting from SessionStateStoreProviderBase and setting the configuration to Custom.
  • with Cookies that are small pieces of data stored in the user browser and sent to the server in each request. They are individualized for a particular domain or subdomain and can be given an expiration date. Cookies can be accessed within your ASP.NET MVC application in the HttpContext.Request.Cookies and HttpContext.Response.Cookies properties.
  • within the QueryString, which is passed as part of the URL. The query string is not part of the route data and can be accessed via HttpContext.Request.QueryString[propertyName] property on the server and in windows.location.href in the browser.
  • inside Context.Items, which is a part of the HttpContext and last only the lifetime of a request. They are typically used to add information within the request via HTTP modules. (For instance during authentication)
  • the Profile which is stored in the database when using ASP.NET Membership and maintains information across multiple sessions. You can access profile information via HttpContext.Profile["miscellaneousInformation"].
  • the application state

When deciding the right strategy we need to think about:

  • Using client side state management provides a more responsive experience to the user and saves sending more requests/information to the server. At the same time it can make the application more complicated with concerns such as how to handle several users concurrently the same information in the client.
  • The size of the information being stored is also important since some approaches have limitations in this regards (cookies, queryString). Large amounts of information are better handled with a session backed by a SQL server database.

Plan for Scalability

In an scalability scenario where you want to add additional servers across the breadth of the web application (horizontal scaling) so that each server handles less of the overall load of the system, you can use an OutProc session management (ServerState or SQLServer) or go for a sessionless solution.

If you want to manage state with a sessionless solution you’ll need to send the required information in every request (with query params or hidden input fields for example).

Use Cookies or Local Storage to Maintain State

Cookies are the predecessor of the HTML5 web storage API (local/session storage). They are sent back and forth between the browser and the server and have a limited size of 4 KB. You can use them within your ASP.NET MVC application to persist information between requests. They are often used for storing login credentials for authentication purposes.

HTML5 Web Storage consists of two APIS:

  • localStorage: that persists information for a given web application across browser sessions
  • and sessionStorage: that persists information until you close the browser (or tab)

The information saved in web storage is stored in the client browser and is not sent to the server (unlike cookies). You can subscribe to storage events. Browser compatibility may be an issue since web storage is a part of HTML5 and it is not supported in older browsers.

You can detect browser capabilities in the server by using the Request.Browser property that returns a HttpBrowserCapabilities object.

Apply Configuration Settings in Web.Config

You can configurion ASP.NET state management in the web.config (or machine.config) files via the <sessionState> element under <system.web>. For instance, for an InProc configuration:

1
2
3
4
5
6
<system.web>
    <sessionState mode="InProc"
                  cookieless="false"
                  timeout="30"
                  stateConnectionString="tcpip=127.0.0.1:42424"/>
</system.web>

or for an OutProc StateServer configuration:

1
2
3
4
5
<system.web>
    <sessionState mode="StateServer"
                  cookieless="false"
                  stateConnectionString="tcpip=192.168.1.222:42424"/>
</system.web>

Implement Sessionless state (for example, using the QueryString)

ASP.NET MVC is meant to embrace the statelessness of the web in which all the information required for handling a request is part of the request itself. Handling state without the use of a session can be done through the use of:

Design a Caching Strategy

Caching is a fundamental strategy for improving the performance of your applications by storing frequently used information within high-speed access memory.

Implement Page Output Caching (performance oriented)

The browser can cache any HTTP GET request for a predefined period of time based on the response headers. ASP.NET MVC allows you to setup caching when serving your pages via GET requests both in the client and the server via the OutputCache attribute:

1
2
3
4
5
[OutputCache(Duration=60, VaryByParam="id", Location="ServerAndClient")]
public ActionResult Details(string id){
   var cityDetails = repo.getCityDetails(id);
   return View(cityDetails);
}

This example will generate HTTP headers that will tell the browser to keep the response in its local cache for a 60 seconds. Since it is also cached in the server, other users making a similar request will also get a cache version (Location=ServerAndClient). These are some of the parameters that you can use to setup the OutputCache:

  • Duration: cache duration in seconds
  • VaryByParam: store a different version of the output based on a parameter sent to the action method
  • Location: tell where the caching takes place Any, Client, Downstream, Server, ServerAndClient, NoStore(no caching)

There are different ways in we can perform caching:

  • cache the output of a while action method or controller (by using the OutputCache attribute)
  • Donut caching, in which we cache the surroundings and we serve dynamically pieces of the website. This is available out of the box in web forms, but in MVC requires you to implement your own helper to access the HttpResponse.WriteSubstitution API that provides this functionality in ASP.NET
  • Donut hole caching, where you cache small pieces within a website. MVC allows you to do this by combining the ChildActionOnly and the OutputCache attributes and by referencing the child view via @Html.Action("MyChildAction").
  • Distributed caching, in scenarios where we have a distributed solution (web farm or azure), we need a way to handle distributed caches where all servers can have keep local caches while having access to a shared cache. This can be solved through Windows Server AppFabric or Microsoft Azure AppFabric.

  • TODO:

Implement Data Caching

The .NET framework provides another way to perform server side caching, the .NET 4 Caching Framework with the ObjectCache and MemoryCache APIs. You can use this type of caching to introduce a caching layer between your domain model and the data access layer.

Implement Application Caching

To enable application caching you need to create a manifest file for your application which details which resources to cache and which to always deliver from the server by using the CACHE, NETWORK and FALLBACK sections. You need to reference this file from your html element:

1
<html manifest="site.manifest">

A manifest file can look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cached entries
CACHE:
/favicon.ico
index.html
images/*

# resources that are always fetched from the server
NETWORK:
login.html

# fallbacks if network is not available
FALLBACK:
login.html offline-login.html

It needs to be server with the MIME type of text/cache-manifest. Once an application is using AppCache, the browser will fetch resources only if:

  • the user cleans the cache,
  • there are changes in the manifest file, or
  • the cache is updated programmatically via the JS APIs

  • TODO:

Implement HTTP Caching

Implement Azure Caching

An example of the user of azure caching configuration in your web.config file is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<system.web>
    <!-- other stuff -->
    <sessionState mode="Custom"
                  customProvider="MyCacheSessionSateProvider">
        <providers>
            <add name="MyCacheSessionStateProvider"
                type="Microsoft.Web.....DistributedCacheSessionStateStoreProvider,..."
                cacheName="myCache"
                dataCacheClientName="default"
                applicationName="MyCacheSessionState"/>
        </providers>
    </sessionState>
</system.web>
<dataCacheClients>
    <dataCacheClient name="default">
        <autoDiscover isEnabled="true"
                      identifier="myapp.cache.windows.net"/>
        <securityProperties mode="Message" sslEnabled="false">
            <messageSecuirty authorizationInfo="secretkey"/>
        </securityProperties>
    </dataCacheClient>
</dataCacheClients>

Where the session state is handled by a custom session provider (Azure cache) that is a described in the providers section.

Design and Implement a WebSocket Strategy

Traditional web communication is done through HTTP and the common request/response flow, this is great in terms of scalability but it falls short in other scenarios like real time communication and highly-interactive applications.

HTML5 Web Sockets fills in the gap for this particular type of use cases and allows for a full duplex, two-way communication between server and client and allows to maintain a connection between both parties (saving the time necessary for establishing and disposing of connections). When using web sockets, the browser does an HTTP request to the server and an upgrade request to convert to a web socket, after that, all communications occur in a single TCP connection and all HTTP related overheads (like creating/disposing connections, headers, etc) are removed.

Read and Write String and Binary Data Async

I already looked at the front-end part of HTML5 web sockets in the How to pass the 70-480 certification blog post and I have a small web sockets article in the wiki. Refer to those articles for such information.

You can manage web socket communication in the backend by using the managed WebSockets API and the WebSocket object. If you decide to build an application that is going to use web sockets you would probably want to use SignalR that provides a higher level abstraction that working with the WebSocket class. If you wanted to go this path that gives you more control, you would need to have a way to handle the connection via an HTTP handler or an HTTP module since you need to implement the upgrade request:

1
2
3
4
5
6
7
8
9
10
11
12
13
// in an action method
HttpContext.Current.AcceptWebSocketRequest(ChatWebSocket)


// Callback 
public async Task ChatWebSocket(AspNetWebSocketContext)
{
    while (true)
    {
        // do stuff
        // TODO: complete this example
    }
}

It is also important to note that there are also other alternatives to WebSockets that are used in older browsers:

  • HTTP polling: periodical AJAX requests to the server to emulate the existence of a continuous connection. Very bandwith and server-usage intensive.
  • HTTP long polling: client makes an AJAX request and the server keeps the connection open until it has data to return.

  • TODO

Choose a Connection Loss Strategy

Since the internet is not very realiable and connections can be lost (more so with the user of mobile devices) it is important to have a strategy for handling the lost of a WebSocket connection:

  • handle the onclose and onerror events
  • be able to handle exceptions when attempting to send a message
  • be able to re-create a connection and resend messages
  • establish mechanisms that allow you to verify that the other party has received a message
  • establish mechanisms to handle receiving the same message numerous times
  • etc…

Decide a Strategy for When to Use Web Sockets

Web Sockets are specially suited for two-way communication with the server with minimal overhead and near real-time. Beware if you are targeting old browsers or if there are network entities that may block the web socket traffic (for instance, if they only allow HTTP traffic).

Implement SignalR

  • TODO
    • READ more about SignalR
    • EXPERIMENT: Build a small example with SignalR
Using SignalR with the Hubs API

You can implement SignalR with hubs. You just need to create a class that inherits from Hub and create a public method that will be later accessible from a JavaScript proxy. For instance, the following hub receives can receive a message and broadcast it to all browsers using your application:

1
2
3
4
5
public class Chat : Hub{
    public void BroadcastMessage(string message){
        Clients.All.showMessage(message);
    }
}

This will be accessible via JavaScript:

1
2
3
4
5
6
7
var chat = $.connection.chat;
chat.server.broadcastMessage($('.chat-input').val());

// the client can receive the messages via
chat.client.showMessage = function(message) {
    $('.chat-window__messages').append(message)
}

You can use the [HubName] attribute to define a different name for the hub than the class name, and [HubMethodName] to modify each method name.

Design HTTP Modules and Handlers

HTTP modules and handlers allow developers to interact directly with the HTTP requests. An incoming request gets processed by multiple HTTP modules (session, authentication, etc) to be finally processed by a single HTTP handler before flowing back as a response to be processed again by the modules.

Implement Async and Sync Modules and Handlers

HTTP modules are called before an HTTP handler is executed. They allow you to intercept or modify each request. To create a module you need to implement the IHttpModule interface (Init(HttpApplication) and Dispose methods). The way that you interact with HTTP requests is by subscribing to the different events of the request lifecycle through the HttpApplication class. You can also use the <httpModule> configuration section in the Web.config file.

Http modules are useful hook up to the request pipeline events and run logic when events are raised, and to implement custom modules to perform actions that will be invoked for all requests being handled. Many of these events can be also handled in Global.asax but the HttpModule approach provides better encapsulation, separation of concerns and code reuse.

The flow of a request within an ASP.NET MVC application is as follows:

  1. Validation
  2. URL mapping (defined within the UrlMappingsSection in Web.config)
  3. events that can be handled by HTTP modules on the request (security, caching, etc)
  4. an HTTP handler handles the request and generates a response
  5. events that can be handled by HTTP modules on the response (recaching, logging, etc)

HTTP handlers on the other hands are used to process individual endpoint requests, i.e., specific URLs within an application. Unlike it happens with modules, where several modules can subscribe to the events of the request pipeline and perform their logic, only one Http handler is used to handle a request. To customize a handler you can implement the IHttpHandler interface (IsReusable and ProcessRequest(HttpContext) methods) and use the <httpHandler> section of the web.config to configure it (select which path, verb and type of endpoints are handled by the custom handler).

ASP.NET 4.5 lets you easily write async modules and handlers by using the async/await pattern and Task objects. These async modules and handlers will not stop or affect the processing of a request as it happens with sync modules and handlers where the whole requset is handled by the same thread and where long running problems can affect the throughput of the whole server.

You can easily implement async handlers by extending the HttpTaskAsyncHandler class that provides the ProcessRequestAsync(HttpContext) method.

ASP.NET MVC Handlers

This is quoted from MSDN – MvcRouteHandler – Remarks.aspx):

ASP.NET MVC includes the following handler types:

MvcHandler. This handler is responsible for initiating the ASP.NET pipeline for an ASP.NET MVC application. It receives a Controller instance from the MVC controller factory; this controller handles further processing of the request. Note that even though MvcHandler implements IHttpHandler, it cannot be mapped as a handler (for example, to the .mvc file-name extension) because the class does not support a parameterless constructor. (Its only constructor requires a RequestContext object.)

MvcRouteHandler. This class implements IRouteHandler, therefore it can integrate with ASP.NET routing. The MvcRouteHandler class associates the route with an MvcHandler instance. A MvcRouteHandler instance is registered with routing when you use the MapRoute method. When the MvcRouteHandler class is invoked, the class generates an MvcHandler instance using the current RequestContext instance. It then delegates control to the new MvcHandler instance.

MvcHttpHandler. This handler is used to facilitate direct handler mapping without going through the routing module. This is useful if you want to map a file-name extension such as .mvc directly to an ASP.NET MVC handler. Internally, MvcHttpHandler performs the same tasks that ASP.NET routing ordinarily performs (going through MvcRouteHandler and MvcHandler). However, it performs these tasks as a handler instead of as a module. This handler is not typically used when the UrlRoutingModule class is enabled for all requests.

Custom HTTP Handler Example

You can for instance, create an http handler to handle some image extension *.gif by creating a ImageProcessor class that implements IHttpHandler and adding the appropriate configuration in your web.config file:

1
2
3
4
5
6
7
8
9
10
11
// In your code
public class FunnyGifProcessor : IHttpHandler{
    public bool IsReusable {get{return true;}}
    public void ProcessRequest(HttpContext context) { // do processing;}
}

// in web.config
<httpHandlers>
    <add verb="*" path="*.gif" type="FunnyGifProcessor"/>
</httpHandlers>
// this means, handle any request for a *.gif file with the ImageProcessor HttpHandler

You cannot use RouteTable.Routes.MapRoute to map a route to a custom HttpHandler because these routes only apply to the MvcHttpHandler.

Choose Between Modules and Handlers in IIS

HTTP handlers allow you to inject logic based on the extension of the file name requested, they are executed based of file extensions, URLs and HTTP verbs. HTTP modules are event driven and inject logic before a resource is requested.

Some ways to differentiate when to use which:

  • serve requests for specific URL/extensions => Http handler
  • applies to all requests based on arbitrary rules => Http module
  • need information available prior to calling to MVC code => Http module
  • handle specific files differently => Http handler
HttpHandler vs HttpModule Summary
  • HttpHandler processes HTTP endpoints requests whereas,
  • HttpModule gives you access to the HTTP pipeline, which allows it to inspect incoming requests and outgoing responses by subscribing to events.

Design the user experience (20-25%)

Apply the user interface design for a web app

Create and Apply Styles Using CSS

Refer to the CSS Wiki and to the article on the 70-480 certification.

The only addition from that is to know that you can use the @Style.Render helper to include styles in your MVC website.

Structure and Layout of a Website Using HTML

Refer to the semantic HTML5 Elements Wiki and to the article on the 70-480 certification.

Implement Dynamic Page Content Based on Design

Dynamic content consists of content within a page that can change between visits based on arbitrary conditions (user, time, date, interactions, etc).

MVC uses primarily the razor syntax with numerous helpers to manage dynamic content. Helpers are snippets of code that result in HTML elements being rendered, or that affect how the whole HTML output is generated. Some of these are: @Html.BeginForm, @Html.TextArea, @Html.TexBox, @Html.CheckBox, and their strongly typed relatives @Html.TextAreaFor, @Html.TextBoxFor that let you associate input elements to properties of a Model (or ViewModel). For instance:

1
2
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)

This will not only bind the value of the model with the HTML elements but also metadata such as validation that we can even use client-side.

Design and implement UI behavior

Implement Client Validation

All three components Model, View and Controller take part in the validation of a MVC application. Within the Model we describe the validation rules that apply to each property through the use of data annotations (attributes in the DataAnnotations namespace). Within the View we use HTML helpers to bind HTML elements to model properties, for instance @Html.EditorFor renders the best matching editor for a given property, @Html.ValidationMessageFor renders a validation message if needed, they can also be wired-up with client side validation. Within the Controller we have access to the ModelState property which represents the state of the model (you can check the IsValid property to find out whether or not there were validation errors).

You also have the possibility of using remote validation via the Remote attribute. Remote validation is useful when you need to validate a condition that requires additional information only available in the server (like access to data that is not present in the client). In order to use remote validation you need to decorate a property with the Remote attribute and point it to an action method within a controller. This action will be triggered when the field is validated in the client:

1
2
3
4
5
6
7
8
9
10
11
// model
[Remote("IsUsernameAvailable", "Validation")]
public string UserName {get;set;}

// action within validation controller
public JsonResult IsUsernameAvailable(string username){
    // jara jara
    // the AllowGet ensures that if the user accepts the value the validation
    // will not run again
    return Json(true, JsonRequestBehavior.AllowGet);
}

You will need to enable client-side validation as well within the web.config file:

1
2
3
4
5
// in the web.config
<appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobstrusiveJavaScriptEnabled" value="true" />
</appSettings>

Use JavaScript and the DOM to Control Application Behavior

Refer to the How to pass the 70-480 certification article that contains references to articles about how to interact with the DOM in javascript.

Extend Objects by Using Prototypical Inheritance

Again refer to the How to pass the 70-480 certification article that contains references to JavaScript OOP. Also this article on OOP in JavaScript for C# developers will be useful.

Use AJAX to Make Partial Page Updates

You can use AJAX within MVC applications to retrieve/send data from/to the server asynchronously either by using the XMLHttpRequest API or libraries like jQuery. Refer to the How to pass the 70-480 certification article that contains references to AJAX, jQuery and the XHR object.

In addition to client-side AJAX support and libraries, MVC makes it easier to use AJAX with the Mvc.Ajax namespace. For instance, instead of the Html.BeginForm helper you could use the Ajax.BeginForm helper:

1
2
3
4
5
6
7
8
9
@using (Ajax.BeginForm("BuyItem", new AjaxOptions {OnSuccess = "onSuccess", OnFailure = "onFailure"}))
{
    // regular form
}
<script>
// handle events
function onSuccess(response) { /* do something */ }
function onFailure(response) { /* do something */ }
</script>

An interesting side effect to take into account when relying on AJAX heavily within your application is its possible negative effects on web crawlers that only parse static content which could affect SEO or other devices like screen readers which could affect accesibility.

Implement the UI Using JQuery

Refer to 70-480 ref, jQuery and jQueryUI. Also check jQuery effects and jQuery UI effects.

Compose the UI layout of an application

ASP.NET MVC and the razor view engine provide different ways in which we can compose and reuse pieces of UI in our web applications: partial views, editor and display templates, layout pages and custom html helpers.

Implement partials for reuse in different areas of the application,

The simplest way of UI reuse is by using partial view. You can insert a partial view into another view by using the @Html.Partial helper.

@Html.Partial vs @Html.RenderPartial

Design and implement pages by using Razor templates (Razor view engine)

Razor templates allow you to reuse pieces UI by defining templates for editing or displaying specific information (a model or view model for instance). An EditorTemplate is displayed when we use the @Html.EditorFor helper on a model property that matches the EditorTemplate type. We defined the suitable type in the view itself:

1
2
3
4
@model MyApp.Cat
@Html.TextBoxFor(m => m.Name)
@Html.TextBoxFor(m => m.Color)
@Html.TextBoxFor(m => m.Race)

Likewise you can create a DisplayTemplate that will be rendered when using the @Html.DisplayFor helper. For these templates to be used by MVC you need to place them in special locations within your view folder:

1
2
3
4
~/Views/ControllerName/EditorTemplates/TemplateName.cshtml
~/Views/Shared/EditorTemplates/TemplateName.cshtml
~/Views/ControllerName/DisplayTemplates/TemplateName.cshtml
~/Views/Shared/DisplayTemplates/TemplateName.cshtml

Design layouts to provide visual structure

MVC and razor allow you to create layout pages to define the high level skeleton of you website (html element, header, footer, etc).

1
2
3
4
5
6
7
8
9
<html>
<head>meta, styles</head>
<body>
    <header></header>
    <section>@RenderBody()</section>
    <aside></aside>
    <footer></footer>
</body>
</html>

You use the @RenderBody method to indicate razor where it should render the view content. Layouts also let you define arbitray sections that can be later filled by other views. You can define sections via @RenderSection:

1
@RenderSection("scripts", required: false);

Implement master/application pages

A layout can be reused by different views by setting the Layout property within a view (or setting a default in _ViewStart.cshtml):

1
2
3
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Enhance application behavior and style based on browser feature detection

Detect browser features and capabilities

Use browser and feature detection to handle inconsistencies in HTML5 browser implementation via jQuery or Modernizr.js, and whenever a browser doesn’t have support for a feature that you want to use, provide a fallback (like a link to a video when a browser doesn’t support the video tag).

Create a web application that runs across multiple browsers and mobile devices

When developing an MVC app you need to understand that you web application needs to be accessible from a range of different devices with different form factors. You can handle this by:

  • using different views for mobile devices
  • using media queries and the viewport meta tag
  • MVC can detect if the device and render different views
  • use third party libraries that provide consistent styles in mobile devices like jQuery mobile, sencha touch or Kendo UI.

You can find information about the different types of view supported in VirtualPathProviderViewEngine.DisplayModeProvider which by default contains mobile and default (for every other device). Mobile specific views contain mobile in their name (see Edit.cshtml versus Edit.Mobile.cshtml). You can even add new display modes for other specific devices to the DisplayModeProvider (f.i. an iPad). It will examine the requests, find information about the user agent and help choosing the right view to render.

Enhance application behavior and style by using vendor-specific extensions

Before CSS features are fully supported or part of the CSS standard they are incorporated in browsers with a browser specific prefix (such as -webkit- or -moz- or -ms-). You may need to include some of these depending the browser versions you are targeting.

Plan an adaptative UI layout

Plan for running applications in browsers on multiple devices (screen resolution, CSS, HTML)

  • Use media queries
  • Or use different layouts for mobile and desktop (_Layout.cshtml and _Layout.Mobile.cshtml)
  • Use jQuery mobile that provides styles and controls specially designed for mobile devices
    • provides support for touch screens and other input methods, accessibility, graceful degradation when features are not supported, modularity and theming.

Plan for mobile web applications

  • Use a front-end approach with media-queries
  • Use a back-end approach rendering different views based on the type of device (DisplayModeProvider)
1
2
3
4
5
6
7
8
9
10
// in Global.asax Application_Start
// we add a new display type for tablets
// now we can use ViewName.Tablet.cshtml to 
// create table specific views
var models = DisplayModeProvider.Instance.Modes;
var tabletMode = new DefaultDisplayMode("tablet")
{
   ContextCondition = (c => IsTablet(c.Request))
};
displayModes.Add(tableMode);
  • TODO
    • READ about media queries when used directly on html elements (like inline with media and viewport attributes, how does it work?)

Develop the user experience (15-20%)

SEO and accesibility

Search Engine Optimization is the process of improving a website ranking on the list of search results. You can improve SEO and accesibility by using these techniques:

Use analytical tools to parse HTML

You can use the Search Engine Optimization Toolkit that runs as an extension on IIS and help you to improve your SEO via recommendations. If you don’t have access to IIS you can use Bing or Google’s webmaster tools. The W3C also offers HTML and CSS validators that you can use. Yet another tool that you can use is the Page Inspector inside Visual Studio.

View and evaluate conceptual structure by using plugs-in for browsers

Use the web developer tools on browsers to assess the quality of the HTML your ASP.NET MVC renders and ensure that it is formatted correctly and that HTML, CSS and JavaScript are clearly separated to allow crawlers and screen readers to easily parse your website. You can even analyze your websites performance in terms of the speed and number of HTTP requests.

Write semantic markup (HTML5 and ARIA) for accessibility (for example, screen readers)

The W3C introduced WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) as a way to improve the accessibility of web applications. The WAI-ARIA provides additional context to HTML elements to make them more accessible through the use of new ARIA attributes within HTML elements.

ARIA tries to address accesibility by improving keyboard focus and navigation, relationships, managing dynamic changes and the role of presentation. For instance:

1
2
3
<!-- a div doesn't provide a lot of semantics, aria allows us to provide additional information for accessibility purposes -->
<div role="application">
    ...etc

MVC provides very limited support for ARIA but you can customize HTML helpers to include aria attributes.

Plan and implement globalization and localization

Plan a localization strategy

By default the culture set on the server is the default culture and content will be returned to all clients in this culture if the application has not been globalized.

There are two levels of localization, language and locale, language is the highest one and represents a language like English (en), the next one is locale that represents a location like UK or US. When a user makes a request to a web application the browser will include the Accept-Language header with the user language preferences (Accept-Language: en-US, en;q=0,8).

If the application has been globalized, it will first will try to match the locale (en-US for instance) and if it is not found will fallback to the language (en) to send the response. In order to support this feature, the web.config must include the following configuration:

1
<globalization culture="auto" uiculture="auto" enableclientbasedculture="true" />

This tells MVC to use client-based culture and load the appropriate culture in the Thread.CurrentThread.CurrentUICulture property for the current request(wonder in the CurrentCulture is also set).

The most common way to handle localization is to use resource files (.resx) which are basically xml files that contain string literals, images, etc. When you need to display localized content you can use the ResourceManager helper class or the @Resources razor directive to get a resource automatically in the CurrentUICulture. Resource files are compiled into satellite assemblies and deployed with your application.

Another solution is to define culture specific views by creating your views in culture specific folders and creating a custom action filter (overriding OnActionExecuted) to select the correct view based on the current UI culture.

Create and apply resources to UI, including JavaScript resources

You can either create a single resources file per language or create several of them (for bigger applications). You can access these files via the ResourceManager or using the @Resources directive.

You also need to globalize your javascript content. You can use the jquery.globalize project and the $.global.preferCulture(language). Since the culture is not available from javascript, you can set it from MVC var language= "@Request.UserLanguages[0]".

Accessing Resources Through Metadata

You can write metadata classes to provide additional metadata (data annotations) for your (view) model classes (and use the MetadataType attribute to decorate the model – this also enables you to extend metadata for classes which you do not have control over). Applying the Display attribute on the properties lets you specify the name of a resource file that contains keys and values used to replace the display name of a property:

1
2
[Display(Name="Name", ResourceType = typeof(Resources.MyResources))]
public string Name {get;set;}

Remember not to use the DisplayName attribute in a globalization context since it doesn’t allow you to use a resource (only string literals).

Set cultures

Although it is nice to use a client-based culture, it is even better if the user can pick her preferred language herself. Once the user has selected a locale, we can set use it by setting the CurrentUICulture:

1
Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-ES");
CurrentUiCulture vs CurrentCulture

When you want to modify the culture used within your application, so that you can provide culture specific formatting, dates, numbers, currency and resources you must set the culture in Thread.CurrentThread:

  • Thread.CurrentThread.CurrentCulture manages formatting for dates, numbers and currency while,
  • Thread.CurrentThread.CurrentCultureUI manages the loading of resource files.

Create satellite resource assemblies

There are two main ways to manage your resource files. You can create a single assembly for your application that contains all resources embedded. This is a good technique if you only have a few locales. If you have a lot of locales or your resource files are big, then you can use satellites assemblies instead. Satellite assemblies are assemblies that only contain resources and which are only loaded if they are needed based on the current culture.

The suggested naming for satellite assemblies is: resourcename.culture.resources.

You can create satellite assemblies by using the assembly linker:

1
al.exe /t:lib /embed:myresources.es-ES.resources /culture:es-ES /out:MyApp.es-ES.resources.dll

After the satellite assembly is being created, you can load it using the ResourceManager when the user locale is es-ES:

1
ResourceManager rm = new ResourceManager("myresources", Assembly.GetExecutingAssembly());
  • TODO
    • READ about the Assembly Linker] that lets you link resources to an assembly.

Design and implement MVC controllers and actions

Apply authorization attributes, global filters, and authentication filters

Certain attributes (filters) in ASP.NET MVC examine the requests (HttpContext primary) being handled by a Controller or Action and determiner whether or not it meets specific requirements:

  • The RequireHttpsAttribute ensures that all calls made to a Controller or Action are done via HTTPS.
  • The ValidateAntiForgeryTokenAttribute helps protect your forms against cross-site request forgeries by ensuring there is a shared secret value between the form data within a hidden field, a browser cookie and the server.
  • The ValidateInputAttribute helps to avoid risks of potentially dangerous information like malicious scripts being sent to the server by removing this content. You can select fields that will not be included in this validation process as well [ValidateInput(true, Exclude="Content")]. Additionally you can also use the [AllowHtml] within a model property.
  • You can use the AuthorizeAttribute to force a user to authenticate when accessing a Controller or Action. You can also be more specific when using this attribute and require a specific role (like [Authorize(Roles="Admin")]).
  • The ChildActionOnlyAttribute protects an action method from being called from the outside of your MVC application. When an action method is decorated with this attribute you’ll only be able to call it via the @Html.Action and @Html.RenderAction methods within a razor view.
  • The HandleErrorAttribute let’s you handle exceptions that may occur within an action. By default, MVC will display the ~/Views/Shared/Error.cshtml view when an error occurs in an action decorated with [HandleError], but you can set the ExceptionType, View, Master properties to call different views with different master pages based on the type of exception. You can also use the Order property to specify the order in which several of these attributes are evaluated. You can even customize it by overriding the OnException method within a given controller. Uncaught exceptions by either the attribute or the OnException method can be handled by overriding the Application_Error in Global.asax.
  • The ActionFilterAttribute is an abstract class that you can use to implement your own custom action filters. It provides four methods that you can override to hook into the MVC pipeline:
    • OnActionExecuting: is called before the action is executed, it lets you examine the HttpContext and decide whether or not to continue
    • OnActionExecuted: is called after an action is executed, it lets you examine the result and determine whether something needs to happen at that point like overriding a view, etc.
    • OnResultExecuting: called before the action result from the action is processed.
    • OnResultExecuted: called after the action result is processed and before the output is loaded into the response stream
    • You can also define whether or not an attribute can be run only once or multiple times by using the AttributeUsage attribute usage

You can apply all these attributes on the action itself, on a controller where it applies to all actions or as a global filter. You can register global filters within App_Start/FilterConfig.cs and the RegisterGlobalFilters method:

1
2
filters.Add(new RequireHttpsAttribute());
filters.Add(new HandleErrorAttribute());
More about Error Handling From MSDN
Accessing Exception Data in the View

The MVC framework passes information about an exception to the error view in the ViewDataDictionary object whose Model property is set to an instance of the ExceptionContext class. The ViewData dictionary contains values for the following keys:

  • ActionName. The intended action method.
  • ControllerName. The intended controller.
  • Exception. The exception object.
Enabling Custom Error Handling

To enable custom error handling for use by a HandleErrorAttribute filter, add a customErrors element to the system.web section of the application’s Web.config file, as shown in the following example:

1
2
3
<system.web>
  <customErrors mode="On" defaultRedirect="Error" />
</system.web>
Handling Errors in the Error View

Errors can occur in the error view itself. In that case, the default ASP.NET error page is displayed. To avoid this, you can configure the application to display an error file in the customErrors section of the Web.config file, as shown in the following example:

1
2
3
4
5
<system.web>
  <customErrors mode="On" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="500" redirect="/Error.htm" />
  </customErrors>
</system.web>
Limitations of the HandleErrorAttribute

From this blog post:

  • It does not catch a HTTP exception other than 500 and bypasses all the others.
  • It is not able to catch an exception raised outside of controllers.
  • The logging of an exception is not supported by the HandleError attribute.
  • It returns an error view even if the error occurred in an AJAX client call.

  • TODO

Specify an override filter

With MVC5 you can override filters:

ASP.NET MVC 5 has a new feature called Filter Overrides, which allows you to clear or replace certain filter types created in higher scopes. For example, if you created a global action filter or controller action filter, you could override those filters on a case-by-case basis at the controller action level. This allows you to set global or controller filters that apply in almost all cases and just override them in the few, specific places where those filters don’t apply

You can use these new filters to override filters in higher scopes (they will clear the previous filters):

  • [OverrideActionFilters]
  • [OverrideAuthentication]
  • [OverrideAuthorization]
  • [OverrideExceptionFilters]
  • [OverrideResultFilters]

And then even add additional filters that only apply to that particular action.

Implement Action Behaviors

Implement Action Results

The ActionResult is the standard result of an action. They are the finishing actions taken by an application, the last step of handling the HttpRequest, and responsible for writing the result information back to the response stream. There are different types:

  • ContentResult
  • EmptyResult
  • FileResult
  • JavaScriptResult
  • JsonResult
  • PartialViewResult
  • RedirectResult
  • RedirectToRouteResult
  • ViewResult

  • TODO

Implement Model Binding

Model binding is the two-way mapping between request values and action method parameters and properties. There are different ways in which you can use model binding: strongly typed views, weakly typed binding and the value provider. There are also different ways in which you can affect the default binding using the Bind attribute.

If you use strongly typed views the model binder can use all the model metadata to help render a view and even add validation information. When the data comes back from the browser the binder can easily parse it and verify whether or not the model is valid prior to calling the action method.

There are several standard model binders:

  • DefaultModerBinder: maps a browser request to parameters and object properties
  • LinqBinaryModelBinder: maps a browser request to a LINQ object (what? xD)
  • ModelBinderAttribute: attribute that lets you associate a model type to a model builder type
  • ModelBinderDictionary: class that contains all model binders for the application listed by binder type

You can also use a weakly-typed approach by using non-strongly typed html helpers (@Html.TextBox instead of @Html.TextBoxFor). The Bind attribute lets you provide hints to help the model binder (like prefixes for properties, black listing, white listing, etc). Refer to more information about this attribute in MSDN

There are other scenarios where model binding is not available, like for instance, when a third party is posting information to an action method. In these scenarios you can use value providers to ease accessing to the request information. Some of these are:

  • FormValueProvider
  • QueryStringProvider
  • HttpFileCollectionProvider
  • RouteDataValueProvider

You can use the TryUpdateModel method to use the Controller’s current value provider to bind model properties or even provide an specific ValueProvider as an argument.

The difference between value providers and model binders is that:

Value providers are responsible for aggregating the values that are part of the current request, e.g. from Form collection, the query string, JSON, etc. They basically say “I don’t know what a ‘FirstName’ is for or what you can do with it, but if you ask me for a ‘FirstName’ I can give you what I have.”

Model binders are responsible for querying the value providers and building up objects based on those results. They basically say “I don’t know where directly to find a ‘FirstName’, ‘LastName’, or ‘Age’, but if the value provider is willing to give them to me then I can create a Person object from them.”

Since model binders aren’t locked to individual sources (with some necessary exceptions, e.g. HttpPostedFile), they can build objects from an aggregate of sources

Design and implement routes

An MVC route is a definition about how a URL can be translated into an Action within Controller.

Define a route to handle a URL pattern

Routes are stored internally in a single RouteCollection object. You can add routes to this collection within the RegisterRoutes method within the App_Start\RouteConfig.cs file. The RouteCollection provides the MapRoute method that you can use to add your routes by using a name, a url template, defaults and constraints:

1
2
3
4
5
routes.MapRoute(
  name: "Default",
  url: "{controller}/{action}/{id}",
  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
  constraints: new { id = @"\d+"});

Apply route constraints

Route constraints add additional constraints to the routing system when it tries to match a given URL to a route. You can define constraints for every parameter using regular expressions. The example above constraints the id parameter to an integer.

Ignore URL patterns

You can use the IgnoreRoute and Ignore methods to ignore certain URL patterns. Since the routing engine evaluates a route at a time, you need to place these ignores at the beginning.

An example of ignoring routes:

1
2
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Ignore("{*allhtml}, new {allhtml=@".*\.htm(/.*)?"});

Add custom route parameters

Custom route parameters provide additional flexibility when you are creating the routes for your web application. You can use custom route parameters to your heart’s content:

1
2
3
4
5
6
routes.MapRoute(
    name: "books by author and genre",
    url: Books/List/{author}/{genre},
    defaults:
        new { author = UrlParameter.Optional, genre = UrlParameter.Optional}
    )

Define areas

When your MVC application grows it is useful to create subdivision to handle increasing complexity. A way to do this is by creating areas. An area in MVC is a portion of an application with a separate set of controllers, views and models into separate groups within the solution and folder structure.

When you create a new area you get an AreaRegistration file where you can specify the area specific routing rules. You can communicate between areas by adding an area parameter within the RouteValues dictionary (like when creating a link).

Control application behavior using MVC extensibility points

MVC has many extensibility points that you can take advantage to customize how your web application behaves.

Implement MVC filters and controller factories

There are four types of filters that you can use to customize your MVC application:

  • Authorization: Implement the IAuthorizationFilter interface and get access to authentication or other security needs or security based evaluations.The interface has a single method OnAuthorization that is call when authorization is required. Some examples are to perform custom authentication, decide whether or not an action is executed, etc.
  • Action: Implement the IActionFilter interface and be able to wrap the execution of an action method. Some examples are to provide extra info into the action method, inspect information coming our of an action, logging, cancel action method execution, overriding the view in which to render the results of an action, etc
  • Result: Implement the IResultFilter interface and be able to wrap the execution of an Action results. Some examples could be logging, perf counters based on view rendering, etc
  • Exception: Implement the IExceptionFilter interface and allows for processing when an unhandled exception is thrown within an action method. It covers the whole lifetime of an action (even authorization). It has a single method OnException that is called when an unhandled exception is thrown within an action method. Some examples of usage could be logging of exceptions and errors.

Whenever you create a filter you can decorate it with the AttributeUsage attribute to specify how and when it can be applied:

1
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]

There is also a way to have control over how controllers get instantiated. You can do that by implementing a custom ControllerFactory by implementing the IControllerFactory (with the methodsCreateController, ReleaseController, GetControllerSessionBehavior). You can register your controller factory within the Application_Start method:

1
ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));

A common use case of creating a custom controller factory is to implement DI and IoC.

Control application behavior by using action results

Action results handle the execution of a result of an action method, they usually deal with the way in which information is formatted prior being sent to the user. You can create custom action results by inheriting the ActionResult and implementing the ExecuteResult(ControllerContext context) method (you can write directly to the response (context.HttpContext.Response). Usages of this could be generating pdf files on the fly (PdfActionResult).

  • TODO
    • EXPERIMENT writing a custom action result

Control application behavior by using view engines

View engines turn views and partial views into HTML code. You can override one of the existing engines (razor or aspx) or you can create a custom view engine by inheriting from VirtualPathProviderViewEngine (and implementing the FindView, FindPartialView, CreateView and ReleaseView methods) or the IViewEngine interface:

  • override existing view engines to add debug information, or provide more flexible pathing.
  • create a new view engine by using the VirtualPathProviderViewEngine as a starting point for building a view engine that relies on the VirtualPathProviderViewEngine class to access view files and to support new parsing processes.
  • create a new view engien from IViewEngine to support new parsing processes or customize the view resolution.

When you create a custom view engine you may need to create a new IView implementation (with has a Render(ViewContext, System.IO.TextWriter method) since the work to render and send page information into the response occurs in the custom view.

Control application behavior by using model binders

You can use custom model binders to manipulate the way data sent within a request is mapped to your action parameters. For instance, you could create a custom model binder that turns three fields with day, month a year into a single DateTime property. Or you could use it as an Adapter between a third party form submission and your website where the form submission field names don’t match what your website expects (it is useful not to have to change your model to support other UI needs).

You can override the default binder by inheriting from DefaultModelBinder and overriding the BindProperty(ControllerContext contContext, BindingContext bindContext, PropertyDescription propDesc) method. You can also create a complete new binder by implementing the IModelBinder interface which has a BindModel method.

You can register a class as the default model binder in the Application_Start:

1
ModelBinders.Binders.DefaultBinder = new MyBinder();

or add them to the list of all supported binders (note that in the example below the binder applies to a specific model type):

1
ModelBinders.Binders.Add(typeof(MyViewModel), new MyBinder());

Control application by using route handlers

There are different ways you can customize how routes are handled in MVC:

You can override the primary route handler MvcRouteHandler and its GetHttpHandler method. You could for instance, translate url parts on the fly to other languages to provide better globalization support (by reading the values in the RequestContext and modifying the request context RouteData accordingly). You need to register the custom route handler for the applicable routes:

1
routes.MapRoute(...route information).RouteHandler = new MyRouteHandler()

Another option is to create your own route handler by implementing the IRouteHandler interface with its GetHttpHandler method. A common case is when you want to use your own IHttpHandler. To register a custom handler you’ll need to:

1
routes.Add("myNewroute", new Route("myroute/{id}", new MyRouteHandler()));

Reduce network bandwidth

Bundle and minify scripts (CSS and JavaScript)

  • Bundling: merge resources into a smaller number of files to minimize the impact of the limited number of HTTP connections per domain (so that the page renders faster)
  • Minify: reduce the size of a file to save bandwith (and also obfuscate as a side-effect)

You can enable bundling and minification by setting <compilation debug="false/> in your web.config or by adding BundleTable.EnableOptimizations = true at the bottom of the RegisterBundles method.

Compress and decompress data (using gzip/deflate; storage)

You can check whether a browser supports compression by reading the Accept-Encoding header. Two common compression algorithms are gzip and deflate. Compression can be enabled in IIS.

Plan a content delivery network (CDN) strategy (for example, Azure CDN)

You can use CDN to put your content nearer to users around the world and thus improve performance. Additionally the help you offload static content from your servers so they can focus on request processing.

Misc notes

Detecting browser capabilities in the backend

Use the Request.Browser property:

  • Request.Browser.IsMobileDevice returns true for mobile devices and allows to serve different views for smaller devices.

Troubleshoot and debug web applications (20-25%)

Prevent and troubleshoot runtime issues

Troubleshoot performance, security, and errors

  • Use the Visual Studio Performance Wizard to profile your running MVC application (also more information in depth in MSDN:
    • Use CPU sampling to lightweight measure CPU usage
    • Use Instrumentation to automatically instrumate all assemblies and measure all function calls and timing. Very detailed
    • Use Memory sampling to measure your memory usage from object creation to GC
    • Use Resource Contention Data to investigate concurrency issues in multithread environments
  • Use the Visual Studio Profiler to get a complete trace of all calls made within your application and all memory used to process those calls. Where the wizard concentrates on performance, the profiler monitors all activity and documents it. Some interesting information from the profiler is: cpu cycles per second, hot path that determines most expensive code application path and highlights problematic functions and shows functions doing the most individual work.
  • Use the Performance Monitor in Windows Server (perfmon) to monitor your applications in a production environment. It provides hundreds of monitors that let you get a better understanding of how your application is performing (even ASP.NET specific ones).

  • TODO

Implement tracing, logging (including using attributes for logging), and debugging (including IntelliTrace)

In order to detect, troubleshoot and fix problem ASP.NET offers a myriad of ways to capture application state and save information outside of the system:

  • logging is the process of saving information. You can use loggers such as NLog or Log4Net and use different providers to store logs in disk, web service or a database with different levels of criticality such as Error, Warning or Information.
  • tracing is a technique that enables you to analyze an application while it is running. You add tracing statements in development and can then use them in dev and production. You can activate/deactivate tracing via configuration without needing to change the code. Tracing is built-in .NET as a part of the System.Diagnostics namespace.
  • debugging is the process of troubleshooting a problem using various tools to determine the cause of a problem and fix it.

To configure tracing you need to:

  1. create one or more TraceListeners which receive tracing data and can store it in disk or a database. You can configure TraceListeners in the system.diagnostics section of your web.config. There are a number of built-in listeners:
    • TextWriterListener
    • EventLogTraceListener
    • DelimitedListTraceListener
    • XmlWriterTraceListener
  2. Write information to a listener using Trace.WriteLine (or other methods such as Write, WriteIf, etc)

You can easily log errors automatically by using the HandleErrorAttribute and overriding the OnException method or using a completely custom error filter. An error filter will handle errors within the action method and on attributes that decorate the action or the controller. You can also handle exceptions at the controller level by overriding the OnException method of the controller. You can manage errors at the application level by overriding the Application_Error method in Global.asax.

A Note on Handling Exceptions Thrown on Missing *.html Files (or other files that are not part of ASP.NET lifecycle)

Missing *.html bypass the ASP.NET processing pipeline, in order to handle exceptions thrown when *.html files are missing you’ll need to implement a custom HttpHandler, you cannot handle this exceptions in the Application_Error event, nor with the customErrors section of the web.config file.

A Note on Extracting Http Code From an HttpException

You can access the HTTP status code from a HttpException by using the GetHttpCode() method and not by using the ErrorCode which returns the HRESULT of the exception (32-bit value assigned to a specific exception).

A Note on Custom errors

If you want to show exception details when an unhandled exceptions occurs within a browser is used within the same server that hosts a website but not when the website is accessed from a different computer you can use the following configuration in your web.config file:

1
2
3
4
5
6
<customErrors mode="RemoteOnly" defaultRedirect="DefaultErrorPage.html">
</customErrors>

<!--
    mode="Off" will always show exception details
    -->

You can also use specific pages for specific status codes:

1
2
3
4
<customErrors mode="RemoteOnly">
    <error statusCode="404" redirect="404.html"/>
    <error statusCode="500" redirect="500.html"/>
</customErrors>

Enforce conditions by using code contracts

A Note on Code Contracts

Remember that when defining a class that describes a contract to be applied to an interface you need to use the:

  • ContractClassFor attribute to decorate the class that describes the code contract
  • ContractClass attribute to decorate the interface

For example:

1
2
3
4
5
6
7
8
9
10
11
[ContractClass(typeof(MyContract))]
public interface IMyInterface{
    public void Do(string something);
}

[ContractClassFor(typeof(IMyInterface))]
public abstract class MyContract : IMyInterface{
    public void Do(string something){
        Contract.Requires(!string.IsNullOrEmpty(something));
    }
}

Enable and configure health monitoring (including Performance Monitor)

Health monitoring is a part of ASP.NET that is designed to handle the logging of events within your web application such as: * lifetime events: triggered when an application starts or stops, etc * errors: raised by exceptions or other errors, * sercurity events: like when a login attempt fails or unathorized access is attempted * etc.

It has the following benefits: * part of ASP.NET and has access to more event than many third party providers * follows the provider framework which means that it can be added to your web application via configuration. This means that you can change the configuration as needed without needing to recompile or redeploy, and have different configurations easily in dev and prod. * has many built-in log sources that let you store your logs in SQL server, windows even log, email and many log formats * each logging event can be handled differently via configuration

These are the different sections that you can use in your web.config: * <bufferModes> where you define how long events are buffered before they are written to a provider * <providers> where you define the providers to use to write events * <profiles> lets you configure how events get logged. This section is critical in limiting the amount of information that gets logged * <rules> where you define the relationship between events and providers. Events that are not defined in this section are not written to any provider. * <eventMappings> where you define the events to log (all events, heartbeats, errors, all errors, infrastructure errors, processing errors, etc)

The cool thing about the health monitoring system is that, since it is a provider, you can manage it entirely via configuration. If you don’t have any other logging solution in your application, you can implement health monitoring right away.

Design an exception handling strategy

  • Handle exceptions across multiple layers
  • Display custom error pages using global.asax or creating your own HTTPHandler or set web.config attributes
  • Handle first chance exceptions

Test a web application

  • Create and run unit tests (for example, use the Assert class), create mocks
  • Create and run web tests, including using Browser Link
  • Debug a web application in multiple browsers and mobile emulators
  • Browser link

Debug an Azure application

  • Collect diagnostic information by using Azure Diagnostics API and appropriately implement on demand versus scheduled
  • Choose log types (for example, event logs, performance counters, and crash dumps)
  • Debug an Azure application by using IntelliTrace, Remote Desktop Protocol (RDP), and remote debugging
  • Interact directly with remote Azure websites using Server Explorer.
A Note About Troubleshooting Problems in Azure via RDP

In order to connect directly to Azure via RDP (Remote Desktop Protocol) you need to use a password protected certificate and import the RemoteAccess on the service definition file for each service that should allow an RDP connection.

Design and implement security (20%-25%)

Configure Authentication

  • Authenticate users
  • Enforce authentication settings
  • Choose between Windows, Forms, and custom authentication
  • Manage user session by using cookies
  • Configure membership providers
  • Create custom membership providers
  • Configure ASP.NET Identity

Configure and apply authorization

  • Create roles, authorize roles by using configuration, authorize roles programmatically,
  • Create custom role providers
  • Implement WCF service authorization

Design and implement claims based authentication across federated identity stores

  • Implement federated authentication by using Azure Access Control Service
  • Create a custom security token by using Windows Identity Foundation
  • Handle token formats (for example, oAuth, OpenID, Microsoft Account, Google, Twitter, and Facebook) for SAML and SWT tokens

Manage data integrity

  • Apply encryption to application data
  • Apply encryption to the configuration sections of an application
  • Sign application data to prevent tampering

Implement a secure site with ASP.NET

  • Secure communication by applying SSL certificates
  • Salt and hash passwords for storage
  • Use HTML encoding to prevent cross-site scripting attacks (ANTI-XSS Library)
  • Implement deferred validation and handle unvalidated requests, for example, form, querystring, and URL
  • Prevent SQL injection attacks by parameterizing queries
  • Prevent cross-site request forgeries (XSRF)
A Note on Authentication with Active Directory and a Custom Login Page

If you want to use Active Directory for authentication but you want to provide a custom login page, then your best choice is to use Forms authentication and access Active Directoy APIs to authenticate users. If you want to use Windows Authentication and have a custom loging page then you’ll need to write a custom HTTP module which is a more complex route to follow.

A Note About How Digital Signing Works

If you want to verify that information was not modified nor tampered with before it arrived to you, you need to use the public key of the entity that digitally signed the information. The entity itself will use the private key to sign the information and guarantee its integrity. Signing the information involes generating a hash of the data and then encrypting this hash by using the entity’s private key. The receiving end can use the public key to decrypt the encrypted hash and verify it against the hash of the information. Because the entity that creates encrypts the hash is the only one in possession of the private key that can encrypt the data, and because it can only be decrypted using the public key, the receiver is assured that the information comes from the original entity. By comparing the hashes the receiver can verify whether or not the information was tampered with.

A Note About the Proper Way To Store Passwords in the DB

When storing passwords in the database you want to append a salt value (randomly generated) to the beginning/end of the password and then hash the combined password and salt. The hashing process is a one-way operation that reduces the probability of revealing the password if the database is compromised. By adding the random salt value to the password before hashing we introduce additional complexity to prevent dictionary attacks and avoid disclosure via duplicated password hashes within the database.

(Bonus) MVC 5 and Misc Stuff

MVC5

  • OWIN and Katana
  • New Identity and Security
  • Web API 2
  • READMVC5 Attribute routing –> as far as I know this is not part of the exam

MISC

  • READ – ServiceBus bindings in MSDN
  • READ – Troubleshooting Azure Web Sites in Visual Studio (attach debugger)

References

Comments