A bit of background
My friend and I are totally interested in web development and everything related to it. This year, the university was given an order to write a web portal for students, in which it will be possible to get the latest information on grades, a schedule ... But more on that later. Of course, the “Design Bureau” (the so-called department which is responsible for developing software at the university), without hesitation, decided to transfer the task to the students. It just so happened that we were among these students and we were offered a choice of ASP.NET Web Forms or PHP Symfony. And in order to complicate the task and learn something new, we asked to allow us to do the task on ASP.NET MVC. The project is now fully developed, and I think as we finish, we will post the source code of the project here. But more about that later. And so, in order to somehow systematize our knowledge and get advice from professionals, we decided to start a series of articles that can help other people begin to learn this wonderful framework. Well? Let's start!
And so, for robots we need at least the following things:
We propose to create a project from scratch, this will allow you to better understand how the ASP.NET MVC project works and is built, and I don’t like the demo code that is present during standard project creation.
Let's start with a clean slate
Let's start by creating a Class Library project for C #. Now let's remove everything unnecessary from it:
Class1.cs ,
AssemblyInfo.cs from the
Properties directory and all that is in
References . As a result, we get just an empty project.
Types of projects
We all know that Visual Studio supports many different types of projects, with each of which the studio works in different ways. For example, if we try to launch the Class Library project we created (Ctrl-F5), we will receive the following message:
')
A project with an Output Type of Class Library cannot be started directly.
Since our goal is to create an ASP.NET MVC project, we will change the type of our project accordingly. To do this, select the
Unload Project item from the context menu of the project, open the project file for editing (right-click on the project -
Edit ) and add the Guid for projects of the
Class Library type:
< ProjectTypeGuids > {fae04ec0-301f-11d3-bf4b-00c04f79efbc} </ ProjectTypeGuids >
And now add a Guid for the Web Application:
< ProjectTypeGuids > {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} </ ProjectTypeGuids >
Please note that the Guid for Web Application must be first, otherwise VS will not reload the project.
After we reload the project (right click on the project file -
Reload Project ), we see that the project icon has changed. If you now try to start the project, the studio will launch the explorer. In addition, since additional settings are required for normal Web Application operation, after the project is restarted, the studio will correct the
ProjectExtensions configuration section.
The final step in changing the type of our project will be to adjust the project's
Output path to
bin \ . To do this, in the project properties, go to the
Build tab and change the
Output path .

Routing Setup
In ASP.NET MVC, as in most other MVC frameworks, URLs do not display the actual path to a file on disk, as implemented by ASP.NET WebForms. In MVC, the URL is more intuitive [controller / action], this transformation is called
routing and in order for it to work correctly - we need to make some changes to the project.
First of all, add
Web.config . Clean it up and add the following:
< httpModules >
< add name ="UrlRoutingModule" type ="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ httpModules >
This module is needed to verify that the requested URL matches the specified routes and if a match is found,
HttpHandler takes control.
Let's create our first application.
Routing determination is best done at the start of the application (
Application_Start ). To do this, we need to add the Global Application Class (
Global.asax file) to the project. I prefer to replace the
Global.asax.cs file (codebehind file) with my
Application.cs .
We
get the following
Global.asax :
<%@ Application Inherits= "Mvc.Application" %>
Route definition
After we added the Global Application Class, Visual Studio added a few references to the project:

