Simplifying ADO.NET Code in .NET 6

When developers think of how to access data, many use the Entity Framework (EF), Dapper, NHibernate, or some other object-relational mapper (ORM). Each of these ORMs use ADO.NET to submit their SQL queries to the back-end database. So, why do many developers use ORMs instead of just using ADO.NET directly? Simply put, ORMs allow you to write. If each of these ORMs are simply wrappers around ADO.NET, can you write your own wrapper to cut down the amount of code you need to write? Absolutely! This series of articles shows you how to create a set of reusable wrapper classes to make it simpler to work with ADO.NET in .NET 6.

Read more on CodeMag web site here;

Simplifying ADO.NET Code in .NET 6: Part 1

Simplifying ADO.NET Code in .NET 6: Part II (Coming soon)

AutoMapper in .NET 6

Adding AutoMapper to ASP.NET 6 application;

dotnet add package AutoMapper --version 10.1.1
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection --version 8.1.1

The next step is adding the AutoMapper to our DI container, inside the program.cs we need to add the following;

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

Now its time to create our AutoMapper profiles, so on the root directory of our application we need to create AutoMapperProfile.cs

We are going to map the below entity (“User”) to the a Dto (“UserDto”)

public class User
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public DateTime DateOfBirth { get; set; }
        public string Country { get; set; }
        public string Address { get; set; }
        public string MobileNumber { get; set; }
        public string Sex { get; set; }
    }
public class UserDto
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string DateOfBirth { get; set; }
        public string Country { get; set; }
    }
}

Now inside the AutoMapperProfile class we need to add the following

public class AutoMapperProfile : Profile
    {
        public AutoMapperProfile()
        {
            CreateMap<UserDto, User>()
                .ForMember(
                    dest => dest.FirstName,
                    opt => opt.MapFrom(src => $"{src.FirstName}")
                )
                .ForMember(
                    dest => dest.LastName,
                    opt => opt.MapFrom(src => $"{src.LastName}")
                )
                .ForMember(
                    dest => dest.Email,
                    opt => opt.MapFrom(src => $"{src.Email}")
                )
                .ForMember(
                    dest => Convert.ToDateTime(dest.DateOfBirth),
                    opt => opt.MapFrom(src => $"{src.DateOfBirth}")
                )
                .ForMember(
                    dest => dest.Phone,
                    opt => opt.MapFrom(src => $"{src.Phone}")
                )
                .ForMember(
                    dest => dest.Country,
                    opt => opt.MapFrom(src => $"{src.Country}")
                )
                .ForMember(
                    dest => dest.Status,
                    opt => opt.MapFrom(src => 1)
                );
        }
    }

The AutoMapperProfile class MUST inherit from Profile class in order for AutoMapper to recognise it.

Inside the constructor we define the mapping between the Entity and the Dto.

Once we complete our profile mapping its now to utilise our new map in our controller.

public class UsersController : ControllerBase
{
    public IUnitOfWork _unitOfWork;
    // define the mapper
    public readonly IMapper _mapper;

    // initialise the dependencies with constructor initialisation
    public UsersController(
        IMapper mapper,
        IUnitOfWork unitOfWork)
    {   
        _mapper = mapper;
        _unitOfWork = unitOfWork;
    }

    [HttpPost]
    public async Task<IActionResult> AddUser(UserDto user)
    {
        // utilise the mapping :)
        var _mappedUser = _mapper.Map<User>(user);

        await _unitOfWork.Users.Add(_mappedUser);
        await _unitOfWork.CompleteAsync();

        var result = new Result<UserDto>();
        result.Content = user;

        return CreatedAtRoute("GetUser", new { id = _mappedUser.Id}, result); // return a 201
    }
}

So basically we need to initialise the mapper with constructor initialisation.

Then we need to utilise as follow

var _mappedUser = _mapper.Map<Entity>(dto);

AutoMapper is a powerful tool to keep in our toolset.

Simple Knockout sample

