Configuring Application in ASP.NET Core MVC

Configuring Application in ASP.NET Core MVC

This tutorial on ASP.NET Core MVC Configurations will reveal you a lot about the inside of this framework. This will give you a solid foundation for understanding the coming topics later on. I will start by creating a new project using empty template.

Create Project using Empty Template

When you create a project using Empty Template you have to do the configurations by yourself. This includes:

  • 1. Adding Folders for Controllers, Views & Models.
  • 2. Adding Configuration files like appsettings.json, bower.json, etc.
  • 3. Adding the layout View.

And many more things which you will see in this tutorial.

Start with opening your Visual Studio and then select Create a new project from the file menu. You will see the option – ASP.NET Core Web Application, so select it.

ASP.NET Core Web Application
Specify the location on your drive where you want the application to be created. Give the name of your application as Configuation.
configure project

Then click the ‘Create’ Button.

Now you will get another dialog box. Here you select Empty template, and also select the Framework, Version, Template and Authentication.

Make the follow settings (as shown by the below image):

asp.net core empty template
  • 1) .NET Core
  • 2) ASP.NET Core 3.1
  • 3) Empty (for template)
  • 4) No Authentication

This will create your ASP.NET Core MVC with Empty Template.

I started ASP.NET tutorials from the very beginning. This is covered in 2 tutorials:

What is .csproj

The name of the .csproj file which in your application will be configuration.csproj.

This file is hidden by Visual Studio and must be accessed by right clicking your project and select Edit Configuration.csproj.

csproj file

The initial context of the Configuration.csproj file is shown below:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

</Project>

The csproj contains many settings which are used to build .NET Projects. You can add any package that your application needs to this file. When you any package to the csproj file then Visual Studio downloads that package. Similarly when you remove any package from csproj file then Visual Studio removes that package from your application.

The elements in csproj files
Element Description
Project It is the root element, the Sdk attribute specifies that the application should be build with Microsoft.NET.Sdk.Web package.
PropertyGroup Used to group related properties.
TargetFramework Instructs .NET Core to use the specified version when building a project.
ItemGroup Used to group related items.
Folder It tells .NET Core to include the folder (here wwwroot) when publishing the project.
PackageReference It specifies dependency on the NuGet package. The Microsoft.AspNetCore.All is a package providing access to all individual packages which provides ASP.NET Core and MVC functionalities.

Json.NET is a popular high-performance JSON package for .NET. It is used to serialize and deserialize JSON. To add Json.NET packages add the below ItemGroup inside the ‘Project node’ of the csproj file:

<Project Sdk="Microsoft.NET.Sdk.Web">

	<PropertyGroup>
		<TargetFramework>netcoreapp3.1</TargetFramework>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
	</ItemGroup>

</Project>


As soon as you save the csproj file, VS will download the Json.NET package and add it to your project.

Typing package names and there versions on the csproj file can be error prone. You can avoid this typing completely by adding packages through NuGet Package Manager.

Adding Packages through NuGet

NuGet Package Manager allows for the management of NuGet packages through an easy-to-use interface. Select Tools ➤ NuGet Package Manager ➤ Manage NuGet

Packages for Solution in your Visual Studio. This will opens NuGet Solution dialog box, there click the Browse tab and enter the name of package in the text box. When you see you searched package on the list, select it and then click the ‘Install’ button.

In the below image I have searched for Json.NET, and then selecting and installing it.

adding json net package nuget

There is a shorter way too if you know the name of the package you require (and, ideally, the version). This is this way through Package Manger Console.

To open it follow the below procedure:

Select Tools ➤ NuGet Package Manager ➤ Packages Manager Console in your Visual Studio then enter the below given line (and press enter key) to install the Json.NET package.

PM> Install-Package Newtonsoft.Json

This command is given on Nuget for every package. Check this link to find the command for Json.NET package.

The Program Class

On the root folder of your application you will find the Program.cs which is called the Program Class. It has a Main() function that provides the entry point for running the application.

