ASP.
NET & MVC
Some Terminologies
1. Solution: It is the outermost container for a C# based application. It can
contain multiple Projects.
2. Project: It is the second outermost container. It can reside independently or in
a Solution. We can have them dedicated for a specific purpose. Example – We
can have 2 different Projects in our Solution for the Web Application and the
Data Layer.
3. Razor View: It is a special file with HTML and C# code in the same file. It has
an extension of .cshtml . If we have a path with the name Index inside the
Controller with the name Home . ASP.NET will then go into the Views > Home >
Index.cshtml to resolve the View.
public class HomeController : Controller {
private IData db;
public HomeController() {
db = new DataDB();
}
public ActionResult Index() {
var model = db.GetAll();
return View(model);
}
}
@model IEnumerable<Solution.DataProject.Models.DataType>
<div>
There are @Model.Count() restaurants in the DB.
</div>
ASP.NET & MVC 1
<ul>
@foreach (var dataPoint in Model) {
<li>@dataPoint.Property</li>
}
</ul>
From C# to HTML in ASP.NET MVC
.dll files: They’re files in the Microsoft Intermediate Language (MSIL) format.
Visual Studio takes the source code of the project, and compiles the C# and
the Scripts and the Configuration files to MSIL. The .dll is a common
executable file in the Windows environment.
IIS Server: Internet Information Services (IIS), is a Web Server for the Windows
environment. It can be used to host any web content on Windows. Visual
Studio, by default, uses a lightweight version of this, called IIS Express, to host
the code we run using the IDE.
ASP.NET & MVC 2
💡 Because the IIS Express Server is only responsible for hosting the Web
Server in the Local Machine, the build and run steps are independent of
each other. We can rebuild the application after making changes to the
code in Visual Studio, and it will update the .dll file, which will then
automatically be picked up by the Server. So, we need not re-run the
application to see the changes.
.NET Configurations
Global.asax
<%@ Application CodeBehind="Global.asax.cs"
Inherits="NameOfProject.Web.MvcA
Language="C#" %>
Global.asax.cs
namespace NameOfProject.Web {
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {
// Startup Code for the Application
}
}
}
The above 2 files are auto generated. They’re responsible for the startup of the
app.
BundleConfig.cs
It has the support for bundling the CSS and JS files together, and minifying it.
RouteConfig.cs
It’s used to map the Routes for the application.
We can ignore as well as map specific routes from controllers.
ASP.NET & MVC 3
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// The Resource is the name of the file
// The '*' in front of pathInfo is used to denote all paths afte
// The .axd extension is for Tracing
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
);
/**
* So, a url hit to '/home/contact/' will try to invoke
* the Contact method in HomeController.cs
* P.S.: The defaults are applied in sequential order, so a call
* will apply the default action of 'Index' and invoke the Index
* HomeController.cs
*/
Web.config
It’s an XML file, used for configuration. Most of its logic consists of “Bind
directives”. It binds the Web Server to the appropriate versions of the Assembly
Files. Most of these are irrelevant to the developer.
There is, however, a specific section in the config, called <appSettings> which is
used to define some Settings for the application. The defaults are used for
framework specific configurations. But we can add our own custom settings to it
and use those in our application.
Controllers in .NET
They are the same as Spring Controllers
They don’t need special strings to point to path, they are configured as shown
in Route.config .
ASP.NET & MVC 4
The method name for each path needs to be either unique, or overloaded.
The HTTP Methods being supported by the Controller method can be
specified using an annotation of the type [HttpGet] .
There also exist a special type of controllers, called API Controllers in the
System. They cannot have special named methods. They will implement
methods by the name of Get(), Post(), Put(), Delete() et cetera.
Models in .NET
They are, for the most part, exactly like Models we are used to.
The annotations for [Required], [MaxLength] , et cetera are all provided by .NET
out of the box.
Entity Framework in .NET
It is an Object Relational Mapper (ORM). It’s an external NuGet package.
It works using the DbContext files. Our database must extend this class.
The DbContext file can then be used to describe our table structures.
It provides us with CRUD operations as a ‘Unit of Work’ operation, i.e., we will
have to call saveChanges() method of the DbContext class for our CRUD
operations to be persisted in the database.
Razor View Engine
Syntax
Anything with @ { ... } format is a block of C# code. But Razor is smart
enough to pick which part of it is HTML, and which is C#.
Anything like @Model.calculate() or @(Model.Calculate()) is a C# expression or
directive that can be injected into the HTML.
Anything like @:text is a literal, which needs to be rendered as HTML.
We can escape the @ sign by writing @@ instead.
ASP.NET & MVC 5
Properties
_ViewStart.cshtmlis a special file, which the Razor View engine will go looking
for. Anything we write here, will be executed before any and all other .cshtml
files inside the same folder or subfolders that are being loaded by the Razor
View Engine.
Layout Property: The Layout property of a View is used to mention the
template of the View. The Layout Property is used to refer to a special kind of
View, called Layout View. The Layout View renders most of the semantic
HTML code on it (like <!DOCTYPE html>, <head> , et cetera). At one point, the
Layout View will have a @Render.Body() call in it. This will be used to render the
actual View at the location of the method call.
ViewBag Property: It’s a dynamic object property that is present for, and
accessibly from every page. It can be used to store View specific
configurations or values. Example – The page title can be stored in the
ViewBag, and the ViewBag can then be accessed from Layout to dynamically
set the title for a View.
Sections in Views: They can be used to render more elements in the Layout
View. We can have a call to sections inside our Layout View using the
directive. The section can be
@RenderSection("nameOfSection", required: boolean)
defined in any of the subsequent views using the @section nameOfSection { ... }
directive.
Partial Views: This can be used to plug in the small reusable chunks of HTML
into our views. The syntax for calling a partial view inside a full view is
@Html.Partial("_nameOfView", modelElement) .
TempData: Used to send temporary data over via requests. Possible use case
– Can be used to show a Confirmation Message on a Redirect.
namespace Conference.Portal {
public class MyPortalController : Controller {
[HttpPost]
[ValidateAntiForgeryToken] // Used to prevent CSRF at
public ActionResult BookHotel(HotelOrder hotelOrder)
hotelService.bookHotel(hotelOrder);
ASP.NET & MVC 6
TempData["Message"] = "Thank you for your hotel b
return RedirectToAction("MyPortal", new { hotelBo
}
}
}
The TempDate["Message"] can then be accessed inside the Layout or the View.
Front-End frameworks
: It is used to render Script bundles for client side libraries.
RenderScripts()
They’re configured using the BundleConfig.cs file in App_Start folder. The
bundler picks up the latest files in the bundles folder of the project, and is
smart enough to serve non-minified version in Development, and minified
version in a Production environment. It also bundles the CSS and JS files
together to create single downloads for the clients.
.NET MVC Request Life Cycle
ASP.NET & MVC 7
Application Start
Application End
ASP.NET & MVC 8
Pre-Application Start
[assembly: PreApplicationStartMethod(typeof(MvcApplication, "Reg
namespace ProjectName {
public class MvcApplication : HttpApplication {
public static void Register() {
HttpApplication.RegisterModule(typeof(LogModule)); /
}
protected void Application_Start() {
// Do Application Start Logic
}
}
}
Lifecycle of a Request
ASP.NET & MVC 9
Routing
HttpHandlers
Classes that implement the IHttpHandler interface and generate a response to a
HttpRequest .
Only 1 can execute per request.
Requests handled by a Custom handler, will not be handled by .NET MVC.
ASP.NET & MVC 10
namespace MvcApplication.Handlers {
public class SampleHandler : IHttpHandler {
public bool isReusable {
get { return false; }
}
public void ProcessRequest(HttpContext context) {
context.Response.Writer("<p>This was generated by th
}
}
}
namespace MvcApplication {
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes
routes.Add(new Route("home/about", new SampleRouteHa
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home", action = "Index", id =
}
ASP.NET & MVC 11
);
}
}
private class SampleRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext reques
return new SampleHandler();
}
}
}
HttpModules
Classes that implement the IHttpModule interface and are designed to respond to
Lifecycle Events.
We can accomplish the same functionality from our Global.asax file as well.
But breaking it out into a Module makes the Project cleaner, and our code
becomes reusable.
ASP.NET & MVC 12
Handlers vs Modules
ASP.NET & MVC 13
Controller Initialisation
ASP.NET & MVC 14
Controller Factory
ASP.NET & MVC 15
Dependency Resolver
ASP.NET & MVC 16
Action Execution
Action Invoker
ASP.NET & MVC 17
Action Method Selector
Only public , non- static and non-special methods can be considered for an
execution action.
Model Binding
ASP.NET & MVC 18
Filters
ASP.NET & MVC 19
ASP.NET & MVC 20
ASP.NET & MVC 21
We can call the Action Filter methods right in the Controller class, because the
Controller class in .NET also implements the IActionFilter .
ASP.NET & MVC 22
ASP.NET & MVC 23
namespace MvcApplication.Helper {
public enum WorkflowValues {
Begin = 0,
ApplicantInfo = 10,
AddressInfo = 20,
EmploymentInfo = 30,
VehicleInfo = 40,
Products = 50,
Final = 60
}
}
namespace MvcApplication.Filters {
public class WorkflowFilter : FilterAttribute, IActionFilter
private int _highestCompletedStage;
public int MinRequiredStage { get; set; };
public int CurrentStage { get; set; };
public void OnActionExecuted(ActionExecutedContext filte
var _context = DependencyResolver().Current.GetServi
ASP.NET & MVC 24
var sessionId = filterContext.HttpContext.Session["T
if (null != sessionId) {
Guid tracker;
if (Guid.TryParse(sessionId.ToString(), out trac
if (
filterContext.HttpContext.Request.Reques
&& CurrentStage >= _highestCompletedStag
) {
var applicant = _context.Applications.Fi
x => ApplicantTracker == tracker
);
applicant.WorkflowStage = CurrentStage;
_context.SaveChanges();
}
}
}
}
public void OnActionExecuting(ActionExecutingContext fil
var applicantId = filterContext.HttpContext.Session
if (null != applicantId) {
Guid tracker;
if (Guid.TryParse(applicationId.ToString(), out
var _context = DependencyResolver().Current
_highestCompletedStage = _context.Applicants
x => ApplicantTracker == tracker
).WorkflowStage;
if (MinRequiredStage > _highestCompletedStag
switch (_highestCompletedPage) {
case (int) WorkflowStage.ApplicantIn
filterContext.Result = GenerateR
"ApplicationInfo", "Applican
ASP.NET & MVC 25
);
break;
case (int) WorkflowStage.AdressInfo
filterContext.Result = GenerateR
"AddressInfo", "Address"
);
break;
case (int) WorkflowStage.EmploymentI
filterContext.Result = GenerateR
"EmploymentInfo", "Employmen
);
break;
case (int) WorkflowStage.VehicleInfo
filterContext.Result = GenerateR
"VehicleInfo", "Vehicle"
);
break;
case (int) WorkflowStage.Products:
filterContext.Result = GenerateR
"ProductInfo", "Products"
);
break;
}
}
}
} else if (CurrentStage != WorkflowStage.ApplicantIn
filterContext.Result = GenerateRedirectUrl("Appl
}
}
private RedirectToRouteResult GenerateRedirectUrl(
string action, string controller
ASP.NET & MVC 26
) {
return new RedirectToRouteResult(
new RouteValueDictionary(new { action = action,
);
}
}
}
namespace MvcApplication.Controllers {
[WorflowFilter(
MinRequiredStage = (int) WorkflowValues.bin,
CurrentStage = (int) WorkflowValues.ApplicantInfo
)]
public class ApplicantController : Controller {
}
}
Action Result Execution
ASP.NET & MVC 27
Custom Action Results
ASP.NET & MVC 28
ASP.NET & MVC 29
namespace MvcApplication.CustomResults {
public class XmlResult : ActionResult {
private object _data;
public XmlResult(object data) {
_data = data;
}
ASP.NET & MVC 30
public override void ExecuteResult(ControllerContext con
XmlSerializer serializer = new XmlSerializer(_data.G
var response = context.HttpContext.Response;
response.ContentType = "text/xml";
serializer.Serialize(response.Output, data);
}
}
}
namespace MvcApplication.CustomResults {
public class CsvResult : FileResult {
private IEnumerable _data;
public CsvResult(IEnumerable _data, string fileName) : b
_data = data;
FileDownloadName = fileName; // FileDownloadName is
}
protected override void WriteFile(HttpResponseBase respo
var builder = new StringBuilder();
var stringWriter = new StringWriter(builder);
foreach (var item in _data) {
var properties = item.GetType().GetProperties();
foreach (var prop in properties) {
stringWriter.Write(GetValue(item, prop.Name)
stringWriter.Write(", ");
}
}
}
private static string GetValue(object item, string propN
ASP.NET & MVC 31
return item
.GetType()
.GetProperty(propName)
.GetValue(item, null)
.ToString() ?? "";
}
}
}
namespace MvcApplication.Controller {
public class FilesController : Controller {
// The Controller Initialization Logic is irrelevant
public ActionResult GetXmlForData() {
var data = _context.GetDataFromSomewhere();
return new XmlResult(data);
}
public ActionResult GetCsvForData() {
var data = _context.GetDataFromSomewhere();
return new CsvResult(data, "Test CSV");
}
}
}
View Results and View Engine
ASP.NET & MVC 32
ASP.NET & MVC 33
ASP.NET & MVC 34
HTML Helpers
ASP.NET & MVC 35
ASP.NET & MVC 36
ASP.NET & MVC 37