European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting :: Instrumenting ASP.NET Core Application for exporting metrics to Prometheus

clock June 28, 2021 08:02 by author Peter

Prometheus is an open-source system monitoring and alerting toolkit. With this tool, we can monitor our application/services in production mode. In this article, we will create a simple ASP.NET Core application and will try to export some key metrics to the Prometheus server.


If you don't have any prior knowledge of Prometheus or you don't have Prometheus installed in Docker, please go through my other blog post "System Monitoring And Alerting With Prometheus (Docker)" where I have tried to give some general idea about Prometheus and the docker installation process.

First, we will create an ASP.NET Core Web API Project.

From this service, we want to expose a basic set of metrics. The available .NET library is prometheus-net that comes with a companion ASP.NET Core Package. Run the following commands in the package manager console to install prometheus-net.
Install-Package prometheus-net

Bash
Install-Package prometheus-net.AspNetCore

Bash
We can now start exposing a default set of metrics adding the following code inside the "Configure" method of the "Startup.cs" file.

N.B. Make sure to place this before the app.UseEndPoints() otherwise it may cause missing some important HTTP metrics.


If we start our service and navigate to the "/metrics" endpoint, we can see a default set of metrics exposed by our service.


We can export HTTP metrics to Prometheus. For this, we need to add HttpMetrics middleware provided by "pormetheus-net".


After adding this middleware if we navigate to the "/metrics" endpoint we can see the HTTP metrics have been exposed.


N.B. Like this HTTP Metrics, we can even export different Health Status Metrics, Network Health Status Metrics, .Net Core Runtime Metrics. But for simplicity's purpose, I am skipping it. But if you are interested you can go through these Nuget package documentation to have a clear understanding.

    prometheus-net.AspNetCore.HealthChecks
    prometheus-net.AspNetCore.HealthChecks
    AspNetCore.HealthChecks.SqlServer
    AspNetCore.HealthChecks.Network
    prometheus-net.SystemMetrics

We can even export some Custom Metrics from our application. For example, we will create a very basic metric to track how many times any specific method is executed.

For this, we will simply go to one of our controllers and put the following code. By this code, we can track how many times this "Get()" method has been executed.


Now as we have instrumented our application with Prometheus and the metrics have been ready now we just need to send these metrics to the Prometheus(Docker) server. For this, we need to dockerize our application. For this, we need to add a "Dockerfile" in the root directory of our application. Dockerfile should contain the following code.

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["PormetheusMetrics/PormetheusMetrics.csproj", "PormetheusMetrics/"]
RUN dotnet restore "PormetheusMetrics/PormetheusMetrics.csproj"
COPY . .
WORKDIR "/src/PormetheusMetrics"
RUN dotnet build "PormetheusMetrics.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "PormetheusMetrics.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PormetheusMetrics.dll"]


Docker

And then need to run the following docker command from the root directory of our application. This command will dockerize our application in docker port 8085.

docker build -t netcore_prom .
docker run -d -p 8085:80 --name netcore_prom netcore_prom

Bash

After the application has been dockerized. We need to set this application as a target in our Prometheus server. For this, we need to do some changes in prometheus.yml file[Please follow my previous blog System Monitoring And Alerting With Prometheus (Docker)]. The prometheus.yml file should be edited as follows.

global:
  scrape_interval: 30s
  scrape_timeout: 10s

rule_files:
scrape_configs:
  - job_name: services
    metrics_path: /metrics
    static_configs:
      - targets: ['prometheus:9090']
  - job_name: 'my-app'
    static_configs:
      - targets: ['host.docker.internal:8085']

YAML
Now if we re-run the Prometheus container as we have updated the "prometheus.yml",
docker-compose up -d

Bash