The default code of the Program Class is shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Configuration
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

The Main method in the Program class calls a CreateHostBuilder() function, which configures the ASP.NET Core like setting up the hosting environment.

Inside the CreateHostBuilder() function, you will find it calling the CreateDefaultBuilder() function which configures the application with the Most Suitable Settings. By Most Suitable Settings I mean the settings which are suitable for most of the ASP.NET Core applications.

The UseStartup() function calls the Startup.cs class which is also kept on the application root folder. The Startup.cs class provides application specific configuration. In the next section you will learn more about Startup Class.

The Build() function builds the application and if no errors are found then will run your application on the browser.

Inside the CreateHostBuilder() function you can provide individual configuration settings. In the below code I have provided 2 individual settings – UseContentRoot & UseIISIntegration.

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
          webBuilder.UseContentRoot(Directory.GetCurrentDirectory())
          .UseIISIntegration()
          .UseStartup<Startup>();
      });

Some important settings are:

Name Description
UseContentRoot() Specifies the content root directory for the application.
UseIISIntegration Enables integration with IIS and IIS Express.
UseKestrel() Configures the Kestrel web server.
Learn to do database programming in ASP.NET core through ADO.NET, check this tutorial – Learn ADO.NET by building CRUD features in ASP.NET Core Application
What is KESTREL Web Server ?

Kestrel is an open-source, cross-platform web server for hosting ASP.NET applications on any platform. It is used automatically when running ASP.NET Core application with IIS.

You can use Kestrel by itself or with a reverse proxy server, such as IIS, Nginx, or Apache. A reverse proxy server receives HTTP requests from the Internet and forwards them to Kestrel after some preliminary handling.

In order to use Kestrel by itself, for running ASP.NET Core MVC application on any of the supported platforms, you click the arrow on the right of IIS Express button in your VS then select the option that says the name of your application. In this application it will be Configuration.

select Kestrel in visual studio

Once selected the name of your application you have to run your application (shortcut F5 key). Now your application will now run on Kestrel only.

The Startup Class

You will find the Startup.cs file on your application’s root folder. This file is the Startup class. The Program Class calls the Startup Class using UseStartup() function. In the startup class you can provide a lot of application specific configuration which you will see in the coming sections.

If you open the Startup class you will see it like shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Configuration
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}

The Startup Class contains 2 methods – ConfigureServices() and Configure().

In the ConfigureServices() method you can create one or more services that can be used throughout your application. A service can be anything that do a task and is available throughout the application. In the below section I will create a simple service to help you understand them in a better way.

In the Configure() method you can configure HTTP Request pipeline which is also know by the name middleware. I will also create some middlewares later on.

In the current code, when you run the application it will just sent the response text – Hello World! on the browser for all requests.

startup class

Understanding Services in ASP.NET Core

An ASP.NET Core Service can be anything in which does a particular task and is available all through the application. Examples are like:

  • 1. A Service for sending a text verification code to user’s email address.
  • 2. A Service for validating mobile number through OTP.
  • 3. A Service that helps in recovering the user’s account password when lost.

I will create a small ASP.NET Core Service that provides the application with the total number of registered users.

Start by creating a folder in your application’s root folder and name it Services or anything you like. Inside this Services folder create a class and name it TotalUsers.cs and add the following code to it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace Configuation.Services
{
    public class TotalUsers
    {
        public long TUsers()
        {
            Random rnd = new Random();
            return rnd.Next(100, int.MaxValue);
        }
    }
}

This class has one public method – Tusers() which returns the total number of users registered in the application. This method returns a random number between 100 and max value of Int. In a real application you are going to fetch this value from the database

The next step involves registering this class in the Startup.cs class so that ASP.NET Core can make this service available throughout the application.

So go the Startup.cs class and import the namespace – using Configuation.Services;.

Next add the following codes inside the ConfigureServices() method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<TotalUsers>();
    services.AddControllersWithViews();
}

