Showing posts with label ASP.NET MVC. Show all posts
Showing posts with label ASP.NET MVC. Show all posts

Tuesday, July 11, 2023

ASP.NET Core UseStaticFiles method


ASP.NET Core UseStaticFiles is an extension method of IApplicationBuilder. This is used in HTTP pipeline to enable the service of static files in the application. The HTTP request for a static file cannot be handled by the application unless this method is used during HTTP pipeline configuration.

In ASP.NET Core, static files are served from the web root path specified in WebRootPath or WebRootFileProvider. The default web root is the 'wwwroot' folder in solution explorer.

The UseStaticFiles has three overloaded versions.
namespace Microsoft.AspNetCore.Builder
{
    // Extension methods for the StaticFileMiddleware
    public static class StaticFileExtensions
    {
        //     Enables static file serving for the current request path
        public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app);

        //     Enables static file serving for the given request path
        public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, string requestPath);

        //     Enables static file serving with the given options
        public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options);
    }
}

Three versions

  • The first version enables the service for static files from the wwwroot folder, and the current request path is not required as it is the current domain path. 
  • The second version allows to add a request path string as its parameter. This request path is added after the current domain path. This is a dummy string not representing any folder but business logic.
  • The third version allows to add options to serve the static files.
UseStaticFiles Version2
Request Path: We are using .NET5.0 to explain it. Look at the following code which is in Configure method of Startup class. The request path parameter is used in 2nd version of UseStaticFiles. Because of request path parameter, any static file can be accessed from wwwroot just by appending MyCss after the domain name in the URL. Both search.png and upload.png are in the same wwwroot folder in images subfolder but can be accessed using either of the following URL.
            app.UseStaticFiles(); // https://localhost:44309/images/search.png
            app.UseStaticFiles("/MyCss"); //https://localhost:44309/MyCss/images/upload.png
The MyCss is a request path parameter in the UseStaticFiles. Note that MyCss is not a folder in the wwwroot.
UseStaticFiles Version3
StaticFileOptions: The files can be served based on different options such as content-types, file system used, request path, web root folder etc. We use StaticFileOptions class to meet these options as required. Look at the following code in which StaticFileOptions object is used with its various properties to access files from NewWebRoot folder. Note that we do not use UseWebRoot method to configure the web root in the Program class.
            app.UseStaticFiles(new StaticFileOptions()
            {
                DefaultContentType = "text/html",
                FileProvider = new PhysicalFileProvider(Path.Combine(System.IO.Directory.GetCurrentDirectory(), "NewWebRoot")),
                RequestPath = "/Sales"

            });
Create a folder Images in NewWebRoot folder and place an image in the Images folder. Run the application. Now use the URL https://localhost:44391/sales/Images/happy.jpg in the address bar. Press Enter. You get the image file happy.jpg placed in the Images folder. Note that in this example, request path sales is mandatory.

FileProvider property of StaticFileOptions class is used to locate resources such as page, view, static files such as images, xml, files, CSS files etc. from the root path specified as parameter. 
  • The Microsoft.Extensions.FileProviders namespace is used for different file providers.
  • File Provider three Interfaces are IFileInfo, IDirectoryContents, IChangeToken. 
  • The primary interface is IFileProvider which is used to obtain file and directory information and change in them. 
  1. GetDirectoryContents(String) enumerates a directory at the given path, if any.
  2. GetFileInfo(String) locates a file at the given path.
  3. Watch(String) creates a IChangeToken for the specified filter.
Look at the following code which includes all 3 versions of UseStaticFiles.

            // https://localhost:44309/images/search.png
            app.UseStaticFiles(); 
            //https://localhost:44309/MyCss/images/upload.png
            app.UseStaticFiles("/MyCss"); 
            //https://localhost:44309/mystaticfiles/products.xml
            app.UseStaticFiles(new StaticFileOptions
            {
               FileProvider= new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "NewWebRoot")),
               RequestPath ="/MyStaticFiles"
            });

Monday, July 10, 2023

Partial View Introduction and Applications