Now if we go to our Prometheus Web UI(http://localhost:9090) and click on the Targets we can see all our targets and their current status.


 

So here we can see that our Application (my-app) service is up and running.
We can even query for our exposed metrics in the Prometheus Web UI and see metrics.

Just like this, we can query all the metrics that we have exposed from our application.

And with this, we finally export our metrics to the Prometheus server. Though this is a huge topic I just tried to keep this as simple as possible. But if you are interested further I would recommend going through the official website of the Prometheus there you will get to learn more about this.

In the next article, I will try to describe integrating Alert Manager with Prometheus.



European ASP.NET Core Hosting :: Send Email Using ASP.NET Core 5 Web API

clock June 21, 2021 07:08 by author Peter

In this article, we will learn how to send an email in ASP.Net Core Web API. We will code the endpoint that will send the email to a user of your business customers. I am implementing the Cloud Native Microservices architecture in my project. And this service is one of the microservices of my project and I will extend this Microservice to handle all types of emails in my project.

Create the ASP.Net Core Web API Project
First, you need to create the ASP.Net core web project using the ASP.Net core 5 web API.
Install the MailKit Nuget Package

Right click on your Solution File. Now click on select the option Nuget Package and then find the MailKit Library for your project configuration. After the installation of this library, add the reference in the code.

Install-Package NETCore.MailKit

C#

You need to include the following namespaces in your code for the correct configuration.
using MailKit.Net.Smtp;
using MailKit.Security;

Add the Folder Model
After the creation of the Model, now create the class MailRequest with the following information.
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace _101SendEmailNotificationDoNetCoreWebAPI.Model
{
    public class MailRequest
    {
        public string ToEmail { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public List<IFormFile> Attachments { get; set; }
    }
}


Not Add the Folder Services
After the creation of the folder now add the following classes.

IMailService
using _101SendEmailNotificationDoNetCoreWebAPI.Model;
using System.Threading.Tasks;
namespace _101SendEmailNotificationDoNetCoreWebAPI.Services
{
    public interface IMailService
    {
        Task SendEmailAsync(MailRequest mailRequest);

    }
}


using MimeKit;
using System.IO;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Options;
using _101SendEmailNotificationDoNetCoreWebAPI.Settings;
using _101SendEmailNotificationDoNetCoreWebAPI.Model;
namespace _101SendEmailNotificationDoNetCoreWebAPI.Services
{
    public class MailService : IMailService
    {
        private readonly MailSettings _mailSettings;
        public MailService(IOptions<MailSettings> mailSettings)
        {
            _mailSettings = mailSettings.Value;
        }
        public async Task SendEmailAsync(MailRequest mailRequest)
        {
            var email = new MimeMessage();
            email.Sender = MailboxAddress.Parse(_mailSettings.Mail);
            email.To.Add(MailboxAddress.Parse(mailRequest.ToEmail));
            email.Subject = mailRequest.Subject;
            var builder = new BodyBuilder();
            if (mailRequest.Attachments != null)
            {
                byte[] fileBytes;
                foreach (var file in mailRequest.Attachments)
                {
                    if (file.Length > 0)
                    {
                        using (var ms = new MemoryStream())
                        {
                            file.CopyTo(ms);
                            fileBytes = ms.ToArray();
                        }
                        builder.Attachments.Add(file.FileName, fileBytes, ContentType.Parse(file.ContentType));
                    }
                }
            }
            builder.HtmlBody = mailRequest.Body;
            email.Body = builder.ToMessageBody();
            using var smtp = new SmtpClient();
            smtp.Connect(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls);
            smtp.Authenticate(_mailSettings.Mail, _mailSettings.Password);
            await smtp.SendAsync(email);
            smtp.Disconnect(true);
        }
    }
}


Add the Folder Settings
Add the class setting in which you define the following Properties.
namespace _101SendEmailNotificationDoNetCoreWebAPI.Settings
{
    public class MailSettings
    {
        public string Mail { get; set; }
        public string DisplayName { get; set; }
        public string Password { get; set; }
        public string Host { get; set; }
        public int Port { get; set; }
    }
}


Add the Controller in the project
Create the Email Controller in which you define the endpoint. Send Email is responsible for sending the email to your business customers.
using _101SendEmailNotificationDoNetCoreWebAPI.Model;
using _101SendEmailNotificationDoNetCoreWebAPI.Services;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;

namespace _101SendEmailNotificationDoNetCoreWebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class EmailController : Controller
    {

        private readonly IMailService mailService;
        public EmailController(IMailService mailService)
        {
            this.mailService = mailService;
        }

        [HttpPost("Send")]
        public async Task<IActionResult> Send([FromForm] MailRequest request)
        {
            try
            {
                await mailService.SendEmailAsync(request);
                return Ok();
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }


    }
}


Configure Each Service In Start-up Class
using _101SendEmailNotificationDoNetCoreWebAPI.Services;
using _101SendEmailNotificationDoNetCoreWebAPI.Settings;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace _101SendEmailNotificationDoNetCoreWebAPI
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<MailSettings>(Configuration.GetSection("MailSettings"));
            services.AddTransient<IMailService, Services.MailService>();

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "_101SendEmailNotificationDoNetCoreWebAPI", Version = "v1" });
            });
            services.AddCors(c =>
            {
                c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
        }

        // 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.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "_101SendEmailNotificationDoNetCoreWebAPI v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

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


Configure the Mail Setting in AppSetting.Json
Configure the SMTP Setting in AppSetting.Json in the following way,

"MailSettings": {
    "Mail": "[email protected]",
    "DisplayName": "Your Brand Name",
    "Password": "YourPassword",
    "Host": "SMTP Host",
    "Port": 587
  },

  •  Mail Define your email Address
  •  Display Name is your Brand Name
  •  The password of your SMTP Server
  •  The host is your SMTP Host
  •  Port No is Your SMTP PORT No

Run your Project and hit the End Point. Now Swagger UI Exposes the End Point


After hitting the endpoint now add the required information in the request body of the endpoint.


Now click on the execute button when the endpoint successfully sends the request then the status is == 200 so our email is successfully sent to the required email address.


In the case of the GMAIL address now click on the Spam folder and your email is there.

In the case of an Outlook/Microsoft Account, just click your Inbox and receive your email there.

Now, check your Email address inbox folder.



European ASP.NET Core Hosting :: Manage Primary Key And Foreign Key Relationship During Migration

clock June 14, 2021 07:14 by author Peter

In this article, we will learn how to create models for database table migration. When we build a simple database for our project, then it is easy to build class models. But when we develop a complex database for our project, then it's hard to maintain PK & FK relationship over the model. It is not easy to maintain, the string length and datatypes over the model.

So, let's see a few points while creating a model class.
Okay, here are the three tables, names - UserDetails, Customer, and Order. Here, we want to create the ID column as the primary key and a foreign key to the UserId column with the AspNetUser table. Like in the database here, also we want to restrict columns with string length. And also want to create two primary keys in a single model.
like below,
 
 Manage Primary Key And Foreign Key Relationship During Migration  Manage Primary Key And Foreign Key Relationship During Migration
 
 Manage Primary Key And Foreign Key Relationship During Migration
 
Here, Firstly I am going to create the UserDetails table. In which few properties and a foreign key relationship exit with the AspnetUser table.
    public class UserDetails {  
        [Key]  
        public int Id {  
            get;  
            set;  
        }  
        [StringLength(100)]  
        [Column(TypeName = "varchar(100)")]  
        public string Name {  
            get;  
            set;  
        }  
        [StringLength(50)]  
        [Column(TypeName = "varchar(50)")]  
        public string Email {  
            get;  
            set;  
        }  
        [StringLength(1)]  
        [Column(TypeName = "char(1)")]  
        public string Gender {  
            get;  
            set;  
        }  
        public string ProfilePic {  
            get;  
            set;  
        }  
        [ForeignKey("IdentityUser")]  
        public string UserId {  
            get;  
            set;  
        }  
        public virtual IdentityUser IdentityUser {  
            get;  
            set;  
        }  
        public byte Role {  
            get;  
            set;  
        }  
        public DateTime ? CreatedOn {  
            get;  
            set;  
        }  
        public bool ? IsActive {  
            get;  
            set;  
        }  
    }   


Here are a few packages for model attribute properties, which we will use to decorate class properties.

    using System.ComponentModel.DataAnnotations;  
    using System.ComponentModel.DataAnnotations.Schema;  

In this model, we are making a Foreign Key relationship with IdentityUser class, which is available in the database with the name AspnetUsers.

    using Microsoft.AspNetCore.Identity;  

If we want to set the string length of 100/50 or something else varchar characters in the database of the Name property, then we define attribute like this,
    [StringLength(100)]    
    [Column(TypeName = "varchar(100)")]    
    public string Name { get; set; }    


If we desire to set the string length of 1 character only in the database of the Gender property, then we define attribute like this,
    [StringLength(1)]    
    [Column(TypeName = "char(1)")]    
    public string Gender { get; set; }   


If we desire to set the DateTime datatype with nullable constraint in the database of the CreatedOn property, then we define attribute like this,
    public DateTime? CreatedOn { get; set; }  

If we desire to make a foreign Key relationship with IdentityUser and store the IdentityUser table Id in the UserId column, then we define attribute like this,
    [ForeignKey("IdentityUser")]  
    public string UserId { get; set; }  
    public virtual IdentityUser IdentityUser { get; set; }  


Now, we will create the customer table. Which contains FullName, Description & Address properties, and the one foreign Key relationship with UserDetails table in the UserDetailsId column.
    public class Customer {  
        [Key]  
        public int Id {  
            get;  
            set;  
        }  
        [StringLength(100)]  
        [Column(TypeName = "varchar(100)")]  
        public string FullName {  
            get;  
            set;  
        }  
        [StringLength(500)]  
        [Column(TypeName = "varchar(500)")]  
        public string Description {  
            get;  
            set;  
        }  
        [StringLength(500)]  
        [Column(TypeName = "varchar(500)")]  
        public string Address {  
            get;  
            set;  
        }  
        [ForeignKey("UserDetails")]  
        public virtual int UserDetailsId {  
            get;  
            set;  
        }  
        public virtual UserDetails UserDetails {  
            get;  
            set;  
        }  
    }   


If we wish to create two foreign Keys in a single table like UserDetailsId, CustomerId in the Order table, then we write two properties for a single foreign key like this,
    public class Order  
       {  
           [Key]  
           public int Id { get; set; }  
      
           [StringLength(100)]  
           [Column(TypeName = "varchar(100)")]  
           public string OrderNumber { get; set; }  
      
           [ForeignKey("Customer")]  
           public virtual int CustomerId { get; set; }  
           public virtual Customer Customer { get; set; }  
      
           [ForeignKey("UserDetails")]  
           public virtual int UserDetailsId { get; set; }  
           public virtual UserDetails UserDetails { get; set; }  
       }  


Register all tables in ApplicationDbContext class set the proper connection string in appsettings.json, register properly this class to Startup.cs class, and then run migration by migration command.
 
ApplicationDbContex.cs class
    public class ApplicationDbContext: IdentityDbContext {  
        public ApplicationDbContext(DbContextOptions < ApplicationDbContext > options): base(options) {}  
        public DbSet < UserDetails > UserDetails {  
            get;  
            set;  
        }  
        public DbSet < Customer > Customer {  
            get;  
            set;  
        }  
        public DbSet < Order > Order {  
            get;  
            set;  
        }  
    }   

appsettings.json class
    "ConnectionStrings": {  
       "DefaultConnection": "Server=MyServer;Database=db_A;user=sa;[email protected];Trusted_Connection=False;"  
     },  

Startup.cs class
    public void ConfigureServices(IServiceCollection services) {  
        services.AddDbContext < ApplicationDbContext > (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));  
        services.AddDefaultIdentity < IdentityUser > (options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores < ApplicationDbContext > ();  
        services.AddControllersWithViews();  
        services.AddRazorPages();  
    } 



European ASP.NET Core Hosting :: A Peek Into .NET 6's DateOnly And TimeOnly Structure

clock June 7, 2021 08:26 by author Peter

If there was a poll to find that one little feature every C# developer would love to have in .Net, then it is most likely the ability to store Date and Time individually. For years now, we had to use DateTime to represent Date when the Time part of the object had to be ignored. The same thing happened when we wanted to save time and had to ignore the Date of the DateTime component.
 

And with .Net 6, that long agonizing wait has come to an end. .Net 6 has now introduced DateOnly and TimeOnly Structures which could store Date and Time components.
 
DateOnly
The DateOnly structure allows you to save a Date property with a more explicit structure rather than using the DateTime and ignoring the Time part.
    var dateOnlyFirst = new DateOnly(2020, 2, 16);  
    var dateOnlySecond = DateOnly.FromDateTime(DateTime.Now);  
    Console.WriteLine(dateOnlyFirst);  
    Console.WriteLine(dateOnlySecond);  
    // Output  
    16-02-2020  
    04-06-2021  


We could create the instance either using the Constructors or static helper methods like DateOnly.FromDateTime. It is also interesting to know what happens behinds the scenes. Internally, the DateOnly structure stores the value in an Int32 field that represents the number of days since 1/1/0001. The field is designed to store values from 1 Jan,0001 to 31st Dec 9999. If you take a glimpse of code in the .Net Github source code for DateOnly, you could find some of the following,
    private readonly int _dayNumber;  
    // Maps to Jan 1st year 1  
    private const int MinDayNumber = 0;  
    // Maps to December 31 year 9999. The value calculated from "new DateTime(9999, 12, 31).Ticks / TimeSpan.TicksPerDay"  
    private const int MaxDayNumber = 3_652_058;  
    public DateOnly(int year, int month, int day) => _dayNumber = DayNumberFromDateTime(new DateTime(year, month, day));  
    public static DateOnly FromDateTime(DateTime dateTime) => new DateOnly(DayNumberFromDateTime(dateTime));  
    private static int DayNumberFromDateTime(DateTime dt) => (int)(dt.Ticks / TimeSpan.TicksPerDay);  

The DateOnly provides most of the (applicable) functionality that DateTime provides including AddDays(),AddMonths(),AddYears, ParseExact and many more.
 
TimeOnly
TimeOnly Quite similar to DateOnly, the TimeOnly structure provides a way to represent the Time component effectively in .Net.
    var timeOnlyFirst = new TimeOnly(10,10,10);  
    var timeOnlySecond = TimeOnly.FromDateTime(DateTime.Now);  
    Console.WriteLine(timeOnlyFirst);  
    Console.WriteLine(timeOnlySecond);  
    //Output  
    10:10  
    05:35  


Internally, TimeOnly uses a long to represent the ticks elapsed since midnight. Let us know to take a glimpse of the internal code of TimeOnly.
     // represent the number of ticks map to the time of the day. 1 ticks = 100-nanosecond in time measurements.  
    private readonly long _ticks;  
    // MinTimeTicks is the ticks for the midnight time 00:00:00.000 AM  
    private const long MinTimeTicks = 0;  
    // MaxTimeTicks is the max tick value for the time in the day. It is calculated using DateTime.Today.AddTicks(-1).TimeOfDay.Ticks.  
    private const long MaxTimeTicks = 863_999_999_999;  
    public TimeOnly(int hour, int minute, int second) : this(DateTime.TimeToTicks(hour, minute, second, 0)) {}  
    public TimeOnly(long ticks)  
       {  
          if ((ulong)ticks > MaxTimeTicks)  
          {  
             throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_TimeOnlyBadTicks);  
          }  
       _ticks = ticks;  
    }  