The services.AddSingleton() will add the service which can now be shared all thought the application. The services.AddControllersWithViews() will add adds support for controllers, API-related features, and views in the application.

MVC actually needs a large number of services and the AddControllersWithViews() method sets up every necessary service in one go.

Next, inside the Configure() method you will find app.UseEndpoints() method (shown below).

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/", async context =>
    {
        await context.Response.WriteAsync("Hello World!");
    });
});

Replace it to:

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});
The MapDefaultControllerRoute() adds endpoints for controller actions and adds the default route which is {controller=Home}/{action=Index}/{id?}. This is the concept of ASP.NET Core Endpoint Routing.

So the Startup class will now look like:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<TotalUsers>();
        services.AddControllersWithViews();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
}

The service is now created and available through in the application. Let us understand how to use this service in a controller.

So create Controllers folder in the root of your application and right click on this newly created folder and select New ➤ Controller.

You get a new window which asks to select the controller type. So select MVC Controller – Empty.

Name this controller as HomeController and import the namespace – using Configuation.Services;.

Finally add the following code to it:

public class HomeController : Controller
{
    private TotalUsers totalUsers;
    public HomeController(TotalUsers tu)
    {
        totalUsers = tu;
    }
 
    public string Index()
    {
        return "Total Users are: " + totalUsers.TUsers();
    }
}

The controller has a constructor which has our service class called TotalUsers in its parameter. When ASP.NET calls this controller it sees the constructor requires an object i.e. has a dependency for the service class called TotalUsers.

MVC then goes to the Startup class and finds the TotalUsers class been configured as a service. So it will now create an instance of the TotalUsers class (by its own) and pass it to the construction of the Home Controller.

This is the concept of Dependency Injection feature which I have explained very deeply in the article called Dependency Injection in ASP.NET Core from a-z

Now see the Index action method of the controller, which uses the TotalUsers instance provided by MVC, and calls the TUsers() method to get the total number of registered users. It finally returns them as string to the View.

Next, create a new folder called Views on the root of the application. Inside this folder create another folder and name it Home.

Now create Index View inside the Views ➤ Home folder, and add the following code to it.

@model string
@Model

To test the service run your application and see the total number of users displayed on the browser.

simple service in asp net core

Understanding Middleware in ASP.NET Core MVC

Middleware in ASP.NET Core are components that sits on the HTTP Request Pipeline and thus are used to configure them. There can be one or more Middlewares sitting on the HTTP pipeline in a line.

When a new HTTP request arrives, it is send to the first Middleware which inspects it. This Middleware will then do 1 of the 2 things:

  • 1. Generate a response and send it back to the client (request initiator).
  • 2. Pass the HTTP Request to the next Middleware.

On handling the complete request, the response will be returned to the client along the same order, which allows all of the earlier Middleware to inspect or modify it.

There are 4 types of Middleware:

  • 1. Content-Generating Middleware.
  • 2. Short-Circuiting Middleware.
  • 3. Request-Editing Middleware.
  • 4. Response-Editing Middleware.

Content-Generating Middleware

Let us create a small Middleware that will only generate some content and hence named as Content-Generating Middleware.

Create a new folder inside the application’s root folder and name it (name can be any thing). Add a class to this new folder and name it ContentMiddleware.cs. Add the following codes to it:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
 
namespace Configuation.Middlewares
{
    public class ContentMiddleware
    {
        private RequestDelegate nextDelegate;
        public ContentMiddleware(RequestDelegate next) => nextDelegate = next;
 
        public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext.Request.Path.ToString() == "/middleware")
            {
                await httpContext.Response.WriteAsync("This is from the content middleware");
            }
            else
            {
                await nextDelegate.Invoke(httpContext);
            }
        }
    }
}

Please note that the Middleware class doesn’t implement an interface or derive from a common base class. They have a constructor that takes a parameter of type RequestDelegate which is provided to it automatically by MVC. The RequestDelegate object represents the next middleware component in the line.