What is Partial view

  • A partial view is a portion of view content which is used to render some specific business UI which is common among some regular views. The partial view is shared among these regular views.
  • A partial view is created using the same Razor View template which is used to create a standard view. A standard view is the view which is based on Action method view result.
  • Same partial view can be used on multiple views (which may be regular view or layout view). Partial view follows DRY principle. Create once, use many times anywhere needed.
  • A partial view has same file extension(.cshtml) as regular view. A view and partial view file extension depend on two things i.e. view engine and the programming language.
  • Partial view cannot have HTML tags like HTML, head, title, body, meta because these are already defined in the layout view. It will have other HTML tags like h1, p, div etc. needed for the component. This fact is applicable on regular views also. We do not use Head part of HTML in regular view.
  •  A partial view is created inside Shared folder because it can be shared among standard views. 
  •  As convention, partial view name begins with underscore. 
  •  A partial view is a regular view which can be used on any view - regular or layout view. 
  •  Note that other regular views must be rendered inside layout view if layout view is being used in the application but partial view can be applied on other views without using it on layout view. 
  •  A partial view can be used on layout view to render common features such as navigation bar on multiple views. 
  •  A partial view can be used on standard and layout views.
  • File extension for Razor Partial View in C# is .cshtml.
  • File extension for Razor Partial View in VB is .vbhtml.
  • File extension for ASPX Partial View in C# or VB is .ascx.

How to Create Partial View in MVC?

Partial view is a shared view because it is shared among different views and so it is created in Views/Shared folder. To create a partial view, right click on Views/Shared folder in solution explorer and click on "Add" and then "View" item. The "Add New Scaffolded Item" windows appears Select "Razor View" and then click "Add" button. Another window "Add Razor View" appears as shown below.


Fill the text boxes as as per the need.
Must check mark the "Create a partial view" option  
Note that the name of partial view should begin with underscore.

How to Use Partial View in another normal view?

Look at the following code.


<div>
    <partial name="_PVProgrammers" model="@Model"></partial>
</div>

The partial tag is used to insert a partial view into a normal view. Normal view is created for an action method of a controller. The partial tag can be inserted into normal view at any position as per the business need.

Applications of Partial view

  • To provide common look and feel in different views portion but not for layout; instead for a business logic such as display list of items in the partial view.
  • To refresh page without reloading in MVC; partial view is used to display data without refresh
  • To fetch data from database without refreshing the page in ASP.NET Core

How to use partial view with AJAX jQuery

We look at a simple example to use partial view to list the records and use JQuery Ajax to refresh it. We also use the jQuery AJAX to perform CRUD operations in ASP.NET Core MVC.

Example

Create ASP.NET Core MVC application using Model-View-Controller template.
  • Project name: PartialViewCoreMvc
  • Solution name: PartialViewCoreMvc
  • .NET Core version: 6.0

Install the following Entity Framework Packages using Install-Package command.
  • Microsoft.EntityFrameworkCore Version="6.0.0"
  • Microsoft.EntityFrameworkCore.Design Version="6.0.0"
  • Microsoft.EntityFrameworkCore.Tools Version="6.0.0"
  • Microsoft.EntityFrameworkCore.SqlServer Version="6.0.0"
Add the connection string into the appsettings.json file available in the content root of the application in solution explorer. 

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=AppliedK4;Integrated Security=True;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False"
  },
  "AllowedHosts": "*"
}

Create Programmer class in Models folder as given below.


namespace PartialViewCoreMvc.Models
{
    public class Programmer
    {
        public int ProgrammerId { get; set; }
        public string? ProgrammerName { get; set; }
        public string? Language { get; set; }
    }
}

Create ProgrammerViewModel class in Models folder as given below.


namespace PartialViewCoreMvc.Models
{
    public class ProgrammerViewModel
    {
        public string? Name { get; set; }
        public string? Language { get; set; }
    }
}

Create a class called AppDbContext in Data folder in the solution explorer as shown below.


using Microsoft.EntityFrameworkCore;
using PartialViewCoreMvc.Models;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options) : base(options)
    {

    }
    public DbSet Programmers { get; set; }
}

Run the following two commands in sequence using Tools > Nuget Package manager > Package manager Console.

  • Add-Migration Initial
  • Update-Database

Check that Migrations folder is created in the solution explorer. In this folder, a partial class named Initial will be created as per add-migration command.

  • Database will be created as given in the appsettings.json file.
  • Also, tables will be created in the database as per DbSet properties given in AppDbContext class file.

Now do the following.

  1. Delete HomeController available in Controllers folder in solution explorer. 
  2. Delete Views/Home folder available in solution explorer.
  3. Create ProgrammerController in Controllers folder.
  4. Create Views/Programmer/Index view for Index action of the ProgrammerController.
  5. Install the Twitter-Bootstrap 4 version using Client Side Library.
  6. Rebuild the application by pressing CTRL+SHIFT+B

The ProgrammerController code is as follows.


using Microsoft.AspNetCore.Mvc;
using PartialViewCoreMvc.Models;