As with the DateOnly structure, the TimeOnly too comes in with a lot of helper methods that would aid the developer.
 
It is quite safe to assume that a lot of developers would be quite happy with the introduction of these structures. These would definitely improve the code base a lot and make the representations more explicit, rather than using DateTime and ignoring a part of it.



European ASP.NET Core Hosting :: What Is AutoMapper In ASP.NET Core ?

clock June 2, 2021 08:14 by author Peter

In this article, we are going to see what is AutoMapper in .NET core, what problems it solves, how to use AutoMapper, AutoMapper ForMember method, AutoMapper ReverseMap method, and Conditional Mappings.

What is AutoMapper?
AutoMapper is a simple C# library that transforms one object type to another object type, which means, it’s a mapper between two objects. AutoMapper is the convention-based object to object mapper. It maps the properties of two different objects by transforming the input object of one type to the output object of another type.
 
How to add AutoMapper?
The first step is to install the corresponding NuGet package in the Package Manager console, using the command “Install-Package Automapper.Extensions.Microsoft.DependencyInjection”. This command will install all AutoMapper Packages.
 
The next step configures the AutoMapper services into our application. Open startup.cs class file, add “services.AddAutoMapper(typeof(Startup))” in configure services method.
 
Now the AutoMapper Package was installed and configured in our project.
 
