Learning MVC Once And For All
Tags: tutorial, dotnet, beginners, backend
Published: 2024-06-05 23:12:28

In this training, we teach the concept of Controller in CodeBehind Framework.

## Why do some people not understand the concept of MVC?

Most back-end frameworks require Controller configuration in Route to run. Concepts like routing or mapping are very confusing. Usually, before learning MVC, beginners are familiar with a script such as PHP or Python, and they easily understand the physical path of the script files in the root and their corresponding path in the url; but the concept of Route becomes challenging for them for the first time, because in this type of back-end frameworks, there is no physical route.

As we said before, in the MVC architecture in CodeBehind, the names of the Controller and Model classes are first determined as the attributes of the page in the View, and the requests reach the View path, and then a new instance of the Controller and Model classes is created. So if you have configured the CodeBehind framework by default, there is no need to configure the Controller in the Route.

## How to teach MVC?

In the MVC architecture of the CodeBehind framework, there is no need to follow the MVC pattern, and each part of the application can be created as only View, Model-View, etc. In this architecture, you can easily create and execute a single View, then you can add and execute a Model to it, and finally, you can add a Controller to it. We recommend to instructors that if you are teaching students the concept of MVC for the first time, use the CodeBehind framework as an example. First, teach the concept of View, then teach the Model-View pattern in the CodeBehind framework, and then teach the Controller.

## Why do we need a Controller?

The Controller acts as an intermediary between the user interface and the database. Controller is responsible for managing user input and processing requests. Controllers play an important role in web programming by helping to organize and manage the flow of data and requests in an application.

The Controller has a high power to respond to requests and provides the response according to the request. Controller can call a View for each request and fill the values ​​of that View with Model.

## MVC example in CodeBehind

Here is an example of a simple MVC application in CodeBehind Framework that displays information about a book:

View File: Book.aspx      
```html
@page
@controller BookController
@model {BookModel}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@model.Title</title>
</head>
<body>
    <h1>@model.Title</h1>
    <p>Author: @model.Author</p>
    <p>Publication Date: @model.PublicationDate</p>
</body>
</html>
```

Model Class: BookModel.cs   
```csharp
public class BookModel
{
	public string Title { get; set; }
	public string Author { get; set; }
	public string PublicationDate { get; set; }
}
```    

Controller Class: BookController.cs
```csharp
using CodeBehind;

public partial class BookController : CodeBehindController
{
	public void PageLoad(HttpContext context)
	{
		BookModel model = new BookModel();

		model.Title = "The Smiling, Proud Wanderer";
		model.Author = "Jin Yong (Louis Cha)";
		model.PublicationDate = "1967";

		View(model);
	}
}
```

Screenshot
![MVC result screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91aiwxngvxrgc9ww8jo2.png)

The response that is sent to the browser is according to the codes below.

HTML result
```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>The Smiling, Proud Wanderer</title>
</head>
<body>
    <h1>The Smiling, Proud Wanderer</h1>
    <p>Author: Jin Yong (Louis Cha)</p>
    <p>Publication Date: 1967</p>
</body>
</html>
```

In this example, we have a `Book.aspx` View that displays the title, author, and publication date of a book. The View is bound to a `BookModel` class that contains the properties for these values. The `BookController` class is responsible for loading the data and passing it to the View.

To run this example, you need to create a new ASP.NET Core project and add the CodeBehind NuGet package to your project. Then, you can create a new folder called Views and add the Book.aspx file to it. Finally, you can run the project and navigate to the `/Book.aspx` URL to see the book information displayed.

Note that this is just a simple example, and you can customize the View and Controller to fit your specific needs.

## CodeBehindController abstract class

It is required to add `CodeBehindController` abstract class to Controller class.

We have explained the properties of `CodeBehindModel` abstract class in the previous training. The `CodeBehindController` abstract class is also somewhat similar to the `CodeBehindModel` abstract class of the Model, but it has more features. Because we want this article to be of high quality regardless of the previous articles, we again explain the same classes and attributes in these two classes.

