HI WELCOME TO Sirees
Showing posts with label asp.net core. Show all posts
Showing posts with label asp.net core. Show all posts

Target Multiple Frameworks in .NET Core 2.x App

Leave a Comment
As mentioned in the previous chapter, creating a .NET Core application which targets multiple frameworks is one of the approaches for code sharing.
We can create .NET Core application and configure multiple target frameworks for it so that it can run with all the configured target frameworks. To demonstrate this, let's create .NET Core 2.0 console application which can run with .NET Core as well as traditional .NET framework in Visual Studio 2017.
The first step is to create a new project in Visual Studio 2017 by clicking on File -> New Project.. This will open New Project popup as shown below.
Create .NET Core 2.x Console Application
In the New Project popup, select Console Application (.NET Core), provide the appropriate name and click OK. This will create new console project as shown below.
Console Application
Now, we can configure multiple frameworks by editing .csproj file. So, right click on the project in solution explorer and select Edit <project-name>.csproj as shown below.
Edit .csproj
The .csproj will look like below.
.csproj:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

</Project>
As you can see above, <TargetFramework> is netcoreapp2.0. It means currently this application can run on .NET Core 2.0 framework. We can include multiple monikers for multiple frameworks here, in order to target multiple frameworks.
To target multiple frameworks, change <TargetFramework> to plural <TargetFrameworks> and include monikers for different frameworks you want to target separated by ;.
Here, we will support two more frameworks .NET Framework 4.0 & 4.6. So include net40 and net46 monikers respectively as shown below. Look at TFMs for all supported target frameworks here.
.csproj:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp2.0;net45;net46</TargetFrameworks>
  </PropertyGroup>

</Project>
As soon as you save the above .csproj file, Visual Studio will load and include the references for .NET 4.5 and .NET 4.6 into Dependencies section as shown below.
Multi Frameworks Dependencies
Now, open program.cs and let's add framework specific code using preprocessor conditions #if and #elif as shown below.
Program.cs
using System;

namespace MultiFrameworkConsole
{
    public class Program
    {
        public static void Main(string[] args)
        {
            
#if NET40
        Console.WriteLine("Target framework: .NET Framework 4.0");
#elif NET45
        Console.WriteLine("Target framework: .NET Framework 4.5");
#else
        Console.WriteLine("Target framework: .NET Core 2.0");
#endif
        Console.ReadKey();
        }
    }
}
As you can see above, to write framework specific code, use symbol with condition for .NET framework moniker and replace the dot with an underscore and change lowercase letters to uppercase.
To run the application for specific framework, click on the run dropdown and select a targeted framework as shown below.
Multi Frameworks Dependencies
Now, run the application and you will see the following output.

Framework Specific References

Sometimes you may need to include specific references for a particular framework. For example, .NET Core 2.0 meta package already includes System.Net reference which is not included in .NET 4.0 and 4.5. So, we need to include it in .csproj file using conditional reference as shown below.
.csproj:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp2.0;net45;net46</TargetFrameworks>
  </PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
    <Reference Include="System.Net" />
  </ItemGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
    <Reference Include="System.Net" />
  </ItemGroup>

</Project>
Now, System.Net reference will be added to .NET 4.0 & 4.5 and System.Net specific code will be executed for all frameworks.

Code Sharing in .NET Core

Leave a Comment
With .NET Core, we can currently develop applications with three different .NET frameworks for different platforms. The traditional or standard .NET Framework is for Windows, Mono framework for iOS, OSx and Android and .NET Core for Windows, Mac and Linux.
.NET Frameworks
These frameworks use different framework class libraries. It means code written in one framework cannot be used with other frameworks. For example, a console application developed with .NET Framework cannot run on .NET Core or vice-versa. Thus, code-sharing is not allowed.
It would be nice to write code once and share with other applications with different .NET frameworks. Isn't it?
Code Sharing
To solve this problem of code sharing, we can use the following three approaches:
  1. Create Portable Class Library
  2. Target Multiple Frameworks ASP.NET Core app
  3. Target .NET Standard