public class ProgrammerController : Controller
{
    private readonly AppDbContext _dbcontext;
    public ProgrammerController(AppDbContext applicationDbContext)
    {
        _dbcontext = applicationDbContext;
    }
    public IActionResult Index()
    {
        return View(_dbcontext.Programmers.Select(c => new ProgrammerViewModel() { Name = c.ProgrammerName, Language = c.Language }).ToList());
    }

    [HttpPost]
    public IActionResult Create(ProgrammerViewModel model)
    {
        if (ModelState.IsValid)
        {
            _dbcontext.Programmers.Add(new Programmer() { ProgrammerName = model.Name, Language = model.Language });
            _dbcontext.SaveChanges();
        }
        //after create new item, requery the database and return the ProgrammerList partial view to update the list.
        return PartialView("_PVProgrammers", _dbcontext.Programmers.Select(c => new ProgrammerViewModel() { Name = c.ProgrammerName, Language = c.Language }).ToList());
    }
}

The Index view code is as follows.


@model List<PartialViewCoreMvc.Models.ProgrammerViewModel>

@{
    ViewData["Title"] = "Index";
}

<div class="row">
    <div class="col-md-4">
        <div class="form-group">
            <label for="Name" class="control-label">Name</label>
            <input name="Name" id="txtname" class="form-control" />
        </div>
        <div class="form-group">
            <label for="Language" class="control-label">Language</label>
            <input Name="Language" id="txtLanguage" class="form-control" />
        </div>
        <br/>
        <div class="form-group offset-6">
            <input type="button" id="submit" value="Add New Programmer" class="btn btn-primary" />
        </div>
    </div>
</div>
<br/>

<div id="itemlist">
    <partial name="_PVProgrammers" model="@Model"></partial>
</div>

@section Scripts{
    <script>
        $(function () {
            $("#submit").click(function () {
                var ProgrammerViewModel = {}; //create an object
                ProgrammerViewModel.Name = $("#txtname").val();
                ProgrammerViewModel.Language = $("#txtLanguage").val();
                
                var currentdate = new Date();
                var datetime = "Last created: " + currentdate.getDate() + "-"
                + (currentdate.getMonth()+1)  + "-" 
                + currentdate.getFullYear() + " "  
                + currentdate.getHours() + ":"  
                + currentdate.getMinutes() + ":" 
                + currentdate.getSeconds();
                console.log(datetime);

                $.ajax({
                    url: "@Url.Action("Create","Programmer")",
                    data: { model: ProgrammerViewModel }, //the name ("model") should be the same with the parameter's name in the controller.
                    type: "Post", //change the method to Post.
                    success: function (result) {
                        $("#itemlist").html("");
                        $("#itemlist").html(result);
                    },
                    error: function (result) {
                        window.alert("This is an unhandled exception. ");
                    }
                });
            });
        });
    </script>
    }

Code explanation.
In the index view, at the top is placed a form which is used to create new programmer. When user clicks the submit button, the jQuery AJAX function is run. The Date function is used just for debugging purpose. The ajax function calls the Create action. It sends the data as ProgrammerViewModel which is received by the Create action. The data name must match the Create parameter i.e. ProgrammerViewModel. Note that Create action returns a PartialView with model data. The model data in Index view is of IList type. The list is updated in the Index view after each create action call. In the Index view, at the bottom, partial view is placed which will render the list of all programmers. To list the existing programmers, Index action is called when the application is run.

Run the application by pressing F5 or CTRL+ F5. We get the following output.

Friday, July 16, 2021

ASP.NET MVC .NET Framework - Creating Application from scratch

To create MVC Application from the scratch, we follow the following steps.

Step1. Select the ASP.NET Web Application (.NET Framework) and click Next button.


Step2. Give a meaningful name of your project. For example, MvcWebApp.


Step3. Select Empty project template. Don't check mark any options from the "Add folders and core references" and uncheck the "configure for HTTPS". and click "Create"
Step4. The default folders and files appear in the Solution Explorer. If you click the CTRL+F5 or F5, we get the following error. 


The error occurs because many important references such as  System.Web.Mvc are missing in this application. We will add them one by one as we go ahead.

Explore the files generated
Before that we look at the default files and folders added in the Solution Explorer. We find packages.config and web.config file apart from Properties and References. Expand the References node to see the default added references.


Collapse the node and click the packages.config file and look at its code. It is an XML file. We find the following code.
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net472" />
</packages>

Similary, click the web.config file and see its code. It is also an XML file.