**Create `PageLoad` method**
You can use the `PageLoad` method in the Controller class. The first time the class is called, the `PageLoad` method is executed.

**View**
View is method and can be called in three modes.

Call Model
`View(MyModel)`

The above method contains as an input argument an instance created from a Model class named MyModel. When we call the View method in this way, the values ​​of the Model class are initialized in the default View path.

Call View
`View("/MyNewView.aspx")`

According to the code above, this type of call is actually a redirect. In this case, the default View is ignored and a new View path is requested. The new View can also include Controller and Model.

Call View with Model
`View("/MyNewView.aspx", MyModel)`

In this call, the sample values ​​created from a Model class are set in the new View.

**ViewData**
ViewData is a name and value instance of the `NameValueCollection` class that is used to transfer data from the Controller to the View.

You can set ViewData in the Controller class as follows.
`ViewData.Add("title", "Hello World!");`

Then you can call ViewData as shown below.
`<title>@ViewData.GetValue("title")</title>`

**Section**
Section is a attribute that applies to aspx pages. Section is a feature whose activation makes all paths after the aspx path refer to the current aspx path.

Section in Model takes its value only when you have activated Section in your View. In the next trainings, we will teach Section completely.

Example:

Active Section in View
```html
 @page
+@section
```

If you enable Section in the `/page/about.aspx` path, any path added after the current path will be considered a Section and the executable file in the `/page/about.aspx` path will still be executed.

Example:

`/page/about.aspx/section1/section2/.../sectionN`

If you enable the Section in an executable file called `Default.aspx`, you will still have access to the default path.

Example:

`/page/about/Default.aspx/section1/section2/.../sectionN`

or

`/page/about/section1/section2/.../sectionN`

**CallerViewPath**
The View path that requests the current Controller.

Example:

If the request path is the following value:
`example.com/page/about/OtherInfo.aspx`
According to the above value, the following string is stored in CallerViewPath:
`/page/about/OtherInfo.aspx`

**CallerViewDirectoryPath**
The View directory path that requests the current Controller.

Example:

If the request path is the following value:
`example.com/page/about/OtherInfo.aspx`
According to the above value, the following string is stored in CallerViewDirectoryPath:
`/page/about`

**Download**
Download is a method that takes the file path as an input argument and makes the file available for download in the View path.

Example:
```csharp
Download("/upload/book/my_book.pdf");
```

**Write**

This method adds string values ​​to the beginning of the View page

Example:
According to the previous example, if you call the following method in the Controller class, the string `New written text` will be added at the beginning of the View response.

`Write("New written text")`

The response that is sent to the browser is according to the codes below.

HTML result
```html
New written text
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>The Smiling, Proud Wanderer</title>
</head>
<body>
    <h1>The Smiling, Proud Wanderer</h1>
    <p>Author: Jin Yong (Louis Cha)</p>
    <p>Publication Date: 1967</p>
</body>
</html>
```

**IgnoreViewAndModel**

This is a boolean attribute, enabling it will cause View and Model to be ignored.

Example:

```csharp
using CodeBehind;

public partial class MyController : CodeBehindController
{
    public void PageLoad(HttpContext context)
    {
        IgnoreViewAndModel = true;
        Write("<b>View values ​​cleared</b>");
    }
}
```

The response that is sent to the browser is according to the codes below.

HTML result
```
<b>View values ​​cleared</b>
```

## Using CodeBehindConstructor method

You can use `CodeBehindConstructor` method instead of `PageLoad` method. We created the same example as before using the `CodeBehindConstructor` method.

View File: Book.aspx      
```html
@page
@controller BookController()
@model {BookModel}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@model.Title</title>
</head>
<body>
    <h1>@model.Title</h1>
    <p>Author: @model.Author</p>
    <p>Publication Date: @model.PublicationDate</p>
</body>
</html>
```

The CodeBehind constructor is activated when you use open `(` and close `)` parentheses in front of the Controller class name in the View.

