Disadvantages of MVC Architecture in ASP.NET Core
Tags: dotnet, backend, architecture, tutorial
Published: 2024-01-15 21:19:16

## Introduction
In this article, we discuss the disadvantages of MVC architecture in ASP.NET Core; at the same time, we compare the wonderful architecture of the [CodeBehind framework](https://github.com/elanatframework/Code_behind) with ASP.NET Core. For each disadvantage of MVC in ASP.NET Core, we will give an example and we will also add the corresponding example with the CodeBehind framework.

## Simple definition of MVC
MVC is a design pattern that consists of three parts: model, view, and controller. View is the display part. Dynamic data models are placed in the view. Controllers are responsible for determining the view and model for requests.

# Why is MVC not good in ASP.NET Core?


## Controller configuration

To use the MVC design pattern in ASP.NET Core, controllers need to be configured in root routes. This is a weak process that exists in the structure of other MVC frameworks. In this structure, the request reaches the route and the route recognizes the controller based on text patterns and then calls the controller. The configuration of the controller in the route is a wrong structure that is placed at the beginning of the request and response cycle and causes problems for that structure.

MVC diagram in ASP.NET Core

![MVC diagram in ASP.NET Core](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bcr6xjr2m4wr9zkuk4y.png)

In the CodeBehind framework, the controller is specified in the attributes section of the view page.

MVC diagram in CodeBehind Framework

![MVC diagram in CodeBehind Framework](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31i6824nig5qnuhmysei.png)


The following code is the routing format in ASP.NET Core, which is determined in the Program.cs file.

```csharp
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
```

This is a three-part pattern where the first part calls the controller and the second part executes the controller method (we won't cover the third part because it's out of the scope of the article). The path below specifies which controller class and method should be executed.
`example.com/ControllerName/MethodName`

Example
URL path:
`example.com/Gallery/Index`

According to this example, the controller class with the name Gallery and Index method will be executed.
Note: The Index method is the default method of the controller class. Also note that you can configure this three-part pattern in a different way.

The simplest type of web programming is to add an executable script file in the physical path and execute that file in the URL path.

Example

Physical path:
`root/page/gallery.aspx`

URL path:
`example.com/page/gallery.aspx`

In the CodeBehind framework, we follow the simple example above. To determine the controller class, it is enough to add the controller class in the attributes section of the aspx page.

Example:
```diff
@page
+@controller Gallery
<!DOCTYPE html>
<html>
...
```

According to the codes above, in the CodeBehind framework, it is only necessary to determine the controller in the view, and there is no need for routing or configuring the controller in the route.

The controller class named Gallery is added in the above code. After executing the gallery.aspx file path, the controller class named Gallery is executed.

Note: It is not necessary that the name of the Gallery controller and the name of the aspx page (gallery.aspx) be the same.

In ASP.NET Core we have an abstract view and it is difficult to understand the path and structure. While in the CodeBehind framework, the simplest web programming structure remains intact and the URL path is the same as the physical path.

The process of creating the controller configuration in the route is challenging and difficult to understand for many.


## Controller class

This is a simple example of a MVC in ASP.NET Core:

Controller in ASP.NET Core
```csharp
using Microsoft.AspNetCore.Mvc;

namespace ProjectName
{
	public class ContactController : Controller
	{
		public IActionResult Index()
		{
			ViewData["Message"] = "Your contact page.";

			AddressModel model = new AddressModel()
			{
				Name = "Microsoft",
				Street = "One Microsoft Way",
				City = "Redmond",
				State = "WA",
				PostalCode = "98052-6399"
			};

			return View(model);
		}
	}
}
```

Model in ASP.NET Core
```csharp
namespace ProjectName
{
    public class AddressModel
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}
```

View in ASP.NET Core (Index.cshtml)
```html
@page
@model ProjectName.AddressModel

<h2>@ViewData["Message"]</h2>
<address>
    @Model.Name<br>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>
```

This also shows an example of MVC in the CodeBehind framework, which is made exactly according to the example of the above MVC codes in ASP.NET Core.

Controller in CodeBehind Framework
```csharp
using CodeBehind;

namespace ProjectName
{
    public class ContactController : CodeBehindController
    {
        public void PageLoad(HttpContext context)
        {
            ViewData.Add("Message", "Your contact page.");

            AddressModel model = new AddressModel()
            {
                Name = "Microsoft",
                Street = "One Microsoft Way",
                City = "Redmond",
                State = "WA",
                PostalCode = "98052-6399"
            };

            View(model);
        }
    }
}
```

Model in CodeBehind Framework
```csharp
using CodeBehind;

namespace ProjectName
{
    public class AddressModel : CodeBehindModel
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}
```

View in CodeBehind Framework (contact.aspx)
```html
@page
@controller ProjectName.ContactController
@model ProjectName.AddressModel

<h2>@ViewData.GetValue("Message")</h2>
<address>
    @model.Name<br>
    @model.Street<br>
    @model.City, @model.State @model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>
```

As you can see, there is not much difference between MVC in ASP.NET Core and CodeBehind framework. Our discussion is about the controller and we added the view and the model just so that you can better understand how the controller works.

In ASP.NET Core, the controller class and method are called according to the pattern specified in the route. View is a file with the extension cshtml, which is usually the same as the name of a method in the controller.. This file must also be located in the directory with the same name as the controller's class name.

Note: It is not mandatory that the name of the method in the controller be the same as the name of the view file; but if not, the path of the view file must be added in the View method.

But in the CodeBehind framework, the controller class is added in the view file just like the model class. View in CodeBehind is a file with aspx extension. Therefore, you don't need to create controller class methods with the same name as the View file name.

In the ASP.NET Core controller, you must return the `View` method to the `IActionResult` return data type. The return data type of `IActionResult` is dumb.

But in the CodeBehind controller, you don't need to return the `View` in the method. You can call the `View` in any method of the controller class that you like.

In ASP.NET Core, every public method is an action, and if you want to use a public method that leaves the action state, you must add the `[NonAction]` attribute to the top of the method. Not only does it get complicated, but it also becomes difficult for beginners to understand.

The controller in the CodeBehind framework has only one PageLoad method; CodeBehind provides you with various features so that you can easily manage multiple views and models in the controller.

**Is it really necessary for the controller to control more than one view?**

Managing two or more separate views (Several views that have nothing to do with each other) in the controller is against the spirit of MVC. But if these views are related or have the same model, they must be managed in the same controller.

In the controller example, let's add a new view whose model is the same as the current view.

We add a view called Index2.cshtml. The view model is the same as the view model of Index.cshtml file. We only change the HTML tags.

View in ASP.NET Core (Index2.cshtml)
```html
@page
@model ProjectName.AddressModel

<h2 class="box"><b>@ViewData["Message"]</b></h2>
<hr>
<address>
    <p><b>Name:</b> @Model.Name</p>
    <p><b>Street:</b> @Model.Street</p>
    <p><b>City:</b> @Model.City, @Model.State @Model.PostalCode</p>
    <p><b>Phone:</b> <abbr title="Phone">P:</abbr> 425.555.0100</p>
</address>
<hr>
```

If we want to call the new view in the ASP.NET Core controller, we need to add the Index2 method.

```diff
using Microsoft.AspNetCore.Mvc;

namespace ProjectName
{
    public class ContactController : Controller
    {
        public IActionResult Index()
        {
            ViewData["Message"] = "Your contact page.";

            AddressModel model = new AddressModel()
            {
                Name = "Microsoft",
                Street = "One Microsoft Way",
                City = "Redmond",
                State = "WA",
                PostalCode = "98052-6399"
            };

            return View(model);
        }
		
+       public IActionResult Index2()
+       {
+           ViewData["Message"] = "Your contact page.";

+           AddressModel model = new AddressModel()
+           {
+               Name = "Microsoft",
+               Street = "One Microsoft Way",
+               City = "Redmond",
+               State = "WA",
+               PostalCode = "98052-6399"
+           };

+           return View(model);
+       }
    }
}
```

You can't even write a new method like this.

```diff
-       public IActionResult Index2()
-       {
-           return Index();
-       }
```

This will cause the Index.cshtml view file to run.

If we want to call the new view in the CodeBehind framework, we just need to create the new view.

We add a view called contact2.aspx. The view model is the same as the view model of contact.aspx file. We only change the HTML tags.

View in CodeBehind framework (contact2.aspx)
```html
@page
@controller ProjectName.ContactController
@model ProjectName.AddressModel

<h2 class="box"><b>@ViewData.GetValue("Message")</b></h2>
<hr>
<address>
    <p><b>Name:</b> @model.Name</p>
    <p><b>Street:</b> @model.Street</p>
    <p><b>City:</b> @model.City, @model.State @model.PostalCode</p>
    <p><b>Phone:</b> <abbr title="Phone">P:</abbr> 425.555.0100</p>
</address>
<hr>
```

The above example from the CodeBehind framework shows that specifying the controller in the view eliminates the need to specify the view in the controller.

Here it is clear that there is no need to change the controller class for views with the same model in the CodeBehind framework. This is the wonderful architecture of the CodeBehind framework.

CodeBehind is .NET Diamond!

**What does the input argument have to do with the query string?**

One of the features of MVC in ASP.NET Core is that you can add query strings as input arguments in action methods. This feature can be set by setting the pattern in the route section.

Example
```csharp
public IActionResult Welcome(string name, int numTimes = 1)
{
    ViewData["Message"] = "Hello " + name;
    ViewData["NumTimes"] = numTimes;
    return View();
}
```

The above example shows a method located in a controller in ASP.NET Core.
The input arguments name and numTimes correspond to the query name corresponding to the name of the arguments and their values are automatically set in the methods. This is a static and simple structure.

Example URL: `example.com/HelloWorld/Welcome?name=Rick&numtimes=4`

Of course, this is a feature and there is no need to follow it. But it must be said that this feature is very dumb and reduces the understanding of the program.

In the CodeBehind framework, we can access any type of data as an input argument in the controller. For example, query string, form data, cookie, session, etc. This possibility helps to increase the dynamics of the systems.

In order to implement the above example in the CodeBehind framework, we must enter the desired data in front of the name of the controller in the view file; in the controller section, it is also necessary to call the CodeBehindConstructor method and specify the argument values in it.

Example

View file
```html
@page
@controller ProjectName.ContactController(context.Request.Query["name"].ToString(), context.Request.Query["numTimes"].ToNumber())
...
```

CodeBehind Constructor method in controller class
```csharp
public void CodeBehindConstructor(string name, int numTimes = 1)
{
    ViewData.Add("Message", "Hello " + name);
    ViewData.Add("NumTimes", numTimes.ToString());
    View();
}
```

As you can see, we did the same thing in ASP.NET Core in the CodeBehind framework. We can do more advanced and different things by using the constructor method in the controller.

## Common structure of MVC and Razor Page

Apart from the CodeBehind framework, there are two common frameworks for developing systems in ASP.NET Core; one is MVC and the other is Razor Page. The storage location of the files of these two structures is also separate; for MVC the Views directory and for Razor Page the Pages directory.
In ASP.NET Core, if we want to have MVC together with Razor pages in one project, it becomes difficult to manage the project, and we also need to configure both.
In the CodeBehind framework, we can develop the system in four ways; you can develop your systems as MVC, Model-View, Controller-View or only View in CodeBehind. You can develop different parts of the system as you want and there is no need to change the configuration or add settings. The storage location of the view files in the CodeBehind framework is the same in any case.

**Partial View and view component**

In ASP.NET Core, if you want to divide the view into different parts, you need to use partial view. If you want to create a more advanced partial view, you should also use the output values of `PartialViewResult` and return `PartialView`. partial view is a vague, complicated and redundant structure and there is no justification for its existence; also, in order to learn how the partial view works, you must learn a different structure from the view structure.

Coding a View Component is also complicated and you need to put a lot of effort into creating a View Component. The `IViewComponentResult` return value and method names like `Invoke()` make development very difficult.

In the CodeBehind framework, you only need to add a page and call the page. only this! You can create view pages however you like and call them in other pages.

Calling partial view and view component in ASP.NET Core is not the same and also complicated; while in the CodeBehind framework, it is enough to use the `LoadPage` method.

Partial view example
```diff
@page
<!DOCTYPE html>
<html>
	<head>
		<title>@ViewData["title"]</title>
	</head>
	<body>
+@Html.Partial("Header")
...
```

view cimponent example

Calling pages on other pages in the CodeBehind framework
```diff
@page
@islayout
<!DOCTYPE html>
<html>
	<head>
		<title>@ViewData.GetValue("title")</title>
	</head>
	<body>
+@LoadPage("/header.aspx")
...
```

The page that is called with the `PageLoad` method also has access to `ViewData`; so you can initialize the `ViewData` before calling the page. If you need HttpContext access on the page you want to call, you should write the LoadPage method as follows.

```diff
+@LoadPage("/header.aspx", context)
```

In the CodeBehind framework, if you add the `@break` attribute in the attributes section of the page view, the page will be removed from direct access.

Example
```diff
@page
+@break
<header>
...
```

You can also use the template; by explaining that the template only replaces the code and only reduces the need to rewrite the codes.

Example using template in CodeBehind framework
layout.aspx
```diff
@page
@islayout
+@template "/layout-template.astx"
<!DOCTYPE html>
<html>
    <head>
        <title>@ViewData.GetValue("title")</title>
    </head>
    <body>
+@{string backgroundColor = "red";}
+@#header
...
```

layout-template.astx
```html
@#header{
<header style="background-color:@backgroundColor;">
...
</header>
}
```

Before compiling the view files in the CodeBehind framework, the values of the template blocks are automatically placed in the template variables.
Example

Temporary value of the layout.aspx file before compilation
```html
@page
@islayout
@template "/layout-template.astx"
<!DOCTYPE html>
<html>
    <head>
        <title>@ViewData.GetValue("title")</title>
    </head>
    <body>
@{string backgroundColor = "red";}
<header style="background-color:@backgroundColor;">
...
</header>
...
```

## Read more

Creating a simple MVC project in ASP.NET Core is complicated.

To learn about MVC in ASP.NET Core, you can read the following links in order:

 - [Get started with ASP.NET Core MVC](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc)
 - [Part 2, add a controller to an ASP.NET Core MVC app](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-controller)
 - [Part 3, add a view to an ASP.NET Core MVC app](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-view)
 - [Part 4, add a model to an ASP.NET Core MVC app](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model)
 - [Partial views in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial)
 - [View components in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components)

After reading the above, please also read the following article about MVC in the CodeBehind framework:

 - [Simple and structured MVC in CodeBehind](https://github.com/elanatframework/Code_behind/blob/elanat_framework/doc/simple_and_structured_mvc_in_code_behind.md)

## MVC in CodeBehind Framework

MVC is very simple in CodeBehind. Simplicity does not mean that the project is simple and basic, and it is the result of a lot of work and years of research. The CodeBehind framework is completely modular and can be used for very large scales.
When you use CodeBehind, you don't necessarily have to use the MVC pattern; you can create simple view-only pages and don't worry about scaling your app, you can easily add controller and model attributes to the current page.

## Conclusion

The need to configure the controller in the route and the complex structure of the controller are among the disadvantages of the MVC structure in ASP.NET Core, which cause complexity and reduce the understanding of the program. Compared to ASP.NET Core, the CodeBehind framework is an engineering masterpiece. CodeBehind offers a fantastic MVC architecture that gives new meaning to the MVC pattern; in this architecture, the route is removed and, like the model, the controller is also determined in the view.

### Related links

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

Get CodeBehind from NuGet:
https://www.nuget.org/packages/CodeBehind/

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