The Middleware also define an Invoke method. This method is called when .NET receives an HTTP request. The Invoke method has a parameter of type HttpContext which contains Information about the HTTP request and the response that will be returned to the client.

In my ContentMiddleware.cs class the Invoke method inspects the HTTP request and checks to see whether the request has been sent to the url /middleware. If it has, then it sends a simple text response – This is from the content middleware. If a different URL has been initiated, then the request is forwarded to the next Middleware in the line.

You have to register the Middleware inside the Configure method of the Startup class using the UseMiddleware() method like shown below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    app.UseMiddleware<ContentMiddleware>();
}

Now run the application and then go to the URL – https://localhost:44343/middleware. You will see the response from the Middleware as shown by the image below:

content middleware

If the URL is not – https://localhost:44343/middleware then the Content Middleware will pass the request to the next Middleware. Note that here there is no Middleware left therefore the request is returned back.

content generating middleware
Using Services in Middleware

Middleware can also receive Services just like Controllers. In the previous section I created a service called TotalUsers, you can use this service in your Middleware by providing it’s dependency in the class constructor. See the below updated code:

using System.Threading.Tasks;
using Configuation.Services;
using Microsoft.AspNetCore.Http;
 
namespace Configuation.Middlewares
{
    public class ContentMiddleware
    {
        private RequestDelegate nextDelegate;
        private TotalUsers totalUsers;
 
        public ContentMiddleware(RequestDelegate next, TotalUsers tu)
        {
            nextDelegate = next;
            totalUsers = tu;
        }
 
        public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext.Request.Path.ToString() == "/middleware")
            {
                await httpContext.Response.WriteAsync("This is from the content middleware, Total Users: " + totalUsers.TUsers());
            }
            else
            {
                await nextDelegate.Invoke(httpContext);
            }
        }
    }
}

Run you application and go to the URL – https://localhost:44343/middleware.

content middleware with service

Short-Circuiting Middleware

Short-Circuiting Middleware don’t always forward request to the next Middleware in the line. That’s why they are called Short-Circuiting Middleware.

Let’s create this type of Middleware. Inside the Middlewares folder create a new class and name it ShortCircuitMiddleware, and add the below code to it:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace Configuation.Middlewares
{
    public class ShortCircuitMiddleware
    {
        private RequestDelegate nextDelegate;
        public ShortCircuitMiddleware(RequestDelegate next) => nextDelegate = next;
 
        public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext.Request.Headers["User-Agent"].Any(v => v.Contains("Firefox")))            {
                httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
            }
            else
            {
                await nextDelegate.Invoke(httpContext);
            }
        }
    }
}

Now go to the Configure method of the Startup class and register this middleware above the previous ‘ContentMiddleware’ Middleware, as shown below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // after UseRouting
    app.UseMiddleware<ShortCircuitMiddleware>();
    app.UseMiddleware<ContentMiddleware>(); 
}

The Middleware executes in the order in which they are registered in the Configure method. I want ShortCircuitMiddleware to execute before ContentMiddleware so I have placed it at first.

The ShortCircuitMiddleware Middleware will not forward the request received from Firefox browser and returns unauthorized status. For other browsers it forwards the request to the ContentMiddleware.

short circuiting middleware

If you now run your application and open the URL – https://localhost:44343/middleware in Firefox browser. You will receive a blank page. For other browsers you will get the same response which you get previously.

The blank page you get in Firefox browser is shown below:

blank page in firefox
Views provide the UI in ASP.NET Core. You can cover views in the article – Views in ASP.NET Core

Request-Editing Middleware

So far we have seen 2 types of Middleware that generates response. Now we will see Middleware that do not generate response instead edit requests. This type of Middleware is known as Request-Editing Middleware.

Create a class inside the Middlewares folder and name it RequestEditingMiddleware.cs. Add the given code to it:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
 
