260 PostgreSQL Support - chempkovsky/CS82ANGULAR GitHub Wiki

Notes

  • We moved all WebApi controllers to separate projects
    • thus, we need to add only two projects with a few lines of code

Steps required to accomplish the task

Create Lookup WebApi project

  • in the solution folder run the commands:
dotnet new webapi -o LpPhBkPostgreSqlWebApp
dotnet sln PhonebookSolution.sln add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj --solution-folder Server
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj package LinqKit.Microsoft.EntityFrameworkCore
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj package MassTransit.RabbitMQ
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj reference LpPhBkContext/LpPhBkContext.csproj
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj reference LpPhBkViews/LpPhBkViews.csproj
dotnet add LpPhBkPostgreSqlWebApp/LpPhBkPostgreSqlWebApp.csproj reference LpPhBkControllers/LpPhBkControllers.csproj

Create main WebApi project

  • in the solution folder run the commands:
dotnet new webapi -o PhBkPostgreSqlWebApp
dotnet sln PhonebookSolution.sln add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj --solution-folder Server
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj package LinqKit.Microsoft.EntityFrameworkCore
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj package MassTransit.RabbitMQ
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj reference PhBkContext/PhBkContext.csproj
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj reference PhBkViews/PhBkViews.csproj
dotnet add PhBkPostgreSqlWebApp/PhBkPostgreSqlWebApp.csproj reference PhBkControllers/PhBkControllers.csproj

Modify appsettings json

  • We need to change only connection strings

  • for LpPhBkPostgreSqlWebApp the appsettings.json will be as follows

Click to show the file
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "LpPhnPhBkConnection": "Server=192.168.100.3;Port=5432;Database=LpPhnPhBkDbDef;User Id=postgres;Password=myPss@wrd",
    "LpEmpPhBkConnection": "Server=192.168.100.3;Port=5432;Database=LpEmpPhBkDbDef;User Id=postgres;Password=myPss@wrd",
    "LpPhBkConnection": "Server=192.168.100.3;Port=5432;Database=LpPhBkDbDef;User Id=postgres;Password=myPss@wrd"
  },
  "PhbkDivisionViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  },
  "PhbkEmployeeViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  },
  "PhbkPhoneViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  },
  "JWT": {
    "ValidAudience": "PhBkAudience",
    "ValidIssuer": "PhBkIssuer",
    "Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
  }

}
  • for PhBkPostgreSqlWebApp the appsettings.json will be as follows
Click to show the file
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "PhBkConnection": "Server=192.168.100.8;Port=5432;Database=PhBkDbDef;User Id=postgres;Password=myPss@wrd",
    "AuthConnection": "Server=192.168.100.8;Port=5432;Database=PhBkDbAuth;User Id=postgres;Password=myPss@wrd",
    "AspNetRegConnection": "Server=192.168.100.8;Port=5432;Database=PhBkAspNet;User Id=postgres;Password=myPss@wrd"
  },
  "JWT": {
    "ValidAudience": "PhBkAudience",
    "ValidIssuer": "PhBkIssuer",
    "Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
  },
  "PhbkDivisionViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  },
  "PhbkEmployeeViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  },
  "PhbkPhoneViewExtForLkUpConf": {
    "HostName": "192.168.100.3",
    "Username": "admin",
    "Password": "admin",
    "VirtualHostName": "phbkhost",
    "ClusterIpAddresses": []
  }

}

Modify Program file

  • We only need to change the code related to Dbcontexts

  • for LpPhBkPostgreSqlWebApp the Program.cs will be as follows

Click to show the file
using LpPhBkContext.PhBk;
using LpPhBkControllers.Consumers;
using LpPhBkViews.PhBk;
using MassTransit;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

ConfigurationManager configuration = builder.Configuration;
builder.Services.AddDbContext<LpPhbkDbContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("LpPhBkConnection")));
builder.Services.AddDbContext<LpEmpPhBkContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("LpEmpPhBkConnection")));
builder.Services.AddDbContext<LpPhnPhBkContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("LpPhnPhBkConnection")));


#region MassTransit config

var phbkDivisionViewExtForLkUpConf = new PhbkDivisionViewExtForLkUpConf();
configuration.GetSection(PhbkDivisionViewExtForLkUpConf.ConfName).Bind(phbkDivisionViewExtForLkUpConf);
builder.Services.AddMassTransit(x => {
    x.AddConsumer<PhbkDivisionViewExtForLkUpMsgConsumer>(typeof(PhbkDivisionViewExtForLkUpMsgConsumerDefinition));
    //.Endpoint(e => { 
    //    e.Name = "phbk-division-view"; 
    //});

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkDivisionViewExtForLkUpConf.HostName, phbkDivisionViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkDivisionViewExtForLkUpConf.Username);
            h.Password(phbkDivisionViewExtForLkUpConf.Password);
            if (phbkDivisionViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkDivisionViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkDivisionViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkDivisionViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        configurator.ConfigureEndpoints(context);
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});

var phbkEmployeeViewExtForLkUpConf = new PhbkEmployeeViewExtForLkUpConf();
configuration.GetSection(PhbkEmployeeViewExtForLkUpConf.ConfName).Bind(phbkEmployeeViewExtForLkUpConf);
builder.Services.AddMassTransit<IBusLpPhbkEmployee>(x => {
    x.AddConsumer<PhbkEmployeeViewExtForLkUpMsgConsumer>(typeof(PhbkEmployeeViewExtForLkUpMsgConsumerDefinition));
    //.Endpoint(e => { 
    //    e.Name = "phbk-division-view"; 
    //});

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkEmployeeViewExtForLkUpConf.HostName, phbkEmployeeViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkEmployeeViewExtForLkUpConf.Username);
            h.Password(phbkEmployeeViewExtForLkUpConf.Password);
            if (phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        configurator.ConfigureEndpoints(context);
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});


