Feat Workers Prioridades y Nivel Serilog
This commit is contained in:
		| @@ -6,6 +6,7 @@ using Elecciones.Core.DTOs.ApiRequests; | ||||
| using Elecciones.Database.Entities; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Elecciones.Core.Enums; | ||||
| using Elecciones.Infrastructure.Services; | ||||
|  | ||||
| namespace Elecciones.Api.Controllers; | ||||
|  | ||||
| @@ -16,11 +17,13 @@ public class AdminController : ControllerBase | ||||
| { | ||||
|   private readonly EleccionesDbContext _dbContext; | ||||
|   private readonly ILogger<AdminController> _logger; | ||||
|   private readonly LoggingSwitchService _loggingSwitchService; | ||||
|  | ||||
|   public AdminController(EleccionesDbContext dbContext, ILogger<AdminController> logger) | ||||
|   public AdminController(EleccionesDbContext dbContext, ILogger<AdminController> logger, LoggingSwitchService loggingSwitchService) | ||||
|   { | ||||
|     _dbContext = dbContext; | ||||
|     _logger = logger; | ||||
|     _loggingSwitchService = loggingSwitchService; | ||||
|   } | ||||
|  | ||||
|   // Endpoint para obtener todas las agrupaciones para el panel de admin | ||||
| @@ -297,4 +300,41 @@ public class AdminController : ControllerBase | ||||
|     await _dbContext.SaveChangesAsync(); | ||||
|     return NoContent(); | ||||
|   } | ||||
|  | ||||
|   /// <summary> | ||||
|   /// Actualiza el nivel mínimo de logging en tiempo real y guarda la configuración en la BD. | ||||
|   /// </summary> | ||||
|   /// <param name="request">Un objeto que contiene el nuevo nivel de logging.</param> | ||||
|   [HttpPut("logging-level")] | ||||
|   public async Task<IActionResult> UpdateLoggingLevel([FromBody] UpdateLoggingLevelRequest request) | ||||
|   { | ||||
|     if (string.IsNullOrWhiteSpace(request.Level)) | ||||
|     { | ||||
|       return BadRequest("El nivel de logging no puede estar vacío."); | ||||
|     } | ||||
|  | ||||
|     // 1. Intentamos actualizar el interruptor de Serilog en memoria. | ||||
|     bool success = _loggingSwitchService.SetLoggingLevel(request.Level); | ||||
|  | ||||
|     if (!success) | ||||
|     { | ||||
|       return BadRequest($"El nivel de logging '{request.Level}' no es válido. Los valores posibles son: Verbose, Debug, Information, Warning, Error, Fatal."); | ||||
|     } | ||||
|  | ||||
|     // 2. Si el cambio fue exitoso, guardamos el nuevo valor en la base de datos. | ||||
|     var config = await _dbContext.Configuraciones.FindAsync("Logging_Level"); | ||||
|     if (config == null) | ||||
|     { | ||||
|       _dbContext.Configuraciones.Add(new Configuracion { Clave = "Logging_Level", Valor = request.Level }); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       config.Valor = request.Level; | ||||
|     } | ||||
|  | ||||
|     await _dbContext.SaveChangesAsync(); | ||||
|  | ||||
|     _logger.LogWarning("El nivel de logging ha sido cambiado a: {Level}", request.Level); | ||||
|     return Ok(new { message = $"Nivel de logging actualizado a '{request.Level}'." }); | ||||
|   } | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| //Elecciones.Api/Program.cs | ||||
| using Elecciones.Database; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Serilog; | ||||
| @@ -13,13 +14,24 @@ using Microsoft.AspNetCore.HttpOverrides; | ||||
| // Esta es la estructura estándar y recomendada. | ||||
| var builder = WebApplication.CreateBuilder(args); | ||||
|  | ||||
| // 1. Configurar Serilog. Esta es la forma correcta de integrarlo. | ||||
| builder.Host.UseSerilog((context, services, configuration) => configuration | ||||
|     .ReadFrom.Configuration(context.Configuration) | ||||
|     .ReadFrom.Services(services) | ||||
|     .Enrich.FromLogContext() | ||||
|     .WriteTo.Console() | ||||
|     .WriteTo.File("logs/api-.log", rollingInterval: RollingInterval.Day)); | ||||
| // 1. Registra el servicio del interruptor como un Singleton. | ||||
| //    Esto asegura que toda la aplicación comparta la MISMA instancia del interruptor. | ||||
| builder.Services.AddSingleton<LoggingSwitchService>(); | ||||
|  | ||||
| builder.Host.UseSerilog((context, services, configuration) => | ||||
| { | ||||
|     // 2. Obtenemos la instancia del interruptor que acabamos de registrar. | ||||
|     var loggingSwitch = services.GetRequiredService<LoggingSwitchService>(); | ||||
|  | ||||
|     configuration | ||||
|         .ReadFrom.Configuration(context.Configuration) | ||||
|         .ReadFrom.Services(services) | ||||
|         .Enrich.FromLogContext() | ||||
|         // 3. Establecemos el nivel mínimo de logging controlado por el interruptor. | ||||
|         .MinimumLevel.ControlledBy(loggingSwitch.LevelSwitch) | ||||
|         .WriteTo.Console() | ||||
|         .WriteTo.File("logs/api-.log", rollingInterval: RollingInterval.Day); // o "logs/worker-.log" | ||||
| }); | ||||
|  | ||||
| // 2. Añadir servicios al contenedor. | ||||
| var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); | ||||
| @@ -83,6 +95,34 @@ builder.Services.Configure<ForwardedHeadersOptions>(options => | ||||
| // 3. Construir la aplicación. | ||||
| var app = builder.Build(); | ||||
|  | ||||
| // --- LÓGICA PARA LEER EL NIVEL DE LOGGING AL INICIO --- | ||||
| // Creamos un scope temporal para leer la configuración de la BD | ||||
| using (var scope = app.Services.CreateScope()) // O 'host.Services.CreateScope()' | ||||
| { | ||||
|     var services = scope.ServiceProvider; | ||||
|     try | ||||
|     { | ||||
|         // El resto de la lógica no cambia | ||||
|         var dbContext = services.GetRequiredService<EleccionesDbContext>(); | ||||
|         var loggingSwitchService = services.GetRequiredService<LoggingSwitchService>(); | ||||
|  | ||||
|         var logLevelConfig = await dbContext.Configuraciones | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(c => c.Clave == "Logging_Level"); | ||||
|  | ||||
|         if (logLevelConfig != null) | ||||
|         { | ||||
|             loggingSwitchService.SetLoggingLevel(logLevelConfig.Valor); | ||||
|             Console.WriteLine($"--> Nivel de logging inicial establecido desde la BD a: {logLevelConfig.Valor}"); | ||||
|         } | ||||
|     } | ||||
|     catch (Exception ex) | ||||
|     { | ||||
|         // Si hay un error (ej. la BD no está disponible al arrancar), se usará el nivel por defecto 'Information'. | ||||
|         Console.WriteLine($"--> No se pudo establecer el nivel de logging desde la BD: {ex.Message}"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| app.UseForwardedHeaders(); | ||||
|  | ||||
| // Seeder para el usuario admin | ||||
| @@ -150,19 +190,29 @@ using (var scope = app.Services.CreateScope()) | ||||
| { | ||||
|     var services = scope.ServiceProvider; | ||||
|     var context = services.GetRequiredService<EleccionesDbContext>(); | ||||
|     if (!context.Configuraciones.Any(c => c.Clave == "MostrarOcupantes")) | ||||
|  | ||||
|     // Lista de configuraciones por defecto a asegurar | ||||
|     var defaultConfiguraciones = new Dictionary<string, string> | ||||
|     { | ||||
|         context.Configuraciones.Add(new Configuracion { Clave = "MostrarOcupantes", Valor = "true" }); | ||||
|         context.SaveChanges(); | ||||
|         Console.WriteLine("--> Seeded default configuration 'MostrarOcupantes'."); | ||||
|     } | ||||
|     if (!context.Configuraciones.Any(c => c.Clave == "TickerResultadosCantidad")) | ||||
|         { "MostrarOcupantes", "true" }, | ||||
|         { "TickerResultadosCantidad", "3" }, | ||||
|         { "ConcejalesResultadosCantidad", "5" }, | ||||
|         { "Worker_Resultados_Activado", "false" }, | ||||
|         { "Worker_Bajas_Activado", "false" }, | ||||
|         { "Worker_Prioridad", "Resultados" }, | ||||
|         { "Logging_Level", "Information" } | ||||
|     }; | ||||
|  | ||||
|     foreach (var config in defaultConfiguraciones) | ||||
|     { | ||||
|         context.Configuraciones.Add(new Configuracion { Clave = "TickerResultadosCantidad", Valor = "3" }); | ||||
|         context.Configuraciones.Add(new Configuracion { Clave = "ConcejalesResultadosCantidad", Valor = "5" }); | ||||
|         context.SaveChanges(); | ||||
|         Console.WriteLine("--> Seeded default configuration 'TickerResultadosCantidad'."); | ||||
|         if (!context.Configuraciones.Any(c => c.Clave == config.Key)) | ||||
|         { | ||||
|             context.Configuraciones.Add(new Configuracion { Clave = config.Key, Valor = config.Value }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     context.SaveChanges(); | ||||
|     Console.WriteLine("--> Seeded default configurations."); | ||||
| } | ||||
|  | ||||
| // Configurar el pipeline de peticiones HTTP. | ||||
|   | ||||
| @@ -859,17 +859,17 @@ | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog/4.2.0": { | ||||
|       "Serilog/4.3.0": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.dll": { | ||||
|             "assemblyVersion": "4.2.0.0", | ||||
|             "fileVersion": "4.2.0.0" | ||||
|             "assemblyVersion": "4.3.0.0", | ||||
|             "fileVersion": "4.3.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.AspNetCore/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0", | ||||
|           "Serilog": "4.3.0", | ||||
|           "Serilog.Extensions.Hosting": "9.0.0", | ||||
|           "Serilog.Formatting.Compact": "3.0.0", | ||||
|           "Serilog.Settings.Configuration": "9.0.0", | ||||
| @@ -889,7 +889,7 @@ | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Hosting.Abstractions": "9.0.0", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8", | ||||
|           "Serilog": "4.2.0", | ||||
|           "Serilog": "4.3.0", | ||||
|           "Serilog.Extensions.Logging": "9.0.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
| @@ -902,7 +902,7 @@ | ||||
|       "Serilog.Extensions.Logging/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Logging": "9.0.8", | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Extensions.Logging.dll": { | ||||
| @@ -913,7 +913,7 @@ | ||||
|       }, | ||||
|       "Serilog.Formatting.Compact/3.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Formatting.Compact.dll": { | ||||
| @@ -926,7 +926,7 @@ | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Binder": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyModel": "9.0.8", | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Settings.Configuration.dll": { | ||||
| @@ -937,7 +937,7 @@ | ||||
|       }, | ||||
|       "Serilog.Sinks.Console/6.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Sinks.Console.dll": { | ||||
| @@ -948,7 +948,7 @@ | ||||
|       }, | ||||
|       "Serilog.Sinks.Debug/3.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Sinks.Debug.dll": { | ||||
| @@ -959,7 +959,7 @@ | ||||
|       }, | ||||
|       "Serilog.Sinks.File/7.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|           "Serilog": "4.3.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Sinks.File.dll": { | ||||
| @@ -1294,8 +1294,10 @@ | ||||
|       "Elecciones.Infrastructure/1.0.0": { | ||||
|         "dependencies": { | ||||
|           "Elecciones.Core": "1.0.0", | ||||
|           "Elecciones.Database": "1.0.0", | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Http": "9.0.8", | ||||
|           "Serilog": "4.3.0", | ||||
|           "System.Threading.RateLimiting": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
| @@ -1691,12 +1693,12 @@ | ||||
|       "path": "mono.texttemplating/3.0.0", | ||||
|       "hashPath": "mono.texttemplating.3.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog/4.2.0": { | ||||
|     "Serilog/4.3.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-gmoWVOvKgbME8TYR+gwMf7osROiWAURterc6Rt2dQyX7wtjZYpqFiA/pY6ztjGQKKV62GGCyOcmtP1UKMHgSmA==", | ||||
|       "path": "serilog/4.2.0", | ||||
|       "hashPath": "serilog.4.2.0.nupkg.sha512" | ||||
|       "sha512": "sha512-+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ==", | ||||
|       "path": "serilog/4.3.0", | ||||
|       "hashPath": "serilog.4.3.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.AspNetCore/9.0.0": { | ||||
|       "type": "package", | ||||
|   | ||||
| @@ -14,7 +14,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d78a02a0ebc4c70ea01e48821db963110e7ce280")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f384a640f36be1289d652dc85e78ebdcef30968a")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Kt4ImnGs0wklEJp/6NxrhrTvGLQxPfYUAB5LMWAnz10=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v1SBeIVg8rE3EddYwnvF/EsPYr2F5GAppt/Egvdtr/0="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","UucupTplk47jbYuQLLfpsVglReDmh1hUE6oD0OEv\u002BsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nor5YuoHu4p8qlladsJ2COw4pycCja0XN1sckUrKV/w="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Kt4ImnGs0wklEJp/6NxrhrTvGLQxPfYUAB5LMWAnz10=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v1SBeIVg8rE3EddYwnvF/EsPYr2F5GAppt/Egvdtr/0="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","UucupTplk47jbYuQLLfpsVglReDmh1hUE6oD0OEv\u002BsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nor5YuoHu4p8qlladsJ2COw4pycCja0XN1sckUrKV/w="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -287,6 +287,9 @@ | ||||
|             "projectReferences": { | ||||
|               "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj": { | ||||
|                 "projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj" | ||||
|               }, | ||||
|               "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj": { | ||||
|                 "projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj" | ||||
|               } | ||||
|             } | ||||
|           } | ||||
| @@ -315,6 +318,10 @@ | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.8, )" | ||||
|             }, | ||||
|             "Serilog": { | ||||
|               "target": "Package", | ||||
|               "version": "[4.3.0, )" | ||||
|             }, | ||||
|             "System.Threading.RateLimiting": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.8, )" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user