How to use Automapper?
Let's take a new user model class, this class will have several properties.
    Public class User {  
        Public int Id {  
            get;  
            set;  
        }  
        Public string FirstName {  
            get;  
            set;  
        }  
        Public string LastName {  
            get;  
            set;  
        }  
        Public string Email {  
            get;  
            set;  
        }  
        Public string Address {  
            get;  
            set;  
        }  
        Public int Age {  
            get;  
            set;  
        }  
    }  


Let’s create a new user view model class, and display the user information,
    Public class UserViewModel {  
        Public string FirstName {  
            get;  
            set;  
        }  
        Public string LastName {  
            get;  
            set;  
        }  
        Public string Email {  
            get;  
            set;  
        }  
    }  


Now let’s see how to convert our domain object to a view model. By using the concept called Profiles, we can organize our mapping configurations.
 
Let’s create a new user profile class, in this class, we can create the mapping configuration inside the constructor.
    Public class UserProfile: Profile // this class inherits from AutoMapper profile class  
    {  
        CreateMap < User, UserViewModel > ();  
    }  


So, basically, we create the mapping from our User domain object to the UserViewModel. That’s it.
 
As soon as our application starts AutoMapper service will scan the application and look for classes that inherit from the profile class and load their mapping configurations.
 
Now, let’s create new controller with the name UserController,
    Public class UserController: controller {  
        Private readonly IMapper _mapper;  
        Public UserController(IMapper mapper) {  
            _mapper = mapper;  
        }  
        Public IActionResult Index() {  
            var userInfo = GetUserInfo();  
            var userViewModel = _mapper.map < UserViewModel > (userInfo);  
            return View(userViewModel);  
        }  
        Private static User GetUserInfo() {  
            Return new User {  
                Id = 1,  
                    FirstName = “John”,  
                    LastName = “Smith”,  
                    Email = “john.smith @gmail.com”  
            }  
        }  
    }  