var phbkPhoneViewExtForLkUpConf = new PhbkPhoneViewExtForLkUpConf();
configuration.GetSection(PhbkPhoneViewExtForLkUpConf.ConfName).Bind(phbkPhoneViewExtForLkUpConf);
builder.Services.AddMassTransit<IBusLpPhbkPhone>(x => {
    x.AddConsumer<PhbkPhoneViewExtForLkUpMsgConsumer>(typeof(PhbkPhoneViewExtForLkUpMsgConsumerDefinition));
    //.Endpoint(e => { 
    //    e.Name = "phbk-division-view"; 
    //});

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkPhoneViewExtForLkUpConf.HostName, phbkPhoneViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkPhoneViewExtForLkUpConf.Username);
            h.Password(phbkPhoneViewExtForLkUpConf.Password);
            if (phbkPhoneViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkPhoneViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkPhoneViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkPhoneViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        configurator.ConfigureEndpoints(context);
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});


#endregion


#region authentification
builder.Services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
    options.SaveToken = true;
    options.RequireHttpsMetadata = true;
    options.TokenValidationParameters = new TokenValidationParameters() {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidAudience = configuration["JWT:ValidAudience"],
        ValidIssuer = configuration["JWT:ValidIssuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]))
    };
});
builder.Services.AddHttpContextAccessor();
#endregion


// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddCors(options => {
    options.AddDefaultPolicy(
        builder => {
            builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
        });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
  • for PhBkPostgreSqlWebApp the Program.cs will be as follows
Click to show the file
using LpPhBkViews.PhBk;
using MassTransit;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using PhBkContext.AspNetReg;
using PhBkContext.Auth;
using PhBkContext.PhBk;
using PhBkControllers.MassTansitBuses;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

ConfigurationManager configuration = builder.Configuration;

builder.Services.AddDbContext<PhbkDbContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("PhBkConnection")));


builder.Services.AddDbContext<aspnetchckdbcontext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("AuthConnection")));

#region authentification
builder.Services.AddDbContext<AspNetRegistrationDbContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("AspNetRegConnection")));
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<AspNetRegistrationDbContext>().AddDefaultTokenProviders();
builder.Services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
    options.SaveToken = true;
    options.RequireHttpsMetadata = true;
    options.TokenValidationParameters = new TokenValidationParameters() {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidAudience = configuration["JWT:ValidAudience"],
        ValidIssuer = configuration["JWT:ValidIssuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]))
    };
});
builder.Services.AddHttpContextAccessor();
#endregion


#region MassTransit config
var phbkDivisionViewExtForLkUpConf = new PhbkDivisionViewExtForLkUpConf();
configuration.GetSection(PhbkDivisionViewExtForLkUpConf.ConfName).Bind(phbkDivisionViewExtForLkUpConf);
builder.Services.AddMassTransit(x => {

    x.AddRequestClient<IPhbkDivisionViewExtForLkUpMsg>();

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkDivisionViewExtForLkUpConf.HostName, phbkDivisionViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkDivisionViewExtForLkUpConf.Username);
            h.Password(phbkDivisionViewExtForLkUpConf.Password);
            if (phbkDivisionViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkDivisionViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkDivisionViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkDivisionViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});

var phbkEmployeeViewExtForLkUpConf = new PhbkEmployeeViewExtForLkUpConf();
configuration.GetSection(PhbkEmployeeViewExtForLkUpConf.ConfName).Bind(phbkEmployeeViewExtForLkUpConf);
builder.Services.AddMassTransit<IBusLpPhbkEmployee>(x => {

    x.AddRequestClient<IPhbkEmployeeViewExtForLkUpMsg>();

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkEmployeeViewExtForLkUpConf.HostName, phbkEmployeeViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkEmployeeViewExtForLkUpConf.Username);
            h.Password(phbkEmployeeViewExtForLkUpConf.Password);
            if (phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkEmployeeViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});


var phbkPhoneViewExtForLkUpConf = new PhbkPhoneViewExtForLkUpConf();
configuration.GetSection(PhbkPhoneViewExtForLkUpConf.ConfName).Bind(phbkPhoneViewExtForLkUpConf);
builder.Services.AddMassTransit<IBusLpPhbkPhone>(x => {
    x.AddRequestClient<IPhbkPhoneViewExtForLkUpMsg>();

    x.UsingRabbitMq((context, configurator) => {
        configurator.Host(phbkPhoneViewExtForLkUpConf.HostName, phbkPhoneViewExtForLkUpConf.VirtualHostName, h => {
            h.Username(phbkPhoneViewExtForLkUpConf.Username);
            h.Password(phbkPhoneViewExtForLkUpConf.Password);
            if (phbkPhoneViewExtForLkUpConf.ClusterIpAddresses != null)
            {
                if (phbkPhoneViewExtForLkUpConf.ClusterIpAddresses.Length > 0)
                {

                    h.UseCluster((configureCluster) => {
                        for (int i = 0; i < phbkPhoneViewExtForLkUpConf.ClusterIpAddresses.Length; i++)
                        {
                            configureCluster.Node(phbkPhoneViewExtForLkUpConf.ClusterIpAddresses[i]);
                        }
                    });
                }
            }
            // h.PublisherConfirmation = true;
            // h.ConfigureBatchPublish(configure => { });
        });
        configurator.ConfigureEndpoints(context);
        // 
        // Quorum Queue settings
        //
        // configurator.SetQuorumQueue(3);
        //
    });
});

#endregion



// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddCors(options => {
    options.AddDefaultPolicy(
        builder => {
            builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
        });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
⚠️ **GitHub.com Fallback** ⚠️