namespace Configuation.Middlewares
{
    public class RequestEditingMiddleware
    {
        private RequestDelegate nextDelegate;
        public RequestEditingMiddleware(RequestDelegate next) => nextDelegate = next;
 
        public async Task Invoke(HttpContext httpContext)
        {
            httpContext.Items["Firefox"] = httpContext.Request.Headers["User-Agent"].Any(v => v.Contains("Firefox"));
            await nextDelegate.Invoke(httpContext);
        }
    }
}

The RequestEditingMiddleware.cs Class only edits the HTTP Request (and does not sends any response). It checks if the request is made from Firefox browser in that case adds a key called Firefox with Boolean value ‘true’ to the HttpContext dictionary. The below given code does this work:

httpContext.Items["Firefox"] = httpContext.Request.Headers["User-Agent"].Any(v => v.Contains("Firefox"));

Now edit the ShortCircuitMiddleware.cs class which you made earlier. Delete or comment out the line which checks the User-Agent.

//if (httpContext.Request.Headers["User-Agent"].Any(v => v.Contains("Firefox")))

In place of it check the item named ‘Firefox’ in the HttpContext. See the below code:

if (httpContext.Items["Firefox"] as bool? == true)

The updated code of ShortCircuitMiddleware.cs Class is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace Configuration.Middlewares
{
    public class ShortCircuitMiddleware
    {
        private RequestDelegate nextDelegate;
        public ShortCircuitMiddleware(RequestDelegate next) => nextDelegate = next;

        public async Task Invoke(HttpContext httpContext)
        {
            //if (httpContext.Request.Headers["User-Agent"].Any(v => v.Contains("Firefox")))
            if (httpContext.Items["Firefox"] as bool? == true)
            {
                httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
            }
            else
            {
                await nextDelegate.Invoke(httpContext);
            }
        }
    }
}

This change is done because the Request-Editing Middleware is checking the User-Agent for firefox and adding it to the HttpContext’s items dictionary. So the value is being provided to the Short-Circuiting Middleware.

Finally Register the Request Editing Middleware on the Configure() method of Statup class:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseMiddleware<RequestEditingMiddleware>();
    app.UseMiddleware<ShortCircuitMiddleware>();
    app.UseMiddleware<ContentMiddleware>();
    app.UseMvcWithDefaultRoute();
}

I placed the Request-Editing Middleware at the start of the HTTP pipeline. This ensures that the request has already been modified before it is forwarded to other Middleware.

request editing middleware

Run the application and upon the URL – https://localhost:44343/middleware in firefox. You will get a blank page due to unauthorized HTTP request condition.

Response-Editing Middleware

As the name suggest the Response-Editing Middleware edits only the response generated by other Middleware.

Right now we are getting a blank page on the Firefox browser. Blank page is no good for real applications, we should also show some message. So with the use of Response-Editing Middleware I will provide text response which users will see only on the firefox browser.

Add a new Class inside the Middlewares folder and name it ResponseEditingMiddleware.cs. Add the below code to it:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace Configuation.Middlewares
{
    public class ResponseEditingMiddleware
    {
        private RequestDelegate nextDelegate;
        public ResponseEditingMiddleware(RequestDelegate next)
        {
            nextDelegate = next;
        }
 
        public async Task Invoke(HttpContext httpContext)
        {
            await nextDelegate.Invoke(httpContext);
            if (httpContext.Response.StatusCode == 401)
            {
                await httpContext.Response.WriteAsync("Firefox browser not authorized");
            }
            else if (httpContext.Response.StatusCode == 404)
            {
                await httpContext.Response.WriteAsync("No Response Generated");
            }
        }
    }
}

In the above code if the HTTP status code in the response is 401 then I am adding text – Firefox browser not authorized to the response. Recall that the 401 un-authorized response is generated by Short-Circuiting Middleware.