Creating portable class library to share code with other .NET frameworks is not a new thing in .NET. Learn about it here.
Learn about how to target multiple frameworks in ASP.NET Core application for code sharing in the next chapter.

.NET Core Application Types

Leave a Comment
We can create two types of applications in .NET Core.
  1. Portable Application
  2. Self-contained application

Portable Application

Portable applications are applications which expect .NET Core runtime on the deployment machines. It cannot be run on a machine which does not have .NET Core runtime installed.
.NET Core Portable Application

Self-contained Application

Self-contained applications are applications which include .NET Core runtime when we publish it. It can run on a machine which does not have .NET Core runtime installed.
.NET Core Self-contained Application

Configure Application Type

We can configure ASP.NET Core application as portable or self-contained application using typeproperty of Microsoft.NETCore.App dependency in project.json. The "type":"platform" indicates that this application expects .NET Core on the machine. This makes it a portable application.
For the self-contained application, remove type-platform from the dependency. This makes it a self-contained application which means .NET Core will be included when you build and publish an application.

ASP.NET Core - Serving Static Files

Leave a Comment
Here, we will learn how to serve static files such as html, JavaScript, CSS, or image files on HTTP request without any server-side processing.
ASP.NET Core application cannot serve static files by default. We must include Microsoft.AspNetCore.StaticFiles middleware in the request pipeline.

Install StaticFiles Middleware

The Microsoft.AspNetCore.StaticFiles middleware package is already included in the meta package Microsoft.AspNetCore.All, so we don't need to install it separately in ASP.NET Core 2.x application.
To install StaticFiles middleware in ASP.NET Core 1.x application, open NuGet package manager by right clicking on project in the solution explorer and select Manage NuGet Packages... Search for staticfiles in the search box in the browse tab. This will display Microsoft.AspNetCore.StaticFilesmiddleware as shown below.
Install StaticFiles Middleware
Click on the Install button on the right pane to install it. Once installed, the Microsoft.AspNetCore.StaticFiles is automatically included in the dependencies section of the project.json.
StaticFiles Dependency in project.json

Using StaticFiles Middleware

By default, all the static files of a web application should be located in the web root folder wwwroot. To understand this, let's create a simple default.html in the wwwroot folder with the following content.
Default.html
Now, to serve the above Default.html static file, we must add StaticFiles middleware in the Configure() method of Startup file as shown below.
public class Startup
{
    public Startup()
    {
    } 
 
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseStaticFiles();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World");
        });
    }
}
As you can see above, the app.UseStaticFiles() method adds StaticFiles middleware into the request pipeline. The UseStaticFiles is an extension method included in the StaticFiles middleware so that we can easily configure it.
Now, open the browser and send http request http://localhost:<port>/default.html which will display default.html as a response as shown below.
Serving HTML File
This way we can serve any other file stored in wwwroot folder or sub-folder. For example, consider the following test.js file in the wwwroot folder.

test.js
Now, we can access this file by sending http://localhost:<port>/test.js request.
Serving JS File
Suppose, you want to serve files from the outside of web root folder (wwwroot). For example, you include images in the following Images folder as shown below.
Serving Static Files
Now, specify StaticFileOptions parameter in the UseStaticFiles method to serve images from the Images folder as shown below.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
                            Path.Combine(Directory.GetCurrentDirectory(), @"Images")),
                            RequestPath = new PathString("/app-images")
    });
}
As you can see, we used FileProvider option to specify Images folder from which static files will be served. The RequestPath option specifies the relative path in the URL which maps to the static folder.
Now, a request to http://localhost/app-images/MyImage.png will serve the MyImage.png file.

Set Default File

As we have seen above, default.html or test.js was served on the specific request for it. However, what if we want to serve default html file on the root request?
Currently, when you send http://localhost:<port> request, it will be handled by run method and display the following result.

