Set up Automapper in ASP.NET Core

Add the main AutoMapper Package to your solution via NuGet.

Add the AutoMapper Dependency Injection Package to your solution via NuGet.

Create a new class for a mapping profile. (I made a class in the main solution directory called MappingProfile.cs and add the following code.) I’ll use a User and UserDto object as an example.

public class MappingProfile : Profile {
     public MappingProfile() {
         // Add as many of these lines as you need to map your objects
         CreateMap<User, UserDto>();
         CreateMap<UserDto, User>();
     }
 }

Then add the AutoMapperConfiguration in the Startup.cs as shown below:

public void ConfigureServices(IServiceCollection services) {
    // .... Ignore code before this

   // Auto Mapper Configurations
    var mapperConfig = new MapperConfiguration(mc =>
    {
        mc.AddProfile(new MappingProfile());
    });

    IMapper mapper = mapperConfig.CreateMapper();
    services.AddSingleton(mapper);

    services.AddMvc();

}

To invoke the mapped object in code, do something like the following:

public class UserController : Controller {

    // Create a field to store the mapper object
    private readonly IMapper _mapper;

    // Assign the object in the constructor for dependency injection
    public UserController(IMapper mapper) {
        _mapper = mapper;
    }

    public async Task<IActionResult> Edit(string id) {

        // Instantiate source object
        // (Get it from the database or whatever your code calls for)
        var user = await _context.Users
            .SingleOrDefaultAsync(u => u.Id == id);

        // Instantiate the mapped data transfer object
        // using the mapper you stored in the private field.
        // The type of the source object is the first type argument
        // and the type of the destination is the second.
        // Pass the source object you just instantiated above
        // as the argument to the _mapper.Map<>() method.
        var model = _mapper.Map<UserDto>(user);

        // .... Do whatever you want after that!
    }
}

References
https://stackoverflow.com/questions/40275195/how-to-set-up-automapper-in-asp-net-core

Change Access Modifier of .resx to Public in Dot NET

Create resource file.
Edit the .csproj file manually.
Search for the embedded resource tag that includes the *.resx file.
Change Generator child tag content to ‘PublicResXFileCodeGenerator’.
Apply “Move to resource”.

<ItemGroup>
    <EmbeddedResource Update="Resources/Resources.resx">
        <Generator>PublicResXFileCodeGenerator</Generator>
    </EmbeddedResource>
</ItemGroup>

References
https://youtrack.jetbrains.com/issue/RIDER-33587/Allow-to-change-access-modifier-of-resx-to-public

Get an element by ID or Class in Blazor

Blazor doesn’t manipulate the DOM directly at C# side. You cancall the JavaScript method by using JavaScript Interop to get an element by ID or class.

  • The getElementsByClassName() method returns a collection of all elements in the document with the specified class names.
  • The getElementById() method returns a collection of all elements in the document with the specified ID names.
@page "/"
@inject IJSRuntime JsRuntime

<h1 id="headingElement">Hello, world!</h1>

<p class="para-element">Welcome to your new app.</p>

@code {
    protected override async void OnAfterRender(bool firstRender)
    {
        await JsRuntime.InvokeVoidAsync("elementId");
    }
}
<body>
      . . .
      . . .

      <script>
        function elementId() {
            // Get element with the specified ID name
            var idValue = document.getElementById("headingElement");
            console.log(idValue.innerHTML);
            // Get element with the specified Class name
            var classValue = document.getElementsByClassName("para-element");
            console.log(classValue[0].innerHTML);
        }
    </script>
</body>

References
https://www.syncfusion.com/faq/blazor/javascript-interop/how-do-i-get-an-element-by-id-or-class-in-blazor

ASP.NET Core Blazor Server with Entity Framework Core

appsettings.Development.json

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
    "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.EntityFrameworkCore.Database.Command": "Information"
    }
  }
}

Database access

using var context = new MyContext();

return await context.MyEntities.ToListAsync();
if (Loading)
{
    return;
}

try
{
    Loading = true;

    ...
}
finally
{
    Loading = false;
}

New DbContext instances

