Buongiorno Pigi,
non sò come ringraziarti anche solo per la pazienza che hai con me.
Allora Vediamo di ricapitolare il tutto provando a darti un idea chiara di quello che sto provando a fare:
la Prima view della mia app è la selezione del cliente ed il controller che ho fatto è questo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
namespace paghe.Controllers
{
public class PagheDacesController : Controller
{
public PagheDacesController(IHttpContextAccessor httpContextAccessor = null)
{
HttpContextAccessor = httpContextAccessor;
}
public IHttpContextAccessor HttpContextAccessor { get; private set; }
//View Elenco Clienti
public ActionResult ElencoClientiPaghe()
{
return View();
}
//Seleziono Cliente
public ActionResult Clienti(string SelCliente)
{
if (SelCliente == "51")
{
HttpContextAccessor.HttpContext.Session.SetString("ConCliente", "51");
HttpContext.Session.SetString("NomeCliente", "Nome Cliente 51");
ViewData["NomeCliente"] = "Nome Cliente 51";
}
if (SelCliente == "56")
{
HttpContextAccessor.HttpContext.Session.SetString("ConCliente", "56");
HttpContext.Session.SetString("NomeCliente", "Nome Cliente 56");
ViewData["NomeCliente"] = "Nome Cliente 56";
}
return RedirectToAction("Login", "LoginUser");
}
ti ho messo solo 2 cliente per Brevità.
La mia idea è seleziono dalla View il Cliente e mi salvo le sue informazioni. ConCliente e Nome Cliente
Dopo aver Selezionato il Cliente vado alla View del Login
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using paghe.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using System.Data.SqlClient;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
namespace paghe.Controllers
{
public class LoginUserController : Controller
{
private readonly PagheContext context;
public LoginUserController(PagheContext context)
{
this.context = context;
}
[HttpGet]
public ActionResult Login()
{
ViewData["NomeCliente"] = HttpContext.Session.GetString("NomeCliente");
return View();
}
[HttpPost]
public ActionResult Login(UtenteLoginModel Utente, string returnUrl)
{
if (ModelState.IsValid)
{
string NomeAccesso = IsValid(Utente.NomeUtente, Utente.Password);
string Ruolo = HttpContext.Session.GetString("Ruolo");
if (NomeAccesso != String.Empty)
{
var claims = new[] { new Claim("NameUser", NomeAccesso), new Claim(ClaimTypes.Role, Ruolo) };
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Dati non corretti.");
}
}
return View(Utente);
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
return Redirect(returnUrl);
else
return RedirectToAction("MenuPaghe", "PagheDaces");
}
public ActionResult Logout()
{
return RedirectToAction("Index", "Home");
}
private string IsValid(string NomeUtente, string password)
{
string NomeAccesso = String.Empty;
using (var context = new PagheContext())
{
var User = context.Users.FromSqlRaw("SELECT Password, Utenti.Id, NomeUtente, Ruoli.NomeRuolo FROM Utenti INNER JOIN UtentiInRuoli ON Utenti.ID = UtentiInRuoli.IDUtente " +
"INNER JOIN Ruoli ON UtentiInRuoli.IDRuolo = Ruoli.ID WHERE(Utenti.NomeUtente = '" + NomeUtente + "')").Single();
if (User != null)
{
if (User.Password == (password))
{
NomeAccesso = User.NomeUtente;
HttpContext.Session.SetString("Ruolo", User.NomeRuolo);
}
}
return NomeAccesso;
}
}
}
}
Quindi la logica sarebbe:
Io Seleziono il Cliente, aggancio il DataBase di riferimento vado sulla View Login se l'utente è corretto vado al Menu del Cliente.
il DatabaseFactory che mi hai aiuto a scrivere dovrebbe servire ad indentificare il database (se non ho capito male), in questo caso tramite un semplice query ma sarebbe più comodo tramite un altro DB, ed è questo:
sing System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
namespace paghe
{
public class DatabaseFactory
{
public DatabaseFactory(IServiceProvider provider, IHttpContextAccessor httpContextAccessor = null)
{
ServiceProvider = provider;
HttpContextAccessor = httpContextAccessor;
}
public IServiceProvider ServiceProvider { get; private set; }
public IHttpContextAccessor HttpContextAccessor { get; private set; }
public PagheContext GetDatabase()
{
if (HttpContextAccessor == null) return new PagheContext("Niente http context");
//HttpContextAccessor.HttpContext.Request.Query.TryGetValue("ConCliente", out StringValues connectionId);
string connectionId = HttpContextAccessor.HttpContext.Session.GetString("ConCliente");
switch (connectionId.ToString().ToUpper())
{
case "51":
return new PagheContext("Server= 192.168.1.103\\SQLDACES,****; Database=*************db1;User ID=***; Password=*****;");
case "56":
return new PagheContext("Server= 192.168.1.103\\SQLDACES,****; Database=*************db2;User ID=***; Password=*****;");
default:
return new PagheContext("Server= 192.168.1.103\\SQLDACES,****; Database=*************db1;User ID=***; Password=*****;");
}
}
}
}
come vedi ho sospeso il codice che HttpAccessor Request che hai scritto tu ed ho messo la Session perchè non capisco come popolarlo,
(credo che dovrei metterlo nel controller del' ELenco Cliente).
e questa è la classe del dbcontext
using Microsoft.EntityFrameworkCore;
using paghe.Models;
using paghe.ViewModels;
using Microsoft.Extensions.Configuration;
namespace paghe
{
public class PagheContext : DbContext
{
public PagheContext(string connectionString)
{
ConnectionString = connectionString;
}
public string ConnectionString { get; private set; }
public PagheContext()
{
}
public PagheContext(DbContextOptions<PagheContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(ConnectionString);
}
}
public DbSet<User> Users { get; set; }
public DbSet<Dipendenti> Dipendenti { get; set; }
}
}
Ora Secondo quello che pensavo di aver capito dovrebbe funzionare così:
1. vado nell' elenco Clienti, lì selezionando il Cliente identifico il Codice Del Cliente tramite la classe PagheDacesController.
2. il Valore passa alla Classe DatabaseFactory per indentificare tramite il ConCliente la stringa di Connessione.
3. mi collego al DataBase desiderato tramite la Classe PagheContext.
4. vado alla View Login e tramite il suo controller controllo che l' utente sia autorizzato ed entro nella View menu del Cliente.
se lancio l app in locale al momento di accedere al menu tramite il Login mi dà questo errore:
ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(string value, string parameterName)
Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, string connectionString, Action<SqlServerDbContextOptionsBuilder> sqlServerOptionsAction)
paghe.PagheContext.OnConfiguring(DbContextOptionsBuilder optionsBuilder) in PagheContext.cs
+ optionsBuilder.UseSqlServer(ConnectionString);
Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
Microsoft.EntityFrameworkCore.DbContext.get_Model()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityType()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.CheckState()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityQueryable()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.System.Linq.IQueryable.get_Provider()
Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlRaw<TEntity>(DbSet<TEntity> source, string sql, object[] parameters)
paghe.Controllers.LoginUserController.IsValid(string NomeUtente, string password) in LoginUserController.cs
+ var User = context.Users.FromSqlRaw("SELECT Password, Utenti.Id, NomeUtente, Ruoli.NomeRuolo FROM Utenti INNER JOIN UtentiInRuoli ON Utenti.ID = UtentiInRuoli.IDUtente " +
paghe.Controllers.LoginUserController.Login(UtenteLoginModel Utente, string returnUrl) in LoginUserController.cs
+ string NomeAccesso = IsValid(Utente.NomeUtente, Utente.Password);
lambda_method(Closure , object , object[] )
ovviamente se valorizzo la ConnectionString così:
ConnectionString= "Server= 192.168.1.103\\SQLDACES,****; Database=*************db2;User ID=***; Password=*****;"
funziona collegandosi al solo Db del Cliente.
Per Logica penso che i problemi siano:
nel popolare la ConnectionId perchè non la sto popolando dall' URLs ma dalla Session
e forse nel costruttore che sto usando per accedere al Db dal Login User cioè
private readonly PagheContext context;
public LoginUserController(PagheContext context)
{
this.context = context;
}
Non ti ho messo le View perchè credo non ti servano per capire dove sono gli errori
Spero di essere stato chiaro
Grazie a presto