Since the Response-Editing Middleware only edits the response of other Middleware it has to be placed before other Middleware in the HTTP pipeline. So register it below other Middleware in the Configure() method of Startup class:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseMiddleware<ResponseEditingMiddleware>();
    app.UseMiddleware<RequestEditingMiddleware>();
    app.UseMiddleware<ShortCircuitMiddleware>();
    app.UseMiddleware<ContentMiddleware>();
    app.UseMvcWithDefaultRoute();
}
response editing middleware

Now run your application and go to URL – https://localhost:44343/middleware in the Firefox browser. You will get the response text – Firefox browser not authorized. This is shown in the image below.

http response text in firefox-browser
When 404 Status Code is Received

In the Response-Editing Middleware there is an else if block:

else if (httpContext.Response.StatusCode == 404)
{
    await httpContext.Response.WriteAsync("No Response Generated");
}

This will execute when status code is 404. This status code is automatically generated when there is no resource found in the application for a url.

Open any random url which is not served by the application like – https://localhost:44343/tutorials. You will see No Response Generated message on your browser.

no response generated

Understanding Application Builder

The Startup Class Configure() method has a parameter of type IApplicationBuilder Interface. This Interface allows the Middleware pipeline to be created.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //.....
}

An important use of IApplicationBuilder Interface is to configure the ASP.NET Core Routes.

If you open Startup file of your application and check the Configure method. There is a method called – app.UseRouting() which adds an Endpoint Routing middleware to the IApplicationBuilder.

Then you can use the Endpoint Routing like what we used in this application:

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});

Worth mentioning are 2 important methods for doing routes configuration.

  • 1. UseMvcWithDefaultRoute
  • 2. UseMvc
UseMvcWithDefaultRoute

The UseMvcWithDefaultRoute is used to set up the default routes in the application. Use it inside the Configure method as shown below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseMvcWithDefaultRoute();
}
UseMvc

The UseMvc is used to configure custom routes in the application. Eg.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseMvc(routes => {
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
    });
}

The above code only shows one custom route. An application can have hundreds of routes set up.

The method UseMvcWithDefaultRoute is just a shortcut. When you use – app.UseMvcWithDefaultRoute(); you are actually just setting up the following route:

app.UseMvc(routes => {
routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id?}");
});
Don’t worry if you do not understood all these as I have covered ASP.NET Core Routing in full details – from top to bottom.

Understanding Hosting Environment

The Startup Class Configure() method has another parameter of type IWebHostEnvironment Interface. It provides information about the hosting environment.

Let’s see some important properties of IWebHostEnvironment Interface.

Name Description
ApplicationName Returns the name of the application.
EnvironmentName Returns the name of the environment.
ContentRootPath Returns the path that contains the application’s content & configuration files.
WebRootPath Returns the path that contains the application’s static content. This is usually ‘wwwroot’ folder.
Using the Environment Name Property

In ASP.NET Core there are 3 environments – Development, Staging & Production. Environments help in setting different configurations in the application.

To set up your environment in the application, go to the Solution Explorer and right click on your application name and select Properties.

In the properties page select the Debug option. There you will see the current hosting environment is set using an environment variable called ASPNETCORE_ENVIRONMENT. You can change its value to either Development, Staging & Production. When you are done save by pressing CTRL+S. Check the below image where I have illustrated this thing.

setting environment

Within the Configure method, you can determine which hosting environment is being used in the following manner:

  • IsDevelopment() – returns true if environment is Development.
  • IsStaging() – returns true if environment is Staging.
  • IsProduction() – returns true if environment is Production.

In the below code I made sure the Middleware are registered only if the environment is Production.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsProduction())
    {
        app.UseMiddleware<ResponseEditingMiddleware>();
        app.UseMiddleware<RequestEditingMiddleware>();
        app.UseMiddleware<ShortCircuitMiddleware>();
        app.UseMiddleware<ContentMiddleware>();
        app.UseMvcWithDefaultRoute();
    }
}
Using the WebRootPath Property to get the Absolute Path