Add another link to the assembly
System.Web.Routing . (This build is installed with NET 3.5 Service Pack 1)
Next, add a call to the
RegisterRoutes method in
Application_Start :
using System.Web;
namespace Mvc
{
public class Application : HttpApplication
{
public void Application_Start()
{
Router.RegisterRoutes(RouteTable.Routes);
}
}
}
For the definition of routes, I use the class
Router , which we will define later. Pay attention to
RouteTable. Routes is a collection of type
RouteCollection , which will contain all routes of our application, and the
RegisterRoutes method fills this collection with data. The route itself (route) contains information about how to handle the request.
routes.MapRoute(
"Default" , // Route name
"{controller}/{action}/{id}" , // URL with parameters
new { controller = "Home" , action = "Index" , id = "" } // Parameter defaults
);
The UrlRoutingModule matches the current request with the routes we have defined and processes it accordingly. If the request matches one of the routes we specified, then
RouteHandler transfers control to
HttpHandler .
Now, add a link to the
System.Web.Mvc assembly and define the
Router class itself. The class
Router will be:
using System.Web.Mvc;
using System.Web.Routing;
namespace Mvc
{
public static class Router
{
public static void RegisterRoutes(RouteCollection routes)
{
Route route = new Route( "{controller}/{action}" , new MvcRouteHandler());
routes.Add(route);
}
}
}
MvcRouteHandler will create an instance of
MvcHandler that processes requests based on data from
RequestContext .
The route (Route) should contain information about which controller to use (instantiate) and what method to call this controller.
Adding Controllers
Add the controller to the
Controllers directory, which usually contains all the controllers:
using System.Web.Mvc;
namespace Mvc.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Hello World!" ;
}
}
}
This controller has one
Index () method defined. Now, when we go to the address
~ / home / index , we will see the inscription "Hello World!".
Next, modify the
RegisterRoutes method as follows:
public static void RegisterRoutes(RouteCollection routes)
{
Route route = new Route(
"{controller}/{action}" ,
new RouteValueDictionary( new { Controller = "Home" , Action = "Index" }),
new MvcRouteHandler());
routes.Add( "Default" , route);
}
In fact, we made the
Index method, the
Home controller, run by default. That is, if we go to the address ~ / we will see the result of running
Index () .
Add view
Since returning the entire page as a string is far from the best practice for building a web application, we will add a view that will contain the page design.
Create the following hierarchy of
Views / Home folders and add a new
GUID that will indicate to the studio that we are working with an MVC project:
< ProjectTypeGuids > {603c0e0b-db56-11dc-be95-000d561079b0};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} </ ProjectTypeGuids >
After restarting the project, new types of MVC-specific elements will become available to us.

Views and components (control) inherit
System.Web.Mvc (you can verify this by looking at the <% @ Page%> directive).
WebFormsViewEngine uses the same compilation principle as WebForms. That is, to work correctly, we need to add a link to this assembly in the
web.config :
< compilation debug ="true" >
< assemblies >
< add assembly ="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ assemblies >
Next, add the MVC View Page
Index.aspx to the
Views / Home directory and change the type returned by the
Index () method:
public ActionResult Index()
{
return View();
}
The last thing we need to do is to prevent direct access to the views that are in the Views folder. (Go to ~ / views / home / index.aspx and you will see the content of this page.) To prevent this from happening, add the following lines to
Web.config<? xml version ="1.0" ? >
< configuration >
< system.web >
< authorization >
< deny users ="*" />
</ authorization >
</ system.web >
</ configuration >
Importing namespaces into an assembly
Just like WebForms, ASP.NET MVC views are compiled in a separate aspnet_compiler process. Until we add links to the assemblies that we use in the application to the configuration file of the web application, the compiler will not know which one to use.
< compilation debug ="true" >
< assemblies >
< add assembly ="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
< add assembly ="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
< add assembly ="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ assemblies >
</ compilation >
Now the compiler will adequately respond to our attempts to use the types defined in one of these assemblies. Now, for convenience, we will add namespaces in Web.config, which will allow us to use short type names.
< pages >
< namespaces >
< add namespace ="System.Collections.Generic" />
< add namespace ="System.Linq" />
< add namespace ="System.Web.Mvc" />
< add namespace ="System.Web.Mvc.Html" />
</ namespaces >
</ pages >
Many new constructions have been added to the latest version of C #, and of course we would like to use them in our views. To do this, add a few more configurations:
< system.codedom >
< compilers >
< compiler language ="c#;cs;csharp" extension =".cs" type ="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
< providerOption name ="CompilerVersion" value ="v3.5" />
< providerOption name ="WarnAsError" value ="false" />
</ compiler >
</ compilers >
</ system.codedom >
Generalized species
In ASP.NET MVC, it is possible to define a strongly typed view by defining the Inherits attribute of the Page directive using the generic System.Web.Mvc.View class.
Example:
<%@ Page Inherits= "System.Web.Mvc.ViewPage<Object>" %>
In order for the compiler to understand this construction, we need to define a parser in Web.config:
<pages pageParserFilterType= "System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
//...
<pages>
That's all for now.
We manually created an ASP.NET MVC project with a minimal set of elements in order to better understand the internal structure (work) of MVC.
Sources can be downloaded
here .
Next time we plan to write an article about the principles and methods that are best used for working with ASP.NET MVC.
So to be continued.
PS Oh, yes, if anyone has one extra invite, then my friend, with whom we were engaged in the translation and design of this article, would also like to get on Habr.
This
article was taken as the basis.