Controller Class: BookController.cs
```csharp
using CodeBehind;

public partial class BookController : CodeBehindController
{
	public void CodeBehindConstructor()
	{
		BookModel model = new BookModel();

		model.Title = "The Smiling, Proud Wanderer";
		model.Author = "Jin Yong (Louis Cha)";
		model.PublicationDate = "1967";

		View(model);
	}
}
```

## MVC in Visual Studio Code

In the Visual Studio Code project, we create a new View named `Monitor.aspx`.

In the Explorer section, by right-clicking on `wwwroot` directory, we select the `New File` option and create a new file called `Monitor.aspx`.

Then we add the following codes inside the `Monitor.aspx` file.
```html
@page
@controller MonitorController
@model {MonitorModel}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@model.Name</title>
</head>
<body>
    <h1>@model.Name</h1>
    <p>Manufacturer: @model.Manufacturer</p>
    <p>Model Number: @model.ModelNumber</p>
    <p>Resolution: @model.Resolution</p>
    <p>Refresh Rate: @model.RefreshRate</p>
    <p>Price: @model.Price USD</p>
</body>
</html>
```

Then we create a Model named `MonitorModel.cs`.

In the Explorer section, by right-clicking on an empty space in Explorer, we select the `New File` option and create a new file called `MonitorModel.cs`.

Then we add the following codes inside the `MonitorModel.cs` file.
```csharp
public class MonitorModel
{
	public string Name { get; set; }
	public string Manufacturer { get; set; }
	public string ModelNumber { get; set; }
	public string Resolution { get; set; }
	public int RefreshRate { get; set; }
	public decimal Price { get; set; }
}
```

Finally we create a Controller named `MonitorController.cs`.

In the Explorer section, by right-clicking on an empty space in Explorer, we select the `New File` option and create a new file called `MonitorController.cs`.

Then we add the following codes inside the `MonitorController.cs` file.
```csharp
using CodeBehind;

public partial class MonitorController : CodeBehindController
{
	public void PageLoad(HttpContext context)
	{
		MonitorModel model = new MonitorModel();

		model.Name = "ASUS VG278Q";
		model.Manufacturer = "ASUS";
		model.ModelNumber = "VG278Q";
		model.Resolution = "1920x1080";
		model.RefreshRate = 144;
		model.Price = 250.00m;

		View(model);
	}
}
```

We run the project (F5 key). After running the project, You need to add the string `/Monitor.aspx` to the URL.

If you enter the above path in the browser, you will see the following image in the browser.

Screenshot

![MVC screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pded6fa84cy0jtraxuca.png)

The response that is sent to the browser is according to the codes below.

HTML result

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>ASUS VG278Q</title>
</head>
<body>
    <h1>ASUS VG278Q</h1>
    <p>Manufacturer: ASUS</p>
    <p>Model Number: VG278Q</p>
    <p>Resolution: 1920x1080</p>
    <p>Refresh Rate: 144</p>
    <p>Price: 250.00 USD</p>
</body>
</html>
```

In this example, we have a `Monitor.aspx` View that displays the name, manufacturer, model number, resolution, refresh rate, and price of a monitor. The View is bound to a `MonitorModel` class that contains the properties for these values. The `MonitorController` class is responsible for loading the data and passing it to the View.

## Add a new View

For you to understand the concept of MVC, we will add a new View and only slightly change its HTML tags.

In the Visual Studio Code project, we create a new View named `Monitor2.aspx`.

In the Explorer section, by right-clicking on `wwwroot` directory, we select the `New File` option and create a new file called `Monitor2.aspx`.

Then we add the following codes inside the `Monitor2.aspx` file.
```html
@page
@controller MonitorController
@model {MonitorModel}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@model.Name</title>
</head>
<body>
    <h1 style="color: red;">@model.Name</h1>
    <b style="color: green;">Manufacturer: @model.Manufacturer</b>
    <b style="color: blue;">Model Number: @model.ModelNumber</b>
    <b style="color: gray;">Resolution: @model.Resolution</b>
    <b style="color: brown;">Refresh Rate: @model.RefreshRate</b>
    <b style="color: pink;">Price: @model.Price USD</b>