Now if we run the application (localhost:5001/user), we can see the below result,
 

That’s all, our AutoMapper was successfully converting from the User domain model object to the UserViewModel object. Very simple isn’t it?
 
But if we have different property names in our source object and destination object ??
 
Here comes the ForMember Method concept.
 
Let’s modify the property names in the above userviewmodel class,
    Public class UserViewModel {  
        Public string FName {  
            get;  
            set;  
        } // previously FirstName  
        Public string LName {  
            get;  
            set;  
        } // previously LastName  
        Public string Email {  
            get;  
            set;  
        }  
    }  


So, now we must map user FirstName to FName and user LastName to LName, to make this work we have to change the mapping in the UserProfile class file.
    Public class UserProfile : Profile // this class inherits from AutoMapper profile class  
    {  
    CreateMap<User, UserViewModel>()  
        .ForMember(dest =>  
            dest.Fname,  
            opt => opt.MapFrom(src => src.FirstName))  
        .ForMember(dest =>  
            dest.Lname,  
            opt => opt.MapFrom(src => src.LastName));  
    }  


Above, we customized the configuration for individual members, we can use the ForMember method which has the destination member parameter of type expression and member options parameter of type action.
 
So far we have only looked at one-directional mapping, which means if we have two types, typeA, and typeB then we only map type A to type B.
 