The WebRootPath property gives the application’s static content folder which is the wwwroot. You can use this property inside a Controller to get the absolute path of the files that are kept in this folder.

To do this, pass the IWebHostEnvironment as the parameter to the constructor of the Controller. The Dependency Injection feature of ASP.NET Core will automatically provide the IWebHostEnvironment value to the constructor. Then you can simply use the WebRootPath property to get the absolute path.

public class MediaController : Controller
{
    private IWebHostEnvironment hostingEnvironment;
 
    public MediaController(IWebHostEnvironment environment)
    {
        hostingEnvironment = environment;
    }
 
    public ActionResult Index()
    {
        string absolutePath = Path.Combine(hostingEnvironment.WebRootPath, "file1.jpg"); 
        return View();
    }   
}

Enable Exception Handling

Exceptional Handling is not enabled in your application. You can check it by running your application and then go to some non-existing URL like https://localhost:44343/Game. You will see a message on the browser saying – No Response Generated.

no response generated for non existing url

This is an Exception but the message does not state anything regarding it’s cause. User must see some proper messages like 404 for non-existing page, 401 for un-authorized, 403 for forbidden. To do this you have to enable Exception Handling.

To enable Exception Handling in your application you need to put the below 2 lines of code inside the Configure() method of the Startup class:

app.UseDeveloperExceptionPage();
app.UseStatusCodePages();
  • UseDeveloperExceptionPage – displays the details of the Exception in the response.
  • UseStatusCodePages – adds descriptive messages to response like 404 – Not Found

Before you check how it works, make sure you comment out the line where the Response Editing Middleware is added in the startup class

//app.UseMiddleware<ResponseEditingMiddleware>();

Now re-run your application and re-visit the URL – https://localhost:44343/Game. You will see the full exception details:

exception message on response

The above Exception was caused by the non-existing action method i.e. a resource which is not found. In fact Exceptions can be cause by a number of ways, mainly due to wrong codes. I will show what happens when exception occurs inside an action method code.

Go to the Home Controller and add 2 action methods. The first is called Exception and it throws a NullReferenceException type of exception. The other is called Error and it is automatically called when some exception happens in the code.

These 2 action methods are given below:

public ViewResult Exception()
{
    throw new System.NullReferenceException();
}
 
public ViewResult Error()
{
   return View();
}

Create a view called Error inside the Views ➤ Home folder and add the following code to it:

<h2>Some Problem</h2>
We got some problem, please visit back after sometime.

Now re-run your application and visit the URL – https://localhost:44343/Home/Exception. You will see full Exception message with Stack Trace to explore the cause of the exception.

exception with stack trace

This full Exception message with Stack Trace is very helpful to developers but it should not be shown the common users of the site.

For this you use the method – IsDevelopment() to show full exception when website is running in the Development mode (localhost).

When the website is running in production you show a common error view for exceptions.

Update your Configure method code with that shown below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseStatusCodePages();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }
    //...
}

The app.UseExceptionHandler(“/Home/Error”) method shows the Error View if the website is not running in the development mode.

Set the environment variable – ASPNETCORE_ENVIRONMENT to ‘Production’ and run the application and visit the ‘/Home/Exception’ page. This time you will see the Error View as shown in the image below.

error view shown in exception

Enable Static Content

In order to make the application use images, JavaScript files, CSS stylesheets which are kept inside the wwwroot folder you have to add – app.UseStaticFiles() inside the configure method of the Startup class.

I called the UseStaticFiles code for all environments since it is needed every time. Put it just before the app.UseRouting() method.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseStaticFiles();
    app.UseRouting();
    //...
}

Understanding appsettings.json File

ASP.NET Core MVC has a JSON file by the name appsettings.json. In this file you can store any data like DB Connection String, logging settings, global variable etc.

To create this file, right click the your project name in the Solution Explorer and select Add ➤ New Item. You will get a dialog box up where you can search for the text ‘appsettings.json’, and this file will show up.