</body>
</html>
```

We run the project (F5 key). After running the project, You need to add the string `/Monitor2.aspx` to the URL.

If you enter the above path in the browser, you will see the following image in the browser.

Screenshot

![MVC new View screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mq5wy87ax8obtjxibay.png)

The response that is sent to the browser is according to the codes below.

HTML result

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>ASUS VG278Q</title>
</head>
<body>
    <h1 style="color: red;">ASUS VG278Q</h1>
    <b style="color: green;">Manufacturer: ASUS</b>
    <b style="color: blue;">Model Number: VG278Q</b>
    <b style="color: gray;">Resolution: 1920x1080</b>
    <b style="color: brown;">Refresh Rate: 144</b>
    <b style="color: pink;">Price: 250.00 USD</b>
</body>
</html>
```

## Change View in Controller

We want to call the new View in the Controller class.

First, we delete the Controller in the `Monitor2.aspx` file.
```diff
@page
-@controller MonitorController
@model {MonitorModel}
+@break
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@model.Name</title>
</head>
<body>
    <h1 style="color: red;">@model.Name</h1>
    <b style="color: green;">Manufacturer: @model.Manufacturer</b>
    <b style="color: blue;">Model Number: @model.ModelNumber</b>
    <b style="color: gray;">Resolution: @model.Resolution</b>
    <b style="color: brown;">Refresh Rate: @model.RefreshRate</b>
    <b style="color: pink;">Price: @model.Price USD</b>
</body>
</html>
```

> Note: We want to call a View from the Controller named `MonitorController`, whose Controller is also `MonitorController`, which causes the Controller named `MonitorController` to call itself one after another, and as a result, the program goes into a loop. Therefore, it is necessary to delete the Controller attribute in the `Monitor2.aspx` file.

If you have noticed, the `break` attribute (`@break`) has also been added to the `Monitor2.aspx` file. The `break` attribute causes the path of the View file to be ignored. In fact, the path below will no longer be directly accessible from the URL:
`example.com/Monitor2.aspx`

We change the `MonitorController` class as follows:
```csharp
using CodeBehind;

public partial class MonitorController : CodeBehindController
{
	public void PageLoad(HttpContext context)
	{
		MonitorModel model = new MonitorModel();

		model.Name = "ASUS VG278Q";
		model.Manufacturer = "ASUS";
		model.ModelNumber = "VG278Q";
		model.Resolution = "1920x1080";
		model.RefreshRate = 144;
		model.Price = 250.00m;

		View("/Monitor2.aspx", model);
	}
}
```

As you can see, in the Controller class above, only the `/Monitor2.aspx` path has been added to the View method.

We run the project (F5 key). After running the project, You need to add the string `/Monitor.aspx` to the URL.

If you enter the above path in the browser, you will see the following image in the browser.

Screenshot

![MVC new View screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mq5wy87ax8obtjxibay.png)

The response that is sent to the browser is according to the codes below.

HTML result

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>ASUS VG278Q</title>
</head>
<body>
    <h1 style="color: red;">ASUS VG278Q</h1>
    <b style="color: green;">Manufacturer: ASUS</b>
    <b style="color: blue;">Model Number: VG278Q</b>
    <b style="color: gray;">Resolution: 1920x1080</b>
    <b style="color: brown;">Refresh Rate: 144</b>
    <b style="color: pink;">Price: 250.00 USD</b>
</body>
</html>
```

Requesting the View path named `Monitor.aspx` causes the Controller named `MonitorController` to be executed. The `MonitorController` Controller also initializes the View named `Monitor2.aspx` with the `MonitorModel` class and sends it to the requester.

For more practice, activate the `IgnoreViewAndModel` attribute in the Controller and see the result again. You can also add a new property such as weight to the data of the `MonitorModel` class and place it in the View and set it in the Controller.

In the next tutorial, we will use a suitable practical example for MVC to display different Views based on URL data (request).

### Related links

CodeBehind on GitHub:
https://github.com/elanatframework/Code_behind

CodeBehind in NuGet:
https://www.nuget.org/packages/CodeBehind/

CodeBehind page:
https://elanat.net/page_content/code_behind