MVC Example - Display Information Based on URL
Tags: tutorial, dotnet, beginners, backend
Published: 2024-06-10 09:06:02

In this tutorial, we want to teach you a practical MVC project (series website). In the project, we check the sent URL values ​​in the Controller and send the appropriate response.

## Activation of static files in ASP.NET Core

In this project, we call the data from XML and put it in the Model and respond to the user. This project has static image and style files and we need to configure the middleware to support static files in ASP.NET Core first.

To support static files, simply call `app.UseStaticFiles()` middleware before `app.UseCodeBehind()` middleware.

Config for support static files
```diff
var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

+app.UseStaticFiles();

SetCodeBehind.CodeBehindCompiler.Initialization();

app.UseCodeBehind();

app.Run();
```

## Add static file

In Visual Studio Code, we first create a directory named `style` in the `wwwroot` directory and then create a file named `series.css` in it and add the following style in it:

CSS file
```css
.series_item
{
    float: left;
    display: table;
    margin: 10px;
    border-bottom: 4px solid #eee;
}

.series_item a
{
    text-decoration: none;
    color: #555;
}

.series_item h2
{
    background-color: #eee;
    text-align: center;
}

.series_item img
{
    height: 570px;
    width: 320px;
    object-fit: cover;
    border-radius: 10px;
}

.series_content p
{
    line-height: 24px;
    color: #444;
}

.series_content img
{
    max-width: 900px;
}
```

In this project, we want to show the image of the series. For this, we first create a directory named `image` in the `wwwroot` directory and then put 4 photos related to the series in it.

You can find photos on the Internet:
- Joy-of-Life-season-2-poster.jpg
- first-sword-of-wudang-poster.jpg
- demi-gods-and-semi-devils-poster.jpg
- side-story-of-fox-volant-poster.jpg

## Series data

We want to retrieve series data from an XML file. To create it, we first create a directory named `data` in our project directory and then create a file named `series_list.xml` in it and add the following data in it:

XML data
```xml
<?xml version="1.0" encoding="UTF-8"?>

<series_lis>
	<series>
		<title>Joy of Life Season 2</title>
		<url_value>joy-of-life-season-2</url_value>
		<genre>Romantic, Fantasy, Comedy, Wuxia</genre>
		<year>2024</year>
        <rating>8.9</rating>
        <image>Joy-of-Life-season-2-poster.jpg</image>
		<about>Fan Xian, the illegitimate son of the finance minister found love with Lin Wan Er, the daughter of the Princess Royal. They wanted to live peaceful lives, but a scheming prince plotted his demise. Fan Xian was forced to fake his death to escape certain doom. Now, he has decided to return to learn the truth behind a dastardly conspiracy. Can he break through the webs of lies and deceit to expose the plotters - and live happily ever after with his beloved bride?</about>
	</series>
	<series>
		<title>First Sword of Wudang</title>
		<url_value>first-sword-of-wudang</url_value>
		<genre>Historical, Romantic, Wuxia</genre>
		<year>2021</year>
		<rating>7.3</rating>
        <image>first-sword-of-wudang-poster.jpg</image>
		<about>During the late Ming dynasty, a time when the nation faced enemies externally and within, the young hero Geng Yu Jing discovered that his birth parents' death was due to a conspiracy that snared the pugilist world. As he embarked on a journey of self-discovery traveling back to his birthplace at Northeast frontiers of China, he uncovered dark secrets of the past, found warm friendship, and romance but also sorrow and enmity. These adventures eventually shaped him to became the legend known as the 'First Sword of Wudang'.</about>
	</series>
	<series>
		<title>Demi Gods and Semi Devils</title>
		<url_value>demi-gods-and-semi-devils</url_value>
		<genre>Historical, Romantic, Comedy, Wuxia</genre>
		<year>2021</year>
		<rating>7.5</rating>
        <image>demi-gods-and-semi-devils-poster.jpg</image>
		<about>Set under the reign of Emperor Zhe Zong of Song, the story revolves around the experiences of Qiao Feng, leader of the beggar clan, Duan Yu, a prince of Dali and Xu Zhu, a Shaolin monk. The three protagonists become sworn brothers during their journey in the pugilistic world.

Qiao Feng is the courageous leader of the beggar clan. Many look up to him as a hero for defending the people of Song. When Qiao Feng is accused of being of Khitan descent and labeled a traitor, he is shunned by his fellow martial artists. In Qiao Feng's quest to clear his name, he comes to learn the truth about his identity and meets the love of his life. He also crosses paths with Dali Prince Duan Yu and Shaolin Monk Xu Zhu.

Duan Yu is a cheerful and bright young prince of Dali. Because of his peace-loving tendencies, he runs away to avoid being forced to learn martial arts but ends up inadvertently mastering powerful martial arts techniques. Successively, he meets Mu Wan Qing and Zhong Ling and falls deeply in love with Wang Yu Yan and her godlike beauty. However, Wang Yu Yan only has eyes for her cousin Murong Fu which complicates their relationship.

Shaolin Monk Xu Zhu is innately pure. After being guided by a martial arts master, he also becomes a powerful martial artist. It starts the kind-hearted monk on an adventure he never imagined for himself. Caught in the conflict between Song and Liao, three intertwining stories are brought together in a story about their heroism.</about>
	</series>
	<series>
		<title>Side Story of Fox Volant</title>
		<url_value>side-story-of-fox-volant</url_value>
		<genre>Romantic, Wuxia</genre>
		<year>2022</year>
		<rating>8.3</rating>
        <image>side-story-of-fox-volant-poster.jpg</image>
		<about>In a realm dominated by martial arts experts, heroes, and villains, Hu Fei is a young, brave, justice-loving man on a quest for revenge. His father was killed, leaving him an orphan and thirsting for vengeance. During his quest, he encounters a tyrannical warlord who he believes has wronged him and others. But things get complicated when he then falls for that same warlord's daughter, the stunning Yuan Zi Yi.

Hu Fei begins to mature and also becomes involved in a mission to find a medical cure that will help restore the vision of his sworn uncle, legendary hero Miao Ren Fang, who he has long believed was responsible for his father’s death. While he searches for this medicine, he meets the young female apprentice of the Poison Hand Medicine King, a woman named Cheng Ling Su. She develops feelings for him, too, complicating matters of the heart.

As his journey leads him to meet more martial artists and learn from them, Hu Fei starts to suspect that his father's death did not quite happen in the way he originally believed. Will he ever learn the true identity of the killer? Where will his quest for justice ultimately lead?</about>
	</series>
</series_lis>
```