builder.Services.AddDbContextFactory<ContactContext>(opt =>
    opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db"));
private async Task DeleteContactAsync()
{
    using var context = DbFactory.CreateDbContext();
    Filters.Loading = true;

    if (Wrapper is not null && context.Contacts is not null)
    {
        var contact = await context.Contacts
            .FirstAsync(c => c.Id == Wrapper.DeleteRequestId);

        if (contact is not null)
        {
            context.Contacts?.Remove(contact);
            await context.SaveChangesAsync();
        }
    }

    Filters.Loading = false;

    await ReloadAsync();
}

Scope to the component lifetime

@implements IDisposable
@inject IDbContextFactory<ContactContext> DbFactory
public void Dispose()
{
    Context?.Dispose();
}
protected override async Task OnInitializedAsync()
{
    Busy = true;

    try
    {
        Context = DbFactory.CreateDbContext();

        if (Context is not null && Context.Contacts is not null)
        {
            var contact = await Context.Contacts.SingleOrDefaultAsync(c => c.Id == ContactId);

            if (contact is not null)
            {
                Contact = contact;
            }
        }
    }
    finally
    {
        Busy = false;
    }

    await base.OnInitializedAsync();
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-6.0

Entity Framework Core Database-First using Npgsql

dotnet ef dbcontext scaffold "Host=my_host;Database=my_db;Username=my_user;Password=my_pw" Npgsql.EntityFrameworkCore.PostgreSQL

If you have other tables in your database, you may use additional parameters – -Schemas and -Tables – to filter the list of schemas and/or tables that are added to the model. For example, you can use the following command:

dotnet ef dbcontext scaffold "host=server;database=test;user id=postgres;" Devart.Data.PostgreSql.Entity.EFCore -Tables dept,emp

References
https://www.npgsql.org/efcore/index.html
https://www.devart.com/dotconnect/postgresql/docs/EFCore-Database-First-NET-Core.html

Deserialize XML to Object in C#

<?xml version="1.0" encoding="utf-8"?>
<Company xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Employee name="x" age="30" />
  <Employee name="y" age="32" />
 </Company>
using System.Xml.Serialization;

[XmlRoot(ElementName = "Company")]
public class Company

{
    public Company()
    {  
        Employees = new List<Employee>();
    }

    [XmlElement(ElementName = "Employee")]
    public List<Employee> Employees { get; set; }

    public Employee this[string name]
    {
        get { return Employees.FirstOrDefault(s => string.Equals(s.Name, name, 							StringComparison.OrdinalIgnoreCase)); }
    }
}

public class Employee
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("age")]
    public string Age { get; set; }
}
public static T DeserializeXml<T>(string str)
{
    var serializer = new XmlSerializer(typeof(T));
    object result;

    using (TextReader reader = new StringReader(str))
    {
        result = serializer.Deserialize(reader);
    }

    return (T) result;
}
var s = "--your xml string--";
var obj = Deserialize<CMS>(s);

References
https://www.delftstack.com/howto/csharp/deserialize-xml-to-object-in-csharp/
https://stackoverflow.com/questions/47158427/how-to-convert-xml-to-list-of-objects

Map Table Name and Column Name in Entity Framework

Table name

[Table("blogs")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable("blogs");
}

Table schema

[Table("blogs", Schema = "blogging")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable("blogs", schema: "blogging");
}

Rather than specifying the schema for each table, you can also define the default schema at the model level with the fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasDefaultSchema("blogging");
}

Column name

public class Account
 {
     [Column("MyPasswordHashColumn")]
     public string PasswordHash { get; set; }

 }
public class YourContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Language>(x => x
            .ToTable("MyAccountsTable")
            .Property(entity => entity.PasswordHash)
                .HasColumnName("MyPasswordHashColumn")
        );
    }
}

References
https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations
https://stackoverflow.com/questions/42190909/how-to-specify-entity-framework-core-table-mapping

Reset Entity Framework Migrations and Drop Database

Remove all files from the migrations folder.

dotnet-ef database drop -f -v
dotnet-ef migrations add Initial
dotnet-ef database update

Do that only if you don’t care about your current persisted data

Without Dropping Database

The Issue: You have mucked up your migrations and you would like to reset it without deleting your existing tables.

The Problem: You can’t reset migrations with existing tables in the database as EF wants to create the tables from scratch.

What to do:

  1. Delete existing migrations from Migrations_History table.
  2. Delete existing migrations from the Migrations Folder.
  3. Run dotnet-ef migrations add Initial. This will create a migration in your Migration folder that includes creating the tables (but it will not run it so it will not error out.)
  4. You now need to create the initial row in the MigrationHistory table so EF has a snapshot of the current state. EF will do this if you apply a migration. However, you can’t apply the migration that you just made as the tables already exist in your database. So go into the Migration and comment out all the code inside the “Up” method.
  5. Now run dotnet-ef database update. It will apply the Migration (while not actually changing the database) and create a snapshot row in MigrationHistory.

You have now reset your migrations and may continue with normal migrations.

References
https://stackoverflow.com/questions/11679385/reset-entity-framework-migrations

Installing .NET 6 on Ubuntu 22.04

sudo apt update && sudo apt install -y wget
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
sudo touch /etc/apt/preferences
sudo nano /etc/apt/preferences

Paste :

Package: *
Pin: origin "packages.microsoft.com"
Pin-Priority: 1001
sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-6.0
dotnet --info

References
https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#2204
https://github.com/dotnet/core/issues/7699