Knockout is a JavaScript library that implements MVVM pattern. It has a very small footprint and can be easily integrated in ASP.NET Core projects. It helps to solve complex logical UI challenges.

MVVM architecture is based on Martin Fowler’s Presentation Model. MVVM consists of three main components: Model, View, and ViewModel.

ViewModel references the Model where the View is completely unaware of the model. This helps front-end developer to stay focused on front-end development..

Here is a simple example using ASP.NET Core 6 MVC template.

<div>
    The name is <span data-bind="text: personName"></span> and the age is <span data-bind="text: personAge"></span> 
</div>
<div>
    <span>PersonName: </span><input data-bind="value: personName" />
    <span>PersonAge: </span><input data-bind="value: personAge" />
</div>

@section scripts {
    <script type="text/javascript">

        var myViewModel = {
            personName: ko.observable('Shahzad'),
            personAge: ko.observable(55)
        };

        //jQuery ready function
        $(function () {

            ko.applyBindings(myViewModel);

        });

    </script>
}

Some key functions from Knockout;

arrayFilter() -> Where()
arrayFirst() -> First()
arrayForEach() -> (no direct equivalent)
arrayGetDistictValues() -> Distinct()
arrayIndexOf() -> IndexOf()
arrayMap() -> Select()
arrayPushAll() -> (no direct equivalent)
arrayRemoveItem() -> (no direct equivalent)
compareArrays() -> (no direct equivalent)

For more info, refer here;

Knockout Home Page

ASP.NET MVC with Knockout.js

Utility function in Knockout

Filter, Search and Sort

jQuery UI and Knockout

https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/march/client-insight-knockout-s-built-in-bindings-for-html-and-javascript

https://visualstudiomagazine.com/articles/2013/08/12/javascript-data-binding-with-knockout.aspx

https://blog.craigtp.co.uk/Post/2017/01/10/KnockoutJS_binding_on_SELECT_elements_in_a_ForEach_loop

Change event on select with knockout binding, how can I know if it is a real change?

Refresh Knockout bindings when viewModel changes

Interesting idea for dynamic queries

A real world example

Use LibMan with ASP.NET Core in Visual Studio

To install/uninstall client side libraries (Bootstrap, jQuery, Popper, Knockout etc), Visual studio has a built-in support known as LibMan in ASP.NET Core projects, including:

  • Support for configuring and running LibMan restore operations on build.
  • Menu items for triggering LibMan restore and clean operations.
  • Search dialog for finding libraries and adding the files to a project.
  • Editing support for libman.json—the LibMan manifest file.

This file can be added in existing project by going through Project->Manage Client Side Libraries. A file Libman.json will be added to the root folder automatically.

LibMan file can be manually edited. This file is located in project root folder, Libman.json.

Cleaning & Restoring Client-Side Libraries can be done quite easily by right clicking on the libman.json file, and it will show up these 2 options. Simply select the needed option to perform the task.

Here is the screenshot:

Update or Uninstall Client Side Libraries

The steps to update or uninstall a Client-Side Library are similar. You need to follow the below steps.

  • 1. Open the libman.json file and then click on the client-side library which you want to uninstall or update.
  • 2. You will see a light yellow bulb icon appearing on the left side. Click on this icon to get the options for – whether to update or uninstall that specific client-side library. Here is the screenshot.

You can also uninstall and update the a client-side library by ‘removing or changing it’s version nunber’ given on it’s entry in the libman.json file, and then saving the file.

For popovers to work, either install Popover.js client library. If you prefer, try bootstrap bundle and you will get popover in it;

<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
Prerequisites

Reference

Use LibMan in Visual Studio

How to install Bootstrap and other libraries

Bootstrap 4 Get started

Bootstrap 4 has solved .NET CORE 6 popover problem. It does support jQuery version @3.56.1 and jQuery UI version @1.13.2. Bootstrap 5 doesn’t support jQuery. It supports vanilla JavaScript.