## Series Models

We create a Model named `SeriesModel` for series information as below.

SeriesModel
```csharp
public class SeriesModel
{
    public int SeriesId { get; set; }
    public string SeriesTitle { get; set; }
    public string SeriesUrlValue { get; set; }
    public string SeriesGenre { get; set; }
    public string SeriesImage { get; set; }
    public string SeriesRating { get; set; }
    public string SeriesYear { get; set; } 
    public string SeriesAbout { get; set; } 
}
```

We also create a Model with the name `SeriesModelList` as below.

SeriesModelList
```csharp
public class SeriesModelList
{
    public List<SeriesModel> SeriesModels = new List<SeriesModel>();
}
```

## Series Views

In this project we want to have two pages, one to display the list of movies and one to display the movies individually with more information.

First, we create a directory called `series_page` in the `wwwroot` directory.
We add a file called `content.aspx` in the `series_page` directory and put the following contents in it:

View (content.aspx)
```html
@page
@model {SeriesModel}
@break
<!DOCTYPE html>
<html>
    <head>
        <title>@model.SeriesTitle</title>
        <link rel="stylesheet" type="text/css" href="/style/series.css" />
    </head>
    <body>
        <div class="series_content">
            <h2>Series name: @model.SeriesTitle</h2>
            <img src="/image/@model.SeriesImage" alt="@model.SeriesTitle">
            <p>Genre: @model.SeriesGenre</p>
            <p>Rating: @model.SeriesRating</p>
            <p>Year: @model.SeriesYear</p>
            <p>About: @model.SeriesAbout</p>
        </div>
    </body>
</html>
```

It is clear, we activated the `break` feature to prevent direct access to the path of this file.

We set `SeriesModel` as the Model on this page.

The `content.aspx` file is created to display a single series.

To display the list of movies, we add a file named `main.aspx` in the `series_page` directory and put the following contents in it:

View (Main.aspx)
```html
@page
@model {SeriesModelList}
@break
<!DOCTYPE html>
<html>
    <head>
        <title>Series information</title>
        <link rel="stylesheet" type="text/css" href="/style/series.css" />
    </head>
    <body>
        <h1>Series information</h1>
        <hr>

        @foreach(SeriesModel TmpModel in @model.SeriesModels)
        {
            <div class="series_item">
                <a href="/series/@TmpModel.SeriesUrlValue">
                    <h2>@TmpModel.SeriesTitle</h2>
                    <img src="/image/@TmpModel.SeriesImage" alt="@TmpModel.SeriesTitle">
                </a>
                <p>Genre: @TmpModel.SeriesGenre</p>
                <p>Rating: @TmpModel.SeriesRating</p>
                <p>Year: @TmpModel.SeriesYear</p>
            </div>
        }

    </body>
</html>
```
We also activated the break feature for this page.