The below figure shows how to select the appsettings.json from the ‘Add New Item’ dialog box.

adding appsettings.json

In the appsettings.json file I want to store which middleware to enable in the application. So add the following code to this file:

{
  "Middleware": {
    "EnableContentMiddleware": true,
    "EnableShortCircuitMiddleware": true,
    "EnableRequestEditingMiddleware": true,
    "EnableResponseEditingMiddleware": false
  }
}

This JSON file contains 4 variables – EnableContentMiddleware, EnableShortCircuitMiddleware, EnableRequestEditingMiddleware & EnableResponseEditingMiddleware. I have given each of them a bool value, and I will read their values in Startup class. Then based on the value I will register the Middleware i.e. if the value of the variable is true only then I will register the Middleware.

You can see the last variable – EnableResponseEditingMiddleware is provided value as false and others variables are provided value as true. So all the Middleware except the Response Editing Middleware will be registered.

Now finally on your Startup class add the namespace – using Microsoft.Extensions.Configuration

Then add a property of type IConfiguration and add the constructor that takes the parameter of type IConfiguration. The parameter’s value will be provided automatically by ASP.NET Core from the Dependency Injection feature.

See the below code:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
public IConfiguration Configuration { get; } 

Finally change the code inside the Configure method as shown below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableResponseEditingMiddleware")).Value)
    {
        app.UseMiddleware<ResponseEditingMiddleware>();
    }
    if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableRequestEditingMiddleware")).Value)
    {
        app.UseMiddleware<RequestEditingMiddleware>();
    }
    if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableShortCircuitMiddleware")).Value)
    {
        app.UseMiddleware<ShortCircuitMiddleware>();
    }
    if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableContentMiddleware")).Value)
    {
        app.UseMiddleware<ContentMiddleware>();
    }
}

In the above code I am reading the bool values of these 4 variables which are kept inside the ‘Middleware’ node. If the value is true then the corresponding Middleware is registered.

When you run the application, all except the Response Editing Middleware will be registered.

Selecting Different appsettings.json files based on different Environment

As stated earlier the appsettings.json stores the connection string for the database. During the course of application development the programmers will want to have not 1 but 2 appsetting.json files in their application.

One that will be used during development and which will contains the connection string (or other variables) to local database.

The other one will be used during production (i.e. when you publish the website and put it on hosting server), and this one will contain the connection string to the production database i.e. the live database.

I will show you how to do this.

First add your connection string to your live database on your appsettings.json file like shown below:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=SQL6003.site4now.net;Database=DB_A3CE39_y11;User Id=DB_PCE39_y11_admin;[email protected];"
  }
}

Now add a new appsetting.json file on your application root folder and give it the name – appsettings.development.json. Then add your local development database connection string as shown below.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=vaio;Database=Goldentaurus;Trusted_Connection=True;"
  }
}

This newly added appsettings.development.json file will remain hidden in the solutions explorer. To view this file right click the arrow (➤) before the appsettings.json file.

The below image explains this:

seeing hidden appsettings.development.json

Now go to the Program.cs file and change the BuildWebHost method from:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

To:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                var env = hostingContext.HostingEnvironment;
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
            })
            .UseIISIntegration()
            .UseStartup<Startup>();
        });

Inside this method you will see a method ConfigureAppConfiguration() being called. It is used to register the appsettings.development.json file.

Now you can run your application and will find the appsettings.development.json file is used when the application runs in development (localhost), and the other appsettings.json file is used in production (live) environment.

To get the connection string, add to the ConfigureServices method of the Starup class, the following code:

services.AddDbContext<SomeClass>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));

This code will provide the constructor of SomeClass.cs this Connection string value.

You can download the full codes of this tutorial from the below link:

Download

Conclusion
I hope you understood how to do configurations in your application one-by-one. It is really important to understand the working of ASP.NET Core MVC and I hope this tutorial has done justice to it.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.