<?xml version="1.0" encoding="utf-8"?>

<!--

  For more information on how to configure your ASP.NET application, please visit

  https://go.microsoft.com/fwlink/?LinkId=169433

  -->

<configuration>

  <system.web>

    <compilation debug="true" targetFramework="4.7.2" />

    <httpRuntime targetFramework="4.7.2" />

  </system.web>

  <system.codedom>

    <compilers>

      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />

      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />

    </compilers>

  </system.codedom>

</configuration>

Click the Properties and then click the AssemblyInfo.cs file. We get the following code.

using System.Reflection;

using System.Runtime.CompilerServices;

using System.Runtime.InteropServices;

 

// General Information about an assembly is controlled through the following

// set of attributes. Change these attribute values to modify the information

// associated with an assembly.

[assembly: AssemblyTitle("MvcWebApp")]

[assembly: AssemblyDescription("")]

[assembly: AssemblyConfiguration("")]

[assembly: AssemblyCompany("")]

[assembly: AssemblyProduct("MvcWebApp")]

[assembly: AssemblyCopyright("Copyright ©  2021")]

[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]

 

// Setting ComVisible to false makes the types in this assembly not visible

// to COM components.  If you need to access a type in this assembly from

// COM, set the ComVisible attribute to true on that type.

[assembly: ComVisible(false)]

 

// The following GUID is for the ID of the typelib if this project is exposed to COM

[assembly: Guid("2e2e0dd4-d4d3-47d6-b9de-8b994bce20f8")]

 

// Version information for an assembly consists of the following four values:

//

//      Major Version

//      Minor Version

//      Build Number

//      Revision

//

// You can specify all the values or you can default the Revision and Build Numbers

// by using the '*' as shown below:

[assembly: AssemblyVersion("1.0.0.0")]

[assembly: AssemblyFileVersion("1.0.0.0")]

 ADDING THE REFERENCE OF System.Web.Mvc.

Step5. We add the reference of System.Web.Mvc. It is required to develop MVC application. Right click the References node and click Add References. 
Then click the Assemblies node the LHS. Expand it and select Framework.  Press CTRL +E to reach the search box and type Mvc and then we find the System.Web.Mvc. Select it and click OK. We find the System.Web.Mvc added in the References. Next we need the RouteConfig class and Global.asax files to set the routing in the MVC application. Without them, application will not work. Both files are interrelated.

Step6. Now we add "App_Start" folder in the project.
Step7. We add the RouteConfig class file inside the App_Start folder.

Step8. We add the following code in the RouteConfig class. We add RegisterRoutes method in this class. The code is as follows.

using System.Web.Mvc;
using System.Web.Routing;

namespace MvcWebApp.App_Start
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute
                (
                name: "default",
                url: "{controller}/{action}/{id}",
                defaults: new
                {
                    controller = "Home",
                    action = "Index",
                    id = UrlParameter.Optional
                }
                );
        }
    }
}

NOTES
  • The MapRoute has three named parameters: name, url and defaults.
  • The RouteCollection belongs to System.Web.Routing namespace.
  • The IgnoreRoute and MapRoute methods belongs to System.Web.Mvc.
Step9. We add Global.asax file. Press CTRL+SHIFT+A and then CTRL+E to reach inside the search box. Type global and press ENTER. We get the Global Application class file. Select it and click Add button.

Step10. Now we get the Global.asax file in the Solution Explorer and it contains Global.asax.cs file. The default code in the Global.asax.cs file is as follows.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.SessionState;

 

namespace MvcWebApp

{

    public class Global : System.Web.HttpApplication

    {

        protected void Application_Start(object sender, EventArgs e){}

        protected void Session_Start(object sender, EventArgs e){}

        protected void Application_BeginRequest(object sender, EventArgs e){}

        protected void Application_AuthenticateRequest(object sender, EventArgs e){}

        protected void Application_Error(object sender, EventArgs e){}

        protected void Session_End(object sender, EventArgs e){}

        protected void Application_End(object sender, EventArgs e){}

       

    }

}

CTRL+M,O and collapse all codes in the Global.asax.


We need to modify the Global.asax and Global.asax.cs files. We modifiy the Global.asax.cs file code. Now it looks as follows. 

using MvcWebApp.App_Start;

using System.Web.Mvc;

using System.Web.Routing;

namespace MvcWebApp

{

    public class MvcApplication : System.Web.HttpApplication

    {

        protected void Application_Start()