We have set `SeriesModelList` as Model in this page. The `SeriesModelList` class contains a list of `SeriesModel` type named `SeriesModels`. We initialize the `SeriesModel` class once for each series in the Controller and add the `SeriesModels` class and then initialize the `SeriesModel` values ​​in the View with a foreach loop.

As you know, in the modern architecture of the CodeBehind framework, there is no need to configure the Controller in the Route, and the requests reach the View path for the first time, then the View calls the Controller.

First, we create a directory named `series` in the `wwwroot` directory, then we create a new View file named `Default.aspx` in this directory and put the following codes in it:

View (Default.aspx)
```html
@page
@controller SeriesController
@section
```

## Prevent access Default.aspx

Before you develop a project in the CodeBehind framework, it is best to disable access to the `Default.aspx` path. To do this, first in the `code_behind` directory, edit the options file and set the `prevent_access_default_aspx` option to `true`.

options.ini
```ini
[CodeBehind options]; do not change order
...
prevent_access_default_aspx=true
```

We will soon provide a complete explanation of the options file in the CodeBehind framework.

## Series Controller

We create a Controller class according to the following codes:

SeriesController
```csharp
using System.Xml;
using CodeBehind;

public partial class SeriesController : CodeBehindController
{
    public void PageLoad(HttpContext context)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load("data/series_list.xml");

        if (Section.Count() == 1)
        {
            string Section0 = System.Web.HttpUtility.UrlEncode(Section.GetValue(0));
            XmlNode SeriesNode = doc.SelectSingleNode("series_lis/series[url_value='" + Section0 + "']");
            
            if (SeriesNode == null)
            {
                IgnoreViewAndModel = true;
                Write("Series not exist!");
                return;
            }

            SeriesModel model = new SeriesModel();

            model.SeriesTitle = SeriesNode["title"].InnerText;
            model.SeriesUrlValue = SeriesNode["url_value"].InnerText;
            model.SeriesGenre = SeriesNode["genre"].InnerText;
            model.SeriesImage = SeriesNode["image"].InnerText;
            model.SeriesRating = SeriesNode["rating"].InnerText;
            model.SeriesYear = SeriesNode["year"].InnerText;
            model.SeriesAbout = SeriesNode["about"].InnerText;

            View("/series_page/content.aspx", model);
        }
        else if (Section.Count() == 0)
        {
            SeriesModelList model = new SeriesModelList();

            XmlNodeList SeriesListNode = doc.SelectSingleNode("series_lis").ChildNodes;

            int i = 1;
            foreach (XmlNode SeriesNode in SeriesListNode)
            {
                SeriesModel series = new SeriesModel();
                series.SeriesId = i;
                series.SeriesTitle = SeriesNode["title"].InnerText;
                series.SeriesUrlValue = SeriesNode["url_value"].InnerText;
                series.SeriesGenre = SeriesNode["genre"].InnerText;
                series.SeriesImage = SeriesNode["image"].InnerText;
                series.SeriesRating = SeriesNode["rating"].InnerText;
                series.SeriesYear = SeriesNode["year"].InnerText;
                model.SeriesModels.Add(series);

                i++;
            }

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

In the Controller class, the series information is first read from the XML file to be retrieved for display on the required pages. Then it checks Section to determine if the requested information is to display a specific series or a list of series.

If there is only one Section, that is, the request is to display a specific series, the corresponding model is created and sent to the content.aspx page. If there is no Section, that is, the request is to display the list of all series, the corresponding model is created and sent to the main.aspx page. Here, two models named SeriesModel and SeriesModelList are defined, which contain the information of each series (for single display) and a list of information of all series.

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

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

Screenshot

![Series list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfc3sezq2twtak81e78k.jpg)

We click on one of the series and then a URL is requested according to the pattern below.

`/series/series-url-value`

Example:

`/series/side-story-of-fox-volant`

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

Screenshot

![Alone Series](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4f83tl2l76vuht85hw87.jpg)

In the next tutorial, we will teach you layouts. We add Layout to this very project so you can better understand the benefits of Layout.

### 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