To serve default.html on the root request http://localhost:<port>, call UseDefaultFiles() method before UseStaticFiles() in the Configure method as shown below.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();

    app.Run(async (context) =>
    {
            await context.Response.WriteAsync("Hello World");
    });
}
The UseDefaultFiles configures the DefaultFiles middleware which is a part of StaticFiles middleware. This will automatically serve html file named default.html, default.htm, index.html or index.htm on the http request http://localhost:<port>. The above example will display default.html file on http://localhost:<port> as shown below.

Serving Static Files
 Note:
Order of middleware is very important. app.UseDefaultFiles() should be added before app.UseStaticFiles() in the request pipeline.

FileServer

The FileServer middleware combines the functionalities of UseDefaultFiles and UseStaticFiles middlware. So, instead of using both the middlware, just use UseFileServer in the Configure method.
UseFileServer = UseDefaultFiles + UseStaticFiles
Example: UseFileServer
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseFileServer();

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("Hello World");
    });
}
Thus, we can serve static files on http requests.

ASP.NET Core - Exception Handling

Leave a Comment
Exception handling is one of the most important features of any application. Fortunately, ASP.NET Core includes a middleware that makes exception handling easy. In this chapter, we will learn about exception handling in ASP.NET Core application.
By default, ASP.NET Core returns a simple status code for any exception that occurs in an application. Consider the following example of Configure method which throws an error.
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {            
        app.Run(context => { throw new Exception("error"); });
    }
}
The above code will display the following result.

Install Microsoft.AspNetCore.Diagnostics Package

To handle exceptions and display user friendly messages, we need to install Microsoft.AspNetCore.Diagnostics NuGet package and add middleware in the Configure() method. If you are using Visual Studio templates to create ASP.NET Core application then this package might be already installed. If not then you can add Microsoft.AspNetCore.Diagnostics package via NuGet manager.
The Microsoft.AspNetCore.Diagnostics package includes following extension methods to handle exceptions in different scenario:
  1. UseDeveloperExceptionPage
  2. UseExceptionHandler

UseDeveloperExceptionPage

The UseDeveloperExceptionPage extension method adds middleware into the request pipeline which displays developer friendly exception detail page. This helps developers in tracing errors that occur during development phase.
As this middleware displays sensitive information, it is advisable to add it only in development environment.
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment() || env.IsStaging())
        {
            app.UseDeveloperExceptionPage();
        }

        app.Run(context => { throw new Exception("error"); });
    }
}
The above code will display the following result.
Exception Handling
As you can see above, the developer exception page includes 4 tabs: Stack, Query, Cookies, and Headers. Stack tab displays information of stack trace, which indicates where exactly an error occurred. Query tab displays information about query string. Cookies tab displays information about cookies set by the request and Headers tab displays information about headers.

UseExceptionHandler

In MVC Core application, we might want some other controller to handle all exceptions and display custom user friendly error messages. The UseExceptionHandler extension method allows us to configure custom error handling route. This is useful when an application runs under production environment.
Example: Exception Handler in MVC
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    if (env.IsDevelopment() || env.IsStaging())
    {
        app.UseDeveloperExceptionPage();
    }
    else 
    {
        app.UseExceptionHandler("/Home/Error");
    }

    //code removed for clarity 
}
In the above example, the UseExceptionHandler("/Home/Error") sets the error handler path. If an error occurred in the MVC application then it will redirect the request to /home/error, which will execute the Error action method of HomeController.
Create a simple Error action method in HomeController class as shown below.
HomeController:
public class HomeController : Controller
{
    public HomeController()
    {
    }

    public IActionResult Error()
    {
        return View();
    } 

    // other code removed for the clarity

}
The following is the content of Error.cshtml.
Error.cshtml
@{
    ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

<h3>Development Mode</h3>
<p>
    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
    <strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>
Now, when an error occurs, it displays the page shown below.
Exception Handling
Thus, we can configure middleware to handle exceptions in ASP.NET Core application.
 Note:
Visual Studio automatically creates Error.cshtml under Home folder when you create ASP.NET Core project with MVC template.