But by using automatic Reverse mapping (using ReverseMap method), it’s possible to achieve Bi-Directional mapping.

    Public class UserProfile : Profile // this class inherits from AutoMapper profile class  
    {  
    CreateMap<User, UserViewModel>()  
        .ForMember(dest =>  
            dest.Fname,  
            opt => opt.MapFrom(src => src.FirstName))  
        .ForMember(dest =>  
            dest.Lname,  
            opt => opt.MapFrom(src => src.LastName))  
        .ReverseMap();  
    }  

Once the reverse map is configured, we can map back from destination to source type.
 
UserController.cs
    Public IActionResult Index() {  
        var userInfo = GetUserInfo();  
        var userViewModel = _mapper.map < UserViewModel > (userInfo);  
        var userViewModelReverse = _mapper.map < Userl > (userViewModel); // Bi-directional Mapping  
        return View(userViewModel);  
    }  


AutoMapper allows you to add Conditional Mapping to properties that must be met before that property will be mapped.
    Public class UserProfile : Profile // this class inherits from AutoMapper profile class  
    {  
    CreateMap<User, UserViewModel>()  
        .ForMember(dest =>  
            dest.Fname,  
            opt => opt.MapFrom(src => src.FirstName))  
        .ForMember(dest =>  
            dest.Lname,  
            opt => opt.MapFrom(src => src.LastName))  
        .ForMember(dest =>  
            dest.IsAdult,  
            opt => opt.Condition (src => src.Age > 18 ? true:false))  
        .ReverseMap();  
    }  


In the above example, the IsAdult property value is based on the condition of Age > 18.
In this article, we have seen what is AutoMapper, how to install and Configure, AutoMapper ForMember method, AutoMapper ReverseMap method, and Conditional Mappings.
Also, AutoMapper provides so many other features to simplify complex mappings. You can check the complete AutoMapper documentation. I hope this article will help you to understand the AutoMapper in ASP.NET Core.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in