        {

            AreaRegistration.RegisterAllAreas();

            RouteConfig.RegisterRoutes(RouteTable.Routes);

        }

    }

}

EDITING THE GLOBAL FILES

NOTE: We renamed the class Global to MvcApplication in the above code. This class name is referenced in the Global.asax file as well. We have to edit it there as well.
Select the project in the Solution Explorer and right click and the select "Open Folder in File Explorer". We reach inside the project folder. We find the Global.asax and Global.asax.cs files there. Right click Global.asax and open it in Notepad or Notepad++. Next, we have to edit it.

We change inherits = "MvcWebApp.Global" to inherits = "MvcWebApp.MvcApplication". Save the file and close it.

Step11. Rebuild the Application using CTRL+SHIFT+B.
ADDING CONTROLLER AND VIEW FILES WITHOUT SCAFOLDING
Step12. We have added the logic of routing in the RouteConfig and Global.asax and Global.asax.cs files. Now we will add the Controllers folder and Views folder in the project. 
We add a HomeController.cs class file in the Controller folder. It is a normal simple class, not controller class. 

The default code is as follows:
namespace MvcWebApp.Controllers
{
    public class HomeController
    {
    }
}

We need to inherit the Controller class in HomeController class so that HomeController inherits all properties and methods of Controller class. Then, the HomeController class becomes a controller class.
The modified code is as follows after inheriting the Controller class
using System.Web.Mvc;

namespace MvcWebApp.Controllers
{
    public class HomeController : Controller
    {
    }
}

REMARK: Controller class is a special class in MVC Framework which must be inherited by any controller class to become a controller. 

All the methods in the user's controller class will be public and non-static and will return ActionResult object. 

The ActionResult class is an abstract class which derived classes such as ViewResult, ContentResult, PartialViewResult, FileResult, JsonResult, JavaScriptResult etc. can be used as an action method return type.

We add an Index method in the HomeController class.
The modified code is as follows
using System.Web.Mvc;

namespace MvcWebApp.Controllers
{
    public class HomeController:Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}
MVC Convention
As the above method returns a view. The View() method returns a view which name will be the name of the action method. It means that the Index named view will be returned by the Index action method of Home controller. 

We create Home folder inside the Views folder which is the repository of all views and the Views folder contains subfolders which are named for each controller class used in the Controller folders. And, we add the Index.cshtml file inside the Views/Home folder. Select the Home folder and press CTRL+SHIFT+A. Then, CTRL+E and type razor in the search box. Select the MVC 5 View Page (Razor)

Rename the file as Index.cshtml and click Add button. The Index.cshtml file is added inside the Home folder. 
Add the following HTML tags in the view page.
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
        Index Test Page
    </div>
</body>
</html>

Rebuild the project by pressing CTRL+SHIFT+B and run the project by pressing CTRL+F5 or F5.

We get the following error.

Exception Details: System.InvalidOperationException: The view at '~/Views/Home/Index.cshtml' must derive from WebViewPage, or WebViewPage<TModel>.

[InvalidOperationException: The view at '~/Views/Home/Index.cshtml' must derive from WebViewPage, or WebViewPage<TModel>.]


Reason of this error?
A razor page i.e. .cshtml file is not simple html file. It contains the C# codes apart from HTML code. The C# codes must be converted into HTML code to render the view as HTML page. So, every view page must inherits the System.Web.Mvc.WebViewPage class which provides the methods and properties to render the page as HTML. We can get some idea by the following Intellisense hints.


So, What is the solution? We must add the following directive in the Index view page at the top of the code.
@inherits System.Web.Mvc.WebViewPage
This will enable the view page to inherit all the methods and properties System.Web.Mvc.WebViewPage class to render the page as HTML.

The Index.cshtml page code becomes as shown below.
@inherits System.Web.Mvc.WebViewPage
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
        Index Test Page
    </div>
</body>
</html>


Again, rebuild the project by pressing CTRL+SHIFT+B and run the project by pressing CTRL+F5 or F5. Now, We get the expected view page.

But the problem is, we will have to add the directive @inherits System.Web.Mvc.WebViewPage
in all the view pages. 

To solve this problem, we can use the web.config file. We add the <configSections> and  <system.web.webPages.razor> tags inside the <configuration> tag.

<configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>
The updated web.config file is as follows.
<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>

  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
  </system.web>
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Again, rebuild the project by pressing CTRL+SHIFT+B and run the project by pressing CTRL+F5 or F5. Now, We get the expected view page.

NOTE: The  <configSections> must be the first child tag of  <configuration> tag.

Hot Topics