feat: implement core domain models, authentication service, and UI components for the attendance system

This commit is contained in:
2026-07-31 14:39:25 -04:00
commit f476f704eb
329 changed files with 12622 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
{}
+201
View File
@@ -0,0 +1,201 @@
# INFORME DE AUDITORÍA
## Proyecto Desktop: Asistencia (Avalonia UI)
**Ruta:** `/home/juan/dev/asistencia-desktop/`
**Referencia (guía):** `/home/juan/dev/sam/Profesores/` (Módulo Profesores SAM)
---
## 1. RESUMEN EJECUTIVO
| Aspecto | Desktop App (Asistencia) | SAM Profesores (guía) |
|---------|------------------------|----------------------|
| **Framework** | Avalonia UI + .NET 10 | ASP.NET WebForms .NET 4.8.1 |
| **Base de datos** | SQLite local (aislada) | MariaDB remota (AWS EC2) |
| **Tipo de app** | Desktop (Windows/Linux/macOS) | Web |
| **Estado** | Prototipo inicial - solo 4 vistas | Completo - 11 páginas |
| **Conexión SAM** | No conecta | Sí, via SPs |
---
## 2. ESTRUCTURA DEL PROYECTO DESKTOP
```
asistencia-desktop/
├── Asistencia.slnx
├── Asistencia/
│ ├── Asistencia.csproj (.NET 10 + Avalonia 12.1.1 + SQLite + DI)
│ ├── Program.cs (entry point clásico Avalonia)
│ ├── App.axaml / App.axaml.cs (DI: DbContext, Repos, Services, ViewModels)
│ ├── ViewLocator.cs
│ ├── app.manifest
│ ├── Models/ (7 entidades)
│ │ ├── Profesor.cs
│ │ ├── Curso.cs
│ │ ├── CursoAbierto.cs
│ │ ├── DetalleContrato.cs
│ │ ├── AsistenciaProfesor.cs
│ │ ├── AsistenciaAlumno.cs
│ │ └── TipoAsistencia.cs
│ ├── Data/
│ │ ├── AppDbContext.cs (SQLite + SeedData)
│ │ └── Repositories/
│ │ ├── ProfesorRepository.cs
│ │ ├── CursoRepository.cs
│ │ └── AsistenciaRepository.cs
│ ├── Services/
│ │ ├── AuthService.cs (login, crear clave, cambiar clave, email)
│ │ └── AsistenciaService.cs (iniciar/finalizar sesión, asistencia alumnos)
│ ├── Helpers/
│ │ └── CryptoHelper.cs (AES key hardcodeada)
│ ├── ViewModels/
│ │ ├── MainWindowViewModel.cs (navegación: Login→Dashboard→Asistencia→Perfil)
│ │ ├── LoginViewModel.cs
│ │ ├── DashboardViewModel.cs
│ │ ├── AsistenciaViewModel.cs (incluye AlumnoAsistenciaViewModel)
│ │ └── PerfilViewModel.cs
│ └── Views/
│ ├── MainWindow.axaml
│ ├── LoginView.axaml
│ ├── DashboardView.axaml
│ ├── AsistenciaView.axaml
│ └── PerfilView.axaml
```
---
## 3. FUNCIONALIDAD IMPLEMENTADA VS. GUÍA (SAM PROFESORES)
| # | Funcionalidad | Desktop App | SAM Profesores | Estado |
|---|--------------|-------------|----------------|--------|
| 1 | **Login / Autenticación** | ✅ SQLite local | ✅ FormsAuth + MariaDB | **Completo** |
| 2 | **Crear clave primera vez** | ✅ Implementado | ✅ CrearClave.aspx | **Completo** |
| 3 | **Dashboard (lista cursos)** | ✅ Básico | ✅ Index.aspx | **Completo** |
| 4 | **Iniciar clase (marcación)** | ✅ SQLite local | ✅ MariaDB + IP validation | **⚠ Parcial** |
| 5 | **Tomar asistencia alumnos** | ✅ P/L/A radio buttons | ✅ P/L/A radio buttons | **Completo** |
| 6 | **Finalizar clase** | ✅ | ✅ | **Completo** |
| 7 | **Perfil (email, clave)** | ✅ | ✅ Profile.aspx | **Completo** |
| 8 | **Ver sesiones y pagos** | ❌ No implementado | ✅ Sesiones.aspx | **FALTANTE** |
| 9 | **Notas / Calificaciones** | ❌ No implementado | ✅ Notas.aspx (CA, MWT, MOT, FOT, FWT) | **FALTANTE** |
| 10 | **Reportes por curso** | ❌ No implementado | ✅ Reports.aspx | **FALTANTE** |
| 11 | **Reemplazo de profesor** | ❌ No implementado | ✅ Reemplazo.aspx | **FALTANTE** |
| 12 | **Contenido del curso (bitácora)** | ❌ No implementado | ✅ Contenido.aspx | **FALTANTE** |
| 13 | **Validación IP/sede** | ❌ No implementado | ✅ Attendance.aspx (IP whitelist) | **FALTANTE** |
| 14 | **Notificaciones email** | ❌ No implementado | ✅ Mails.cs (reemplazos, sedes) | **FALTANTE** |
| 15 | **Soporte múltiples schemas** (abierto/cerrado) | ❌ No implementado | ✅ Plan Central + Empresa | **FALTANTE** |
| 16 | **Olvido de clave** | ❌ No implementado | ✅ OlvidoClave.aspx | **FALTANTE** |
---
## 4. HALLAZGOS CRÍTICOS
### 4.1 Base de datos aislada (SQLite local)
La desktop app usa SQLite local con datos de prueba (seed data). **No se conecta a la base de datos real SAM (MariaDB)**. Esto significa que:
- Los profesores no pueden ver sus cursos reales
- Las marcaciones no quedan registradas en el sistema SAM
- Los datos de asistencia de alumnos no se sincronizan
- No hay integración con el módulo de pagos (RRHH)
**Solución:** Reemplazar SQLite por conexión directa a MariaDB usando las mismas stored procedures que usa el módulo SAM Profesores (sam.BuscarCursoProfesor, sam.IngresoAsistenciaProfesor, etc.)
### 4.2 Seguridad: Encriptación AES con clave hardcodeada
Ambos proyectos comparten la misma vulnerabilidad:
```
Clave AES: "S4M_Pru3b4_2024!"
IV: new byte[16] (ceros estáticos)
Modo: CBC
```
La clave está hardcodeada en el código fuente (`CryptoHelper.cs` y `Seguridad.cs`). Un atacante con acceso al binario o al código puede desencriptar todas las contraseñas de los profesores.
**Recomendación:** Usar hash con salt (bcrypt/argon2) en lugar de encriptación reversible, o al menos mover la clave a una variable de entorno/configuración segura.
### 4.3 Sin validación de IP/Sede
La app SAM actual valida que el profesor solo pueda iniciar clases desde las IPs de la red del instituto:
```csharp
string[] IPsPermitidas = { "200.68.55.74", "200.54.121.26", "181.212.110.122", "127.0.0.1", "::1" };
```
Y para sedes ONLINE/EMPRESAS omite esta validación. La desktop app **no tiene ninguna validación**, lo que permite iniciar clases desde cualquier lugar.
**Recomendación:** La carta que se generó previamente (sobre inicio solo desde sedes físicas) debería reflejarse aquí: validar que el equipo esté en la red de una sede física autorizada.
### 4.4 Sin soporte para schemas múltiples
SAM maneja dos orígenes de datos:
- **Plan Central** (schema `sige_sam_V3`) — cursos regulares
- **Empresa** (schema `sige_sam_empresa`) — cursos cerrados
La desktop app no diferencia entre ambos.
### 4.5 Sin ciclo de vida de sesión completo
En SAM, cuando se finaliza una clase se registra `HoraSalida` y se cambia `Estado = 'Finalizada'`. La desktop hace lo mismo localmente, pero no hay registro del período de pago (21→20), ni se calculan horas para RRHH.
### 4.6 Modelo AsistenciaProfesor tiene campo `Temporal` no usado
El modelo `AsistenciaProfesor` tiene un campo `Temporal` (bool, default false) que no se utiliza en ninguna parte del código. En SAM este campo se usa para identificar reemplazos (`temporal = 1`).
### 4.7 Sin View ni ViewModel para Sesiones, Notas, Reportes, Reemplazo, Contenido
Faltan **5 vistas completas** para igualar la funcionalidad del módulo SAM.
---
## 5. COMPARATIVA ARQUITECTÓNICA
### SAM Profesores (WebForms)
```
Web (aspx.cs) → Negocio (NProfesor, NCurso, Seguridad, Mails) → Datos (Conexion MariaDB, Profesor.cs, Curso.cs)
```
### Desktop App (Avalonia)
```
Views (axaml) → ViewModels → Services (AuthService, AsistenciaService) → Repositories → AppDbContext (SQLite)
```
Ambos usan una arquitectura en capas similar, pero el desktop reemplaza la capa de datos MariaDB por SQLite local.
---
## 6. PENDIENTE PARA COMPILAR MULTIPLATAFORMA
Antes de compilar para Windows, macOS y Linux (deb + Arch), se debe:
### 6.1 Funcional (para igualar la guía SAM)
1. Conectar a MariaDB real (replicar stored procedures)
2. Implementar validación de IP/Sede (inicio solo desde sedes físicas)
3. Agregar vistas: Sesiones (pagos), Notas, Reportes, Reemplazo, Contenido
4. Agregar notificaciones por email
5. Soportar schemas Plan Central y Empresa
### 6.2 Técnico
1. Corregir seguridad de contraseñas (bcrypt/argon2)
2. Mover configuración sensible a variables de entorno o archivo de configuración
3. Agregar `RuntimeIdentifiers` en `.csproj` para publicación multiplataforma
4. Probar compilación con:
- `dotnet publish -c Release -r win-x64 --self-contained`
- `dotnet publish -c Release -r linux-x64 --self-contained`
- `dotnet publish -c Release -r osx-x64 --self-contained`
5. Para empaquetado:
- **Windows**: NSIS o Inno Setup (o .exe directo)
- **Linux .deb**: `dotnet publish` + `dpkg-deb` para crear .deb
- **Linux Arch**: PKGBUILD para AUR/local
- **macOS**: .app bundle o .dmg
---
## 7. CONCLUSIÓN
La desktop app es un **prototipo funcional** con las 4 vistas básicas (login, dashboard, asistencia, perfil) pero que **actualmente opera en aislamiento** con SQLite local. No reemplaza al sistema SAM real porque:
1. No está conectada a la base de datos de producción
2. Le falta más de la mitad de la funcionalidad del módulo Profesores SAM
3. Carece de las validaciones de seguridad y sede que el sistema actual tiene
**Para producción:** Se requiere conectar a MariaDB (usando las mismas SPs), agregar las vistas faltantes, e implementar las validaciones de IP/sede antes de distribuir ejecutables a los profesores.
+3
View File
@@ -0,0 +1,3 @@
<Solution>
<Project Path="Asistencia/Asistencia.csproj" />
</Solution>
+33
View File
@@ -0,0 +1,33 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Asistencia.App"
xmlns:local="using:Asistencia"
RequestedThemeVariant="Light">
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
<Application.Resources>
<SolidColorBrush x:Key="PrimaryNavy" Color="#00285d" />
<SolidColorBrush x:Key="PrimaryNavyLight" Color="#004a9e" />
<SolidColorBrush x:Key="PrimaryBlue" Color="#4A90D9" />
<SolidColorBrush x:Key="SuccessColor" Color="#28A745" />
<SolidColorBrush x:Key="WarningColor" Color="#FFC107" />
<SolidColorBrush x:Key="DangerColor" Color="#DC3545" />
<SolidColorBrush x:Key="InfoColor" Color="#17A2B8" />
<SolidColorBrush x:Key="BackgroundPrimary" Color="#FFFFFF" />
<SolidColorBrush x:Key="BackgroundSecondary" Color="#F5F7FA" />
<SolidColorBrush x:Key="BackgroundDark" Color="#1E1E2E" />
<SolidColorBrush x:Key="TextPrimary" Color="#212529" />
<SolidColorBrush x:Key="TextSecondary" Color="#6C757D" />
<SolidColorBrush x:Key="TextOnPrimary" Color="#FFFFFF" />
<SolidColorBrush x:Key="TextMuted" Color="#ADB5BD" />
<SolidColorBrush x:Key="BorderColor" Color="#DEE2E6" />
</Application.Resources>
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Asistencia/Styles/Cards.axaml" />
</Application.Styles>
</Application>
+51
View File
@@ -0,0 +1,51 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Asistencia.ViewModels;
using Asistencia.Views;
using Asistencia.Data;
using Asistencia.Data.Repositories;
using Asistencia.Services;
using Microsoft.Extensions.DependencyInjection;
namespace Asistencia;
public partial class App : Application
{
public static IServiceProvider? Services { get; private set; }
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var services = new ServiceCollection();
services.AddDbContext<AppDbContext>();
services.AddSingleton<ProfesorRepository>();
services.AddSingleton<CursoRepository>();
services.AddSingleton<AsistenciaRepository>();
services.AddSingleton<AuthService>();
services.AddSingleton<AsistenciaService>();
services.AddSingleton<MainWindowViewModel>();
Services = services.BuildServiceProvider();
using var scope = Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Database.EnsureCreated();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var vm = Services.GetRequiredService<MainWindowViewModel>();
desktop.MainWindow = new MainWindow
{
DataContext = vm
};
}
base.OnFrameworkInitializationCompleted();
}
}
+32
View File
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\" />
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="12.1.1" />
<PackageReference Include="Avalonia.Desktop" Version="12.1.1" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.1.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.1.1" />
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.10" />
</ItemGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

+139
View File
@@ -0,0 +1,139 @@
using Microsoft.EntityFrameworkCore;
using Asistencia.Models;
namespace Asistencia.Data;
public class AppDbContext : DbContext
{
public DbSet<Profesor> Profesores => Set<Profesor>();
public DbSet<Curso> Cursos => Set<Curso>();
public DbSet<CursoAbierto> CursosAbiertos => Set<CursoAbierto>();
public DbSet<DetalleContrato> DetallesContrato => Set<DetalleContrato>();
public DbSet<AsistenciaProfesor> AsistenciasProfesor => Set<AsistenciaProfesor>();
public DbSet<AsistenciaAlumno> AsistenciasAlumno => Set<AsistenciaAlumno>();
public string DbPath { get; }
public AppDbContext()
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var appFolder = Path.Combine(folder, "Asistencia");
Directory.CreateDirectory(appFolder);
DbPath = Path.Combine(appFolder, "asistencia.db");
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CursoAbierto>()
.HasOne(c => c.Curso)
.WithMany()
.HasForeignKey(c => c.IdCursos);
modelBuilder.Entity<DetalleContrato>()
.HasOne(d => d.CursoAbierto)
.WithMany()
.HasForeignKey(d => d.IdCursoAbierto);
modelBuilder.Entity<AsistenciaProfesor>()
.HasOne(a => a.CursoAbierto)
.WithMany()
.HasForeignKey(a => a.IdCursoAbierto);
modelBuilder.Entity<AsistenciaAlumno>()
.HasKey(a => new { a.IdDetalleContrato, a.FechaAsistencia });
modelBuilder.Entity<AsistenciaAlumno>()
.HasOne(a => a.DetalleContrato)
.WithMany()
.HasForeignKey(a => a.IdDetalleContrato);
SeedData(modelBuilder);
}
private static void SeedData(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Profesor>().HasData(
new Profesor
{
RutPasaporte = "12345678-9",
Nombre = "Juan",
Paterno = "Perez",
Materno = "Gonzalez",
Email = "juan.perez@norteamericano.cl",
Fono = "+56912345678",
Direccion = "Av. Providencia 1234, Santiago",
Clave = "",
CrearClave = true
}
);
modelBuilder.Entity<Curso>().HasData(
new Curso { IdCursos = 1, NombreCurso = "English Basic A1" },
new Curso { IdCursos = 2, NombreCurso = "English Intermediate B1" },
new Curso { IdCursos = 3, NombreCurso = "English Advanced C1" }
);
modelBuilder.Entity<CursoAbierto>().HasData(
new CursoAbierto
{
IdCursoAbierto = 1,
IdCursos = 1,
Sala = "Sala 101",
Sede = "Providencia",
HoraInicio = "09:00",
HoraFin = "10:30",
FechaInicio = new DateTime(2026, 3, 1),
FechaTermino = new DateTime(2026, 7, 31),
ProfesorRun = "12345678-9"
},
new CursoAbierto
{
IdCursoAbierto = 2,
IdCursos = 2,
Sala = "Sala 202",
Sede = "Las Condes",
HoraInicio = "14:00",
HoraFin = "15:30",
FechaInicio = new DateTime(2026, 3, 1),
FechaTermino = new DateTime(2026, 7, 31),
ProfesorRun = "12345678-9"
}
);
modelBuilder.Entity<DetalleContrato>().HasData(
new DetalleContrato
{
IdDetalleContrato = 1,
IdCursoAbierto = 1,
AP_Paterno = "Garcia",
AP_Materno = "Lopez",
Nombres = "Maria",
Email = "maria.garcia@email.com",
Telefono = "+56998765432"
},
new DetalleContrato
{
IdDetalleContrato = 2,
IdCursoAbierto = 1,
AP_Paterno = "Rodriguez",
AP_Materno = "Soto",
Nombres = "Carlos",
Email = "carlos.rodriguez@email.com",
Telefono = "+56987654321"
},
new DetalleContrato
{
IdDetalleContrato = 3,
IdCursoAbierto = 2,
AP_Paterno = "Martinez",
AP_Materno = "Fernandez",
Nombres = "Ana",
Email = "ana.martinez@email.com",
Telefono = "+56976543210"
}
);
}
}
@@ -0,0 +1,88 @@
using Microsoft.EntityFrameworkCore;
using Asistencia.Models;
namespace Asistencia.Data.Repositories;
public class AsistenciaRepository
{
private readonly AppDbContext _context;
public AsistenciaRepository(AppDbContext context)
{
_context = context;
}
public async Task<AsistenciaProfesor?> BuscarSesionActivaAsync(int idCursoAbierto, DateTime fecha)
{
return await _context.AsistenciasProfesor
.FirstOrDefaultAsync(a =>
a.IdCursoAbierto == idCursoAbierto &&
a.FechaAsistencia.Date == fecha.Date &&
a.Estado == "Activa");
}
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut, DateTime fecha, string horaInicio)
{
var sesion = new AsistenciaProfesor
{
IdCursoAbierto = idCursoAbierto,
RutPasaporte = rut,
FechaAsistencia = fecha,
HoraInicio = horaInicio,
Estado = "Activa"
};
_context.AsistenciasProfesor.Add(sesion);
await _context.SaveChangesAsync();
return sesion;
}
public async Task<bool> FinalizarSesionAsync(int idSesion, string horaFin)
{
var sesion = await _context.AsistenciasProfesor.FindAsync(idSesion);
if (sesion == null) return false;
sesion.HoraFin = horaFin;
sesion.Estado = "Finalizada";
await _context.SaveChangesAsync();
return true;
}
public async Task<Dictionary<int, int>> ObtenerAsistenciaAlumnosAsync(int idCursoAbierto, DateTime fecha)
{
var alumnos = await _context.DetallesContrato
.Where(d => d.IdCursoAbierto == idCursoAbierto)
.ToListAsync();
var asistencias = await _context.AsistenciasAlumno
.Where(a => alumnos.Select(al => al.IdDetalleContrato).Contains(a.IdDetalleContrato)
&& a.FechaAsistencia.Date == fecha.Date)
.ToListAsync();
return asistencias.ToDictionary(a => a.IdDetalleContrato, a => a.IdTipoAsistencia);
}
public async Task GuardarAsistenciaAlumnoAsync(int idDetalleContrato, DateTime fecha, string hora, int tipoAsistencia)
{
var existing = await _context.AsistenciasAlumno
.FirstOrDefaultAsync(a => a.IdDetalleContrato == idDetalleContrato
&& a.FechaAsistencia.Date == fecha.Date);
if (existing != null)
{
existing.IdTipoAsistencia = tipoAsistencia;
existing.Hora = hora;
}
else
{
_context.AsistenciasAlumno.Add(new AsistenciaAlumno
{
IdDetalleContrato = idDetalleContrato,
FechaAsistencia = fecha,
Hora = hora,
IdTipoAsistencia = tipoAsistencia
});
}
await _context.SaveChangesAsync();
}
}
@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore;
using Asistencia.Models;
namespace Asistencia.Data.Repositories;
public class CursoRepository
{
private readonly AppDbContext _context;
public CursoRepository(AppDbContext context)
{
_context = context;
}
public async Task<List<CursoAbierto>> BuscarCursosPorProfesorAsync(string profesorRun)
{
return await _context.CursosAbiertos
.Include(c => c.Curso)
.Where(c => c.ProfesorRun == profesorRun)
.ToListAsync();
}
public async Task<CursoAbierto?> BuscarCursoAbiertoPorIdAsync(int idCursoAbierto)
{
return await _context.CursosAbiertos
.Include(c => c.Curso)
.FirstOrDefaultAsync(c => c.IdCursoAbierto == idCursoAbierto);
}
public async Task<List<DetalleContrato>> BuscarAlumnosPorCursoAsync(int idCursoAbierto)
{
return await _context.DetallesContrato
.Where(d => d.IdCursoAbierto == idCursoAbierto)
.ToListAsync();
}
}
@@ -0,0 +1,51 @@
using Microsoft.EntityFrameworkCore;
using Asistencia.Models;
namespace Asistencia.Data.Repositories;
public class ProfesorRepository
{
private readonly AppDbContext _context;
public ProfesorRepository(AppDbContext context)
{
_context = context;
}
public async Task<Profesor?> BuscarPorRutAsync(string rut)
{
return await _context.Profesores.FirstOrDefaultAsync(p => p.RutPasaporte == rut);
}
public async Task<bool> ActualizarClaveAsync(string rut, string nuevaClave)
{
var profesor = await _context.Profesores.FirstOrDefaultAsync(p => p.RutPasaporte == rut);
if (profesor == null) return false;
profesor.Clave = nuevaClave;
profesor.CrearClave = false;
await _context.SaveChangesAsync();
return true;
}
public async Task<bool> ActualizarEmailAsync(string rut, string email)
{
var profesor = await _context.Profesores.FirstOrDefaultAsync(p => p.RutPasaporte == rut);
if (profesor == null) return false;
profesor.Email = email;
await _context.SaveChangesAsync();
return true;
}
public async Task<Profesor?> AutenticarAsync(string rut, string clave)
{
var profesor = await _context.Profesores.FirstOrDefaultAsync(p => p.RutPasaporte == rut);
if (profesor == null) return null;
if (profesor.CrearClave) return null;
var claveDescifrada = Helpers.CryptoHelper.Desencriptar(profesor.Clave);
return claveDescifrada == clave ? profesor : null;
}
}
+44
View File
@@ -0,0 +1,44 @@
using System.Security.Cryptography;
using System.Text;
namespace Asistencia.Helpers;
public static class CryptoHelper
{
private static readonly byte[] Key = Encoding.UTF8.GetBytes("S4M_Pru3b4_2024!");
private static readonly byte[] IV = new byte[16];
public static string Encriptar(string texto)
{
using var aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using var encryptor = aes.CreateEncryptor();
using var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var writer = new StreamWriter(cs))
{
writer.Write(texto);
}
return Convert.ToBase64String(ms.ToArray());
}
public static string Desencriptar(string textoEncriptado)
{
using var aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
var buffer = Convert.FromBase64String(textoEncriptado);
using var decryptor = aes.CreateDecryptor();
using var ms = new MemoryStream(buffer);
using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
using var reader = new StreamReader(cs);
return reader.ReadToEnd();
}
}
+17
View File
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class AsistenciaAlumno
{
public int IdDetalleContrato { get; set; }
public DateTime FechaAsistencia { get; set; }
[MaxLength(10)]
public string Hora { get; set; } = string.Empty;
public int IdTipoAsistencia { get; set; } = 3;
public DetalleContrato? DetalleContrato { get; set; }
}
+29
View File
@@ -0,0 +1,29 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class AsistenciaProfesor
{
[Key]
public int Id { get; set; }
public int IdCursoAbierto { get; set; }
[MaxLength(20)]
public string RutPasaporte { get; set; } = string.Empty;
public DateTime FechaAsistencia { get; set; }
[MaxLength(10)]
public string HoraInicio { get; set; } = string.Empty;
[MaxLength(10)]
public string HoraFin { get; set; } = string.Empty;
[MaxLength(20)]
public string Estado { get; set; } = "Activa";
public bool Temporal { get; set; }
public CursoAbierto? CursoAbierto { get; set; }
}
+12
View File
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class Curso
{
[Key]
public int IdCursos { get; set; }
[MaxLength(200)]
public string NombreCurso { get; set; } = string.Empty;
}
+32
View File
@@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class CursoAbierto
{
[Key]
public int IdCursoAbierto { get; set; }
public int IdCursos { get; set; }
[MaxLength(50)]
public string Sala { get; set; } = string.Empty;
[MaxLength(100)]
public string Sede { get; set; } = string.Empty;
[MaxLength(10)]
public string HoraInicio { get; set; } = string.Empty;
[MaxLength(10)]
public string HoraFin { get; set; } = string.Empty;
public DateTime FechaInicio { get; set; }
public DateTime FechaTermino { get; set; }
[MaxLength(20)]
public string ProfesorRun { get; set; } = string.Empty;
public Curso? Curso { get; set; }
}
+30
View File
@@ -0,0 +1,30 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class DetalleContrato
{
[Key]
public int IdDetalleContrato { get; set; }
public int IdCursoAbierto { get; set; }
[MaxLength(100)]
public string AP_Paterno { get; set; } = string.Empty;
[MaxLength(100)]
public string AP_Materno { get; set; } = string.Empty;
[MaxLength(100)]
public string Nombres { get; set; } = string.Empty;
[MaxLength(200)]
public string Email { get; set; } = string.Empty;
[MaxLength(20)]
public string Telefono { get; set; } = string.Empty;
public CursoAbierto? CursoAbierto { get; set; }
public string NombreCompleto => $"{Nombres} {AP_Paterno} {AP_Materno}".Trim();
}
+35
View File
@@ -0,0 +1,35 @@
using System.ComponentModel.DataAnnotations;
namespace Asistencia.Models;
public class Profesor
{
[Key]
[MaxLength(20)]
public string RutPasaporte { get; set; } = string.Empty;
[MaxLength(100)]
public string Nombre { get; set; } = string.Empty;
[MaxLength(100)]
public string Paterno { get; set; } = string.Empty;
[MaxLength(100)]
public string Materno { get; set; } = string.Empty;
[MaxLength(200)]
public string Email { get; set; } = string.Empty;
[MaxLength(20)]
public string Fono { get; set; } = string.Empty;
[MaxLength(300)]
public string Direccion { get; set; } = string.Empty;
[MaxLength(500)]
public string Clave { get; set; } = string.Empty;
public bool CrearClave { get; set; }
public string NombreCompleto => $"{Nombre} {Paterno} {Materno}".Trim();
}
+16
View File
@@ -0,0 +1,16 @@
namespace Asistencia.Models;
public static class TipoAsistencia
{
public const int Presente = 1;
public const int Tardanza = 2;
public const int Ausente = 3;
public static string Nombre(int id) => id switch
{
Presente => "Presente",
Tardanza => "Tardanza",
Ausente => "Ausente",
_ => "Desconocido"
};
}
+24
View File
@@ -0,0 +1,24 @@
using Avalonia;
using System;
namespace Asistencia;
sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.WithInterFont()
.LogToTrace();
}
+48
View File
@@ -0,0 +1,48 @@
using Asistencia.Data.Repositories;
using Asistencia.Models;
namespace Asistencia.Services;
public class AsistenciaService
{
private readonly CursoRepository _cursoRepo;
private readonly AsistenciaRepository _asistenciaRepo;
public AsistenciaService(CursoRepository cursoRepo, AsistenciaRepository asistenciaRepo)
{
_cursoRepo = cursoRepo;
_asistenciaRepo = asistenciaRepo;
}
public Task<List<CursoAbierto>> ObtenerCursosProfesorAsync(string profesorRun)
=> _cursoRepo.BuscarCursosPorProfesorAsync(profesorRun);
public Task<CursoAbierto?> ObtenerCursoAsync(int idCursoAbierto)
=> _cursoRepo.BuscarCursoAbiertoPorIdAsync(idCursoAbierto);
public Task<List<DetalleContrato>> ObtenerAlumnosAsync(int idCursoAbierto)
=> _cursoRepo.BuscarAlumnosPorCursoAsync(idCursoAbierto);
public Task<AsistenciaProfesor?> BuscarSesionActivaAsync(int idCursoAbierto)
=> _asistenciaRepo.BuscarSesionActivaAsync(idCursoAbierto, DateTime.Today);
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut)
{
var now = DateTime.Now;
return await _asistenciaRepo.IniciarSesionAsync(idCursoAbierto, rut, now.Date, now.ToString("HH:mm"));
}
public async Task<bool> FinalizarSesionAsync(int idSesion)
{
return await _asistenciaRepo.FinalizarSesionAsync(idSesion, DateTime.Now.ToString("HH:mm"));
}
public Task<Dictionary<int, int>> ObtenerAsistenciaAlumnosAsync(int idCursoAbierto)
=> _asistenciaRepo.ObtenerAsistenciaAlumnosAsync(idCursoAbierto, DateTime.Today);
public async Task GuardarAsistenciaAlumnoAsync(int idDetalleContrato, int tipoAsistencia)
{
await _asistenciaRepo.GuardarAsistenciaAlumnoAsync(
idDetalleContrato, DateTime.Today, DateTime.Now.ToString("HH:mm"), tipoAsistencia);
}
}
+96
View File
@@ -0,0 +1,96 @@
using Asistencia.Data.Repositories;
using Asistencia.Models;
namespace Asistencia.Services;
public class AuthService
{
private readonly ProfesorRepository _profesorRepo;
private Profesor? _currentUser;
public AuthService(ProfesorRepository profesorRepo)
{
_profesorRepo = profesorRepo;
}
public Profesor? CurrentUser => _currentUser;
public async Task<(bool Success, string Message)> LoginAsync(string rut, string password)
{
if (string.IsNullOrWhiteSpace(rut) || string.IsNullOrWhiteSpace(password))
return (false, "Ingrese usuario y contraseña");
var profesor = await _profesorRepo.BuscarPorRutAsync(rut);
if (profesor == null)
return (false, "Usuario no encontrado");
if (profesor.CrearClave)
return (false, "Debe crear su contraseña primero");
var authenticated = await _profesorRepo.AutenticarAsync(rut, password);
if (authenticated == null)
return (false, "Contraseña incorrecta");
_currentUser = authenticated;
return (true, "Inicio de sesión exitoso");
}
public async Task<(bool Success, string Message)> CrearClaveAsync(string rut, string nuevaClave, string confirmarClave)
{
if (string.IsNullOrWhiteSpace(nuevaClave))
return (false, "Ingrese una contraseña");
if (nuevaClave.Length < 6)
return (false, "La contraseña debe tener al menos 6 caracteres");
if (nuevaClave != confirmarClave)
return (false, "Las contraseñas no coinciden");
var encrypted = Helpers.CryptoHelper.Encriptar(nuevaClave);
var result = await _profesorRepo.ActualizarClaveAsync(rut, encrypted);
return result ? (true, "Contraseña creada exitosamente") : (false, "Error al crear contraseña");
}
public async Task<(bool Success, string Message)> ActualizarEmailAsync(string email)
{
if (_currentUser == null) return (false, "No hay sesión activa");
if (string.IsNullOrWhiteSpace(email) || !email.Contains("@"))
return (false, "Ingrese un email válido");
var result = await _profesorRepo.ActualizarEmailAsync(_currentUser.RutPasaporte, email);
if (result)
{
_currentUser.Email = email;
return (true, "Email actualizado exitosamente");
}
return (false, "Error al actualizar email");
}
public async Task<(bool Success, string Message)> CambiarClaveAsync(string claveActual, string nuevaClave, string confirmarClave)
{
if (_currentUser == null) return (false, "No hay sesión activa");
if (string.IsNullOrWhiteSpace(claveActual))
return (false, "Ingrese la contraseña actual");
if (string.IsNullOrWhiteSpace(nuevaClave) || nuevaClave.Length < 6)
return (false, "La nueva contraseña debe tener al menos 6 caracteres");
if (nuevaClave != confirmarClave)
return (false, "Las contraseñas no coinciden");
var authenticated = await _profesorRepo.AutenticarAsync(_currentUser.RutPasaporte, claveActual);
if (authenticated == null)
return (false, "La contraseña actual es incorrecta");
var encrypted = Helpers.CryptoHelper.Encriptar(nuevaClave);
var result = await _profesorRepo.ActualizarClaveAsync(_currentUser.RutPasaporte, encrypted);
return result ? (true, "Contraseña cambiada exitosamente") : (false, "Error al cambiar contraseña");
}
public void Logout()
{
_currentUser = null;
}
}
+83
View File
@@ -0,0 +1,83 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style Selector="Button.primary">
<Setter Property="Background" Value="{DynamicResource PrimaryNavy}" />
<Setter Property="Foreground" Value="{DynamicResource TextOnPrimary}" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="20,10" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style Selector="Button.primary:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{DynamicResource PrimaryNavyLight}" />
</Style>
<Style Selector="Button.secondary">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryNavy}" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="20,10" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryNavy}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style Selector="Button.secondary:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="#F0F4FF" />
</Style>
<Style Selector="Button.danger">
<Setter Property="Background" Value="{DynamicResource DangerColor}" />
<Setter Property="Foreground" Value="{DynamicResource TextOnPrimary}" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="20,10" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style Selector="Button.success">
<Setter Property="Background" Value="{DynamicResource SuccessColor}" />
<Setter Property="Foreground" Value="{DynamicResource TextOnPrimary}" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="12,8" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style Selector="Border.card">
<Setter Property="Background" Value="{DynamicResource BackgroundPrimary}" />
<Setter Property="CornerRadius" Value="12" />
<Setter Property="Padding" Value="24" />
<Setter Property="BorderBrush" Value="{DynamicResource BorderColor}" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<Style Selector="TextBlock.page-header">
<Setter Property="FontSize" Value="24" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="Margin" Value="0,0,0,24" />
</Style>
<Style Selector="TextBlock.section-title">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="Margin" Value="0,0,0,12" />
</Style>
<Style Selector="TextBlock.card-title">
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
</Style>
</Styles>
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Asistencia.ViewModels;
namespace Asistencia;
/// <summary>
/// Given a view model, returns the corresponding view if possible.
/// </summary>
[RequiresUnreferencedCode(
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
@@ -0,0 +1,167 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Asistencia.Models;
using Asistencia.Services;
using System.Collections.ObjectModel;
namespace Asistencia.ViewModels;
public partial class AsistenciaViewModel : ObservableObject
{
private readonly AsistenciaService _asistenciaService;
private readonly AuthService _authService;
private readonly MainWindowViewModel _mainVm;
private readonly CursoAbierto _curso;
[ObservableProperty]
private string _nombreCurso = string.Empty;
[ObservableProperty]
private string _infoCurso = string.Empty;
[ObservableProperty]
private bool _enSesion;
[ObservableProperty]
private int _totalAlumnos;
[ObservableProperty]
private int _presentes;
[ObservableProperty]
private int _tardanzas;
[ObservableProperty]
private int _ausentes;
[ObservableProperty]
private string _mensajeEstado = string.Empty;
public ObservableCollection<AlumnoAsistenciaViewModel> Alumnos { get; } = new();
public AsistenciaViewModel(AsistenciaService asistenciaService, AuthService authService, CursoAbierto curso, MainWindowViewModel mainVm)
{
_asistenciaService = asistenciaService;
_authService = authService;
_mainVm = mainVm;
_curso = curso;
NombreCurso = curso.Curso?.NombreCurso ?? "Curso";
InfoCurso = $"{curso.Sala} | {curso.Sede} | {curso.HoraInicio} - {curso.HoraFin}";
_ = InitAsync();
}
private async Task InitAsync()
{
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
EnSesion = sesion != null;
var alumnos = await _asistenciaService.ObtenerAlumnosAsync(_curso.IdCursoAbierto);
var asistencias = await _asistenciaService.ObtenerAsistenciaAlumnosAsync(_curso.IdCursoAbierto);
Alumnos.Clear();
foreach (var alumno in alumnos)
{
var tipo = asistencias.TryGetValue(alumno.IdDetalleContrato, out var t) ? t : TipoAsistencia.Ausente;
Alumnos.Add(new AlumnoAsistenciaViewModel(alumno, tipo));
}
TotalAlumnos = Alumnos.Count;
ActualizarContadores();
MensajeEstado = EnSesion
? "Sesion en curso - Puede registrar asistencia"
: "Inicie la sesion para registrar asistencia";
}
[RelayCommand]
private async Task IniciarSesionAsync()
{
if (_authService.CurrentUser == null) return;
await _asistenciaService.IniciarSesionAsync(_curso.IdCursoAbierto, _authService.CurrentUser.RutPasaporte);
EnSesion = true;
MensajeEstado = "Sesion iniciada - Registre la asistencia de los alumnos";
}
[RelayCommand]
private async Task FinalizarSesionAsync()
{
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
if (sesion != null)
{
await _asistenciaService.FinalizarSesionAsync(sesion.Id);
}
EnSesion = false;
MensajeEstado = "Sesion finalizada";
}
[RelayCommand]
private async Task MarcarAlumnoAsync(AlumnoAsistenciaViewModel? alumno)
{
if (alumno == null || !EnSesion) return;
alumno.CiclarTipoAsistencia();
await _asistenciaService.GuardarAsistenciaAlumnoAsync(alumno.IdDetalleContrato, alumno.TipoAsistencia);
ActualizarContadores();
}
[RelayCommand]
private void Volver()
{
_mainVm.NavigateToDashboard();
}
private void ActualizarContadores()
{
Presentes = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Presente);
Tardanzas = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Tardanza);
Ausentes = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Ausente);
}
}
public partial class AlumnoAsistenciaViewModel : ObservableObject
{
public int IdDetalleContrato { get; }
public string NombreCompleto { get; }
[ObservableProperty]
private int _tipoAsistencia;
[ObservableProperty]
private string _tipoAsistenciaTexto;
[ObservableProperty]
private string _tipoAsistenciaColor;
public AlumnoAsistenciaViewModel(DetalleContrato alumno, int tipoInicial)
{
IdDetalleContrato = alumno.IdDetalleContrato;
NombreCompleto = alumno.NombreCompleto;
TipoAsistencia = tipoInicial;
ActualizarDisplay();
}
public void CiclarTipoAsistencia()
{
TipoAsistencia = TipoAsistencia switch
{
Models.TipoAsistencia.Presente => Models.TipoAsistencia.Tardanza,
Models.TipoAsistencia.Tardanza => Models.TipoAsistencia.Ausente,
_ => Models.TipoAsistencia.Presente
};
ActualizarDisplay();
}
private void ActualizarDisplay()
{
TipoAsistenciaTexto = Models.TipoAsistencia.Nombre(TipoAsistencia);
TipoAsistenciaColor = TipoAsistencia switch
{
Models.TipoAsistencia.Presente => "#28A745",
Models.TipoAsistencia.Tardanza => "#FFC107",
_ => "#DC3545"
};
}
}
@@ -0,0 +1,61 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Asistencia.Models;
using Asistencia.Services;
using System.Collections.ObjectModel;
namespace Asistencia.ViewModels;
public partial class DashboardViewModel : ObservableObject
{
private readonly AuthService _authService;
private readonly AsistenciaService _asistenciaService;
private readonly MainWindowViewModel _mainVm;
[ObservableProperty]
private string _nombreProfesor = string.Empty;
[ObservableProperty]
private int _totalCursos;
public ObservableCollection<CursoAbierto> Cursos { get; } = new();
public DashboardViewModel(AuthService authService, AsistenciaService asistenciaService, MainWindowViewModel mainVm)
{
_authService = authService;
_asistenciaService = asistenciaService;
_mainVm = mainVm;
NombreProfesor = authService.CurrentUser?.Nombre ?? "";
_ = LoadCursosAsync();
}
private async Task LoadCursosAsync()
{
if (_authService.CurrentUser == null) return;
var cursos = await _asistenciaService.ObtenerCursosProfesorAsync(_authService.CurrentUser.RutPasaporte);
Cursos.Clear();
foreach (var c in cursos) Cursos.Add(c);
TotalCursos = Cursos.Count;
}
[RelayCommand]
private void AbrirAsistencia(CursoAbierto? curso)
{
if (curso != null)
_mainVm.NavigateToAsistencia(curso);
}
[RelayCommand]
private void AbrirPerfil()
{
_mainVm.NavigateToPerfil();
}
[RelayCommand]
private void CerrarSesion()
{
_authService.Logout();
_mainVm.NavigateToLogin();
}
}
+53
View File
@@ -0,0 +1,53 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Asistencia.Services;
namespace Asistencia.ViewModels;
public partial class LoginViewModel : ObservableObject
{
private readonly AuthService _authService;
private readonly MainWindowViewModel _mainVm;
[ObservableProperty]
private string _rut = string.Empty;
[ObservableProperty]
private string _password = string.Empty;
[ObservableProperty]
private string _errorMessage = string.Empty;
[ObservableProperty]
private bool _hasError;
[ObservableProperty]
private bool _isLoading;
public LoginViewModel(AuthService authService, MainWindowViewModel mainVm)
{
_authService = authService;
_mainVm = mainVm;
}
[RelayCommand]
private async Task LoginAsync()
{
IsLoading = true;
HasError = false;
var (success, message) = await _authService.LoginAsync(Rut, Password);
if (success)
{
_mainVm.NavigateToDashboard();
}
else
{
ErrorMessage = message;
HasError = true;
}
IsLoading = false;
}
}
@@ -0,0 +1,58 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Asistencia.Models;
using Asistencia.Services;
using Avalonia.Controls;
using Asistencia.Views;
using System.Collections.ObjectModel;
namespace Asistencia.ViewModels;
public partial class MainWindowViewModel : ObservableObject
{
private readonly AuthService _authService;
private readonly AsistenciaService _asistenciaService;
private object? _currentView;
[ObservableProperty]
private string _currentViewTitle = "Login";
public object? CurrentView
{
get => _currentView;
set => SetProperty(ref _currentView, value);
}
public MainWindowViewModel(AuthService authService, AsistenciaService asistenciaService)
{
_authService = authService;
_asistenciaService = asistenciaService;
CurrentView = new LoginViewModel(authService, this);
}
public void NavigateToLogin()
{
CurrentViewTitle = "Login";
CurrentView = new LoginViewModel(_authService, this);
}
public void NavigateToDashboard()
{
CurrentViewTitle = "Panel Principal";
CurrentView = new DashboardViewModel(_authService, _asistenciaService, this);
}
public void NavigateToAsistencia(CursoAbierto curso)
{
CurrentViewTitle = "Asistencia";
CurrentView = new AsistenciaViewModel(_asistenciaService, _authService, curso, this);
}
public void NavigateToPerfil()
{
CurrentViewTitle = "Mi Perfil";
CurrentView = new PerfilViewModel(_authService, this);
}
public string UsuarioActual => _authService.CurrentUser?.NombreCompleto ?? "";
}
+122
View File
@@ -0,0 +1,122 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Asistencia.Services;
namespace Asistencia.ViewModels;
public partial class PerfilViewModel : ObservableObject
{
private readonly AuthService _authService;
private readonly MainWindowViewModel _mainVm;
[ObservableProperty]
private string _rut = string.Empty;
[ObservableProperty]
private string _nombreCompleto = string.Empty;
[ObservableProperty]
private string _email = string.Empty;
[ObservableProperty]
private string _fono = string.Empty;
[ObservableProperty]
private string _direccion = string.Empty;
[ObservableProperty]
private string _mensajeExito = string.Empty;
[ObservableProperty]
private bool _tieneExito;
[ObservableProperty]
private string _mensajeError = string.Empty;
[ObservableProperty]
private bool _tieneError;
[ObservableProperty]
private bool _mostrarCambioClave;
[ObservableProperty]
private string _claveActual = string.Empty;
[ObservableProperty]
private string _nuevaClave = string.Empty;
[ObservableProperty]
private string _confirmarClave = string.Empty;
public PerfilViewModel(AuthService authService, MainWindowViewModel mainVm)
{
_authService = authService;
_mainVm = mainVm;
var user = authService.CurrentUser;
if (user != null)
{
Rut = user.RutPasaporte;
NombreCompleto = user.NombreCompleto;
Email = user.Email;
Fono = user.Fono;
Direccion = user.Direccion;
}
}
[RelayCommand]
private async Task GuardarEmailAsync()
{
TieneExito = false;
TieneError = false;
var (success, message) = await _authService.ActualizarEmailAsync(Email);
if (success)
{
MensajeExito = message;
TieneExito = true;
}
else
{
MensajeError = message;
TieneError = true;
}
}
[RelayCommand]
private async Task CambiarClaveAsync()
{
TieneExito = false;
TieneError = false;
var (success, message) = await _authService.CambiarClaveAsync(ClaveActual, NuevaClave, ConfirmarClave);
if (success)
{
MensajeExito = message;
TieneExito = true;
MostrarCambioClave = false;
ClaveActual = string.Empty;
NuevaClave = string.Empty;
ConfirmarClave = string.Empty;
}
else
{
MensajeError = message;
TieneError = true;
}
}
[RelayCommand]
private void ToggleCambioClave()
{
MostrarCambioClave = !MostrarCambioClave;
TieneExito = false;
TieneError = false;
}
[RelayCommand]
private void Volver()
{
_mainVm.NavigateToDashboard();
}
}
+7
View File
@@ -0,0 +1,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Asistencia.ViewModels;
public abstract class ViewModelBase : ObservableObject
{
}
+135
View File
@@ -0,0 +1,135 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
x:Class="Asistencia.Views.AsistenciaView"
x:DataType="vm:AsistenciaViewModel">
<Design.DataContext>
<vm:AsistenciaViewModel />
</Design.DataContext>
<ScrollViewer>
<StackPanel Spacing="0" Margin="32,24">
<Button Content="Volver" Classes="secondary"
HorizontalAlignment="Left"
Command="{Binding VolverCommand}"
Margin="0,0,0,16" />
<TextBlock Text="{Binding NombreCurso}" Classes="page-header" />
<Border Classes="card" Margin="0,0,0,20">
<StackPanel Spacing="8">
<TextBlock Text="{Binding InfoCurso}"
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding MensajeEstado}"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryNavy}" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,8,0,0">
<Button Content="Iniciar Sesion"
Classes="success"
Command="{Binding IniciarSesionCommand}"
IsVisible="{Binding !EnSesion}" />
<Button Content="Finalizar Sesion"
Classes="danger"
Command="{Binding FinalizarSesionCommand}"
IsVisible="{Binding EnSesion}" />
</StackPanel>
</StackPanel>
</Border>
<Grid ColumnDefinitions="*,Auto" Margin="0,0,0,16">
<TextBlock Grid.Column="0"
Classes="section-title"
Text="Alumnos"
VerticalAlignment="Center" />
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="16">
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource SuccessColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Presentes}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource WarningColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Tardanzas}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource DangerColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Ausentes}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
</StackPanel>
</Grid>
<Border Classes="card" Padding="0">
<Grid RowDefinitions="Auto,*">
<Border Grid.Row="0" Background="{DynamicResource BackgroundSecondary}"
CornerRadius="12,12,0,0" Padding="16,12">
<Grid ColumnDefinitions="*,120">
<TextBlock Grid.Column="0" Text="Alumno"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Grid.Column="1" Text="Estado"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondary}"
HorizontalAlignment="Center" />
</Grid>
</Border>
<ListBox Grid.Row="1"
ItemsSource="{Binding Alumnos}"
Background="Transparent"
BorderThickness="0"
Padding="0">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:AlumnoAsistenciaViewModel">
<Border Padding="16,12"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,0,0,1">
<Grid ColumnDefinitions="*,120">
<TextBlock Grid.Column="0"
Text="{Binding NombreCompleto}"
FontSize="14"
VerticalAlignment="Center" />
<Button Grid.Column="1"
HorizontalAlignment="Center"
Command="{Binding $parent[ListBox].((vm:AsistenciaViewModel)DataContext).MarcarAlumnoCommand}"
CommandParameter="{Binding}"
Background="{Binding TipoAsistenciaColor}"
CornerRadius="20"
Padding="16,6"
FontSize="13"
FontWeight="SemiBold"
Foreground="White"
BorderThickness="0"
MinWidth="100">
<TextBlock Text="{Binding TipoAsistenciaTexto}"
Foreground="White" />
</Button>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
<Border Classes="card" Margin="0,16,0,0"
IsVisible="{Binding !Alumnos.Count}"
Background="#FFF3CD">
<TextBlock Text="No hay alumnos en este curso."
FontSize="14" Foreground="#856404" />
</Border>
</StackPanel>
</ScrollViewer>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Asistencia.Views;
public partial class AsistenciaView : UserControl
{
public AsistenciaView()
{
InitializeComponent();
}
}
+89
View File
@@ -0,0 +1,89 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
xmlns:models="using:Asistencia.Models"
x:Class="Asistencia.Views.DashboardView"
x:DataType="vm:DashboardViewModel">
<Design.DataContext>
<vm:DashboardViewModel />
</Design.DataContext>
<ScrollViewer>
<StackPanel Spacing="0" Margin="32,24">
<TextBlock Text="Panel Principal" Classes="page-header" />
<Border Classes="card" Margin="0,0,0,24">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Bienvenido"
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding NombreProfesor}"
FontSize="24" FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
<Button Content="Mi Perfil"
Command="{Binding AbrirPerfilCommand}"
Classes="secondary" />
<Button Content="Cerrar Sesion"
Command="{Binding CerrarSesionCommand}"
Classes="danger" />
</StackPanel>
</Grid>
</Border>
<TextBlock Text="Mis Cursos" Classes="section-title" Margin="0,0,0,12" />
<ItemsControl ItemsSource="{Binding Cursos}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:CursoAbierto">
<Border Classes="card" Margin="0,0,0,12">
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{Binding Curso.NombreCurso}"
FontSize="18" FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}" />
<TextBlock Grid.Row="0" Grid.Column="1"
Text="{Binding Sala}"
FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Grid.Row="1" Grid.Column="0"
FontSize="13"
Foreground="{DynamicResource TextSecondary}"
Margin="0,4,0,0">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} | {1}">
<Binding Path="Sede" />
<Binding Path="HoraInicio" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
Content="Tomar Asistencia"
Classes="primary"
HorizontalAlignment="Left"
Margin="0,12,0,0"
Command="{Binding $parent[ItemsControl].((vm:DashboardViewModel)DataContext).AbrirAsistenciaCommand}"
CommandParameter="{Binding}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border Classes="card" Margin="0,24,0,0"
IsVisible="{Binding !Cursos.Count}"
Background="#FFF3CD">
<TextBlock Text="No tiene cursos asignados actualmente."
FontSize="14" Foreground="#856404" />
</Border>
</StackPanel>
</ScrollViewer>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Asistencia.Views;
public partial class DashboardView : UserControl
{
public DashboardView()
{
InitializeComponent();
}
}
+56
View File
@@ -0,0 +1,56 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
x:Class="Asistencia.Views.LoginView"
x:DataType="vm:LoginViewModel">
<Design.DataContext>
<vm:LoginViewModel />
</Design.DataContext>
<Panel Background="{DynamicResource BackgroundSecondary}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center"
CornerRadius="16" Padding="48" Width="420"
Background="{DynamicResource BackgroundPrimary}"
BorderBrush="{DynamicResource BorderColor}" BorderThickness="1">
<StackPanel Spacing="8">
<TextBlock Text="Sistema de Asistencia"
FontSize="28" FontWeight="Bold"
Foreground="{DynamicResource PrimaryNavy}"
HorizontalAlignment="Center" />
<TextBlock Text="Inicie sesion con su cuenta"
FontSize="14" Foreground="{DynamicResource TextSecondary}"
HorizontalAlignment="Center" Margin="0,0,0,24" />
<TextBlock Text="RUT" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<TextBox Watermark="Ej: 12345678-9"
Text="{Binding Rut}"
FontSize="14" Margin="0,0,0,8" />
<TextBlock Text="Contrasena" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<TextBox Watermark="Ingrese su contrasena"
Text="{Binding Password}"
PasswordChar="*"
FontSize="14" Margin="0,0,0,16" />
<Button Content="Iniciar Sesion"
Command="{Binding LoginCommand}"
Classes="primary"
HorizontalAlignment="Stretch"
Height="44"
IsEnabled="{Binding !IsLoading}" />
<TextBlock Text="{Binding ErrorMessage}"
Foreground="{DynamicResource DangerColor}"
FontSize="13"
HorizontalAlignment="Center"
IsVisible="{Binding HasError}"
Margin="0,8,0,0" />
</StackPanel>
</Border>
</Panel>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Asistencia.Views;
public partial class LoginView : UserControl
{
public LoginView()
{
InitializeComponent();
}
}
+23
View File
@@ -0,0 +1,23 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
xmlns:views="using:Asistencia.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="700"
x:Class="Asistencia.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="Sistema de Asistencia"
Width="1024" Height="700"
MinWidth="800" MinHeight="600"
WindowStartupLocation="CenterScreen">
<Design.DataContext>
<vm:MainWindowViewModel />
</Design.DataContext>
<Panel>
<ContentControl Content="{Binding CurrentView}" />
</Panel>
</Window>
+11
View File
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace Asistencia.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
+125
View File
@@ -0,0 +1,125 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
x:Class="Asistencia.Views.PerfilView"
x:DataType="vm:PerfilViewModel">
<Design.DataContext>
<vm:PerfilViewModel />
</Design.DataContext>
<ScrollViewer>
<StackPanel Spacing="0" Margin="32,24" MaxWidth="600">
<Button Content="Volver" Classes="secondary"
HorizontalAlignment="Left"
Command="{Binding VolverCommand}"
Margin="0,0,0,16" />
<TextBlock Text="Mi Perfil" Classes="page-header" />
<Border Classes="card" Margin="0,0,0,20">
<StackPanel Spacing="16">
<TextBlock Text="Informacion Personal"
Classes="card-title" Margin="0,0,0,8" />
<StackPanel Spacing="4">
<TextBlock Text="RUT" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding Rut}" FontSize="15"
FontWeight="SemiBold" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Nombre Completo" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding NombreCompleto}" FontSize="15"
FontWeight="SemiBold" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Telefono" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding Fono}" FontSize="15" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Direccion" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding Direccion}" FontSize="15" />
</StackPanel>
</StackPanel>
</Border>
<Border Classes="card" Margin="0,0,0,20">
<StackPanel Spacing="16">
<TextBlock Text="Email" Classes="card-title" Margin="0,0,0,8" />
<TextBox Text="{Binding Email}" FontSize="14"
Watermark="correo@ejemplo.com" />
<Button Content="Guardar Email"
Classes="primary"
HorizontalAlignment="Left"
Command="{Binding GuardarEmailCommand}" />
</StackPanel>
</Border>
<Border Classes="card" Margin="0,0,0,20">
<StackPanel Spacing="16">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Cambiar Contrasena"
Classes="card-title" />
<Button Grid.Column="1"
Content="Cambiar Contrasena"
Classes="secondary"
Command="{Binding ToggleCambioClaveCommand}"
FontSize="13" />
</Grid>
<StackPanel Spacing="12"
IsVisible="{Binding MostrarCambioClave}">
<StackPanel Spacing="4">
<TextBlock Text="Contrasena Actual" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBox Text="{Binding ClaveActual}"
PasswordChar="*" FontSize="14" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Nueva Contrasena" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBox Text="{Binding NuevaClave}"
PasswordChar="*" FontSize="14" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Confirmar Contrasena" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBox Text="{Binding ConfirmarClave}"
PasswordChar="*" FontSize="14" />
</StackPanel>
<Button Content="Cambiar Contrasena"
Classes="primary"
HorizontalAlignment="Left"
Command="{Binding CambiarClaveCommand}" />
</StackPanel>
</StackPanel>
</Border>
<Border Classes="card"
IsVisible="{Binding TieneExito}"
Background="#D4EDDA" BorderBrush="#C3E6CB" Margin="0,0,0,12">
<TextBlock Text="{Binding MensajeExito}"
FontSize="14" Foreground="#155724" />
</Border>
<Border Classes="card"
IsVisible="{Binding TieneError}"
Background="#F8D7DA" BorderBrush="#F5C6CB" Margin="0,0,0,12">
<TextBlock Text="{Binding MensajeError}"
FontSize="14" Foreground="#721C24" />
</Border>
</StackPanel>
</ScrollViewer>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Asistencia.Views;
public partial class PerfilView : UserControl
{
public PerfilView()
{
InitializeComponent();
}
}
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="Asistencia.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,16 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
},
"configProperties": {
"Avalonia.Diagnostics.Diagnostic.IsEnabled": true,
"MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT": true,
"System.Diagnostics.Metrics.Meter.IsSupported": true,
"System.Reflection.NullabilityInfoContext.IsSupported": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.IO.Redist" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,260 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v6.0": {
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost/4.14.0-3.25262.10": {
"dependencies": {
"Microsoft.Build.Locator": "1.6.10",
"Microsoft.CodeAnalysis.NetAnalyzers": "8.0.0-preview.23468.1",
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers": "3.3.4-beta1.22504.1",
"Microsoft.DotNet.XliffTasks": "9.0.0-beta.25255.5",
"Microsoft.VisualStudio.Threading.Analyzers": "17.13.2",
"Newtonsoft.Json": "13.0.3",
"Roslyn.Diagnostics.Analyzers": "3.11.0-beta1.24081.1",
"System.Collections.Immutable": "9.0.0",
"System.CommandLine": "2.0.0-beta4.24528.1"
},
"runtime": {
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll": {}
},
"resources": {
"cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "cs"
},
"de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "de"
},
"es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "es"
},
"fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "fr"
},
"it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "it"
},
"ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "ja"
},
"ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "ko"
},
"pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "pl"
},
"pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "pt-BR"
},
"ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "ru"
},
"tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "tr"
},
"zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "zh-Hans"
},
"zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
"locale": "zh-Hant"
}
}
},
"Microsoft.Build.Locator/1.6.10": {
"runtime": {
"lib/net6.0/Microsoft.Build.Locator.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.6.10.57384"
}
}
},
"Microsoft.CodeAnalysis.BannedApiAnalyzers/3.11.0-beta1.24081.1": {},
"Microsoft.CodeAnalysis.NetAnalyzers/8.0.0-preview.23468.1": {},
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers/3.3.4-beta1.22504.1": {},
"Microsoft.CodeAnalysis.PublicApiAnalyzers/3.11.0-beta1.24081.1": {},
"Microsoft.DotNet.XliffTasks/9.0.0-beta.25255.5": {},
"Microsoft.VisualStudio.Threading.Analyzers/17.13.2": {},
"Newtonsoft.Json/13.0.3": {
"runtime": {
"lib/net6.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.3.27908"
}
}
},
"Roslyn.Diagnostics.Analyzers/3.11.0-beta1.24081.1": {
"dependencies": {
"Microsoft.CodeAnalysis.BannedApiAnalyzers": "3.11.0-beta1.24081.1",
"Microsoft.CodeAnalysis.PublicApiAnalyzers": "3.11.0-beta1.24081.1"
}
},
"System.Collections.Immutable/9.0.0": {
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
},
"runtime": {
"lib/netstandard2.0/System.Collections.Immutable.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.24.52809"
}
}
},
"System.CommandLine/2.0.0-beta4.24528.1": {
"dependencies": {
"System.Memory": "4.5.5"
},
"runtime": {
"lib/netstandard2.0/System.CommandLine.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.0.24.52801"
}
},
"resources": {
"lib/netstandard2.0/cs/System.CommandLine.resources.dll": {
"locale": "cs"
},
"lib/netstandard2.0/de/System.CommandLine.resources.dll": {
"locale": "de"
},
"lib/netstandard2.0/es/System.CommandLine.resources.dll": {
"locale": "es"
},
"lib/netstandard2.0/fr/System.CommandLine.resources.dll": {
"locale": "fr"
},
"lib/netstandard2.0/it/System.CommandLine.resources.dll": {
"locale": "it"
},
"lib/netstandard2.0/ja/System.CommandLine.resources.dll": {
"locale": "ja"
},
"lib/netstandard2.0/ko/System.CommandLine.resources.dll": {
"locale": "ko"
},
"lib/netstandard2.0/pl/System.CommandLine.resources.dll": {
"locale": "pl"
},
"lib/netstandard2.0/pt-BR/System.CommandLine.resources.dll": {
"locale": "pt-BR"
},
"lib/netstandard2.0/ru/System.CommandLine.resources.dll": {
"locale": "ru"
},
"lib/netstandard2.0/tr/System.CommandLine.resources.dll": {
"locale": "tr"
},
"lib/netstandard2.0/zh-Hans/System.CommandLine.resources.dll": {
"locale": "zh-Hans"
},
"lib/netstandard2.0/zh-Hant/System.CommandLine.resources.dll": {
"locale": "zh-Hant"
}
}
},
"System.Memory/4.5.5": {},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {}
}
},
"libraries": {
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost/4.14.0-3.25262.10": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.Build.Locator/1.6.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DJhCkTGqy1LMJzEmG/2qxRTMHwdPc3WdVoGQI5o5mKHVo4dsHrCMLIyruwU/NSvPNSdvONlaf7jdFXnAMuxAuA==",
"path": "microsoft.build.locator/1.6.10",
"hashPath": "microsoft.build.locator.1.6.10.nupkg.sha512"
},
"Microsoft.CodeAnalysis.BannedApiAnalyzers/3.11.0-beta1.24081.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DH6L3rsbjppLrHM2l2/NKbnMaYd0NFHx2pjZaFdrVcRkONrV3i9FHv6Id8Dp6/TmjhXQsJVJJFbhhjkpuP1xxg==",
"path": "microsoft.codeanalysis.bannedapianalyzers/3.11.0-beta1.24081.1",
"hashPath": "microsoft.codeanalysis.bannedapianalyzers.3.11.0-beta1.24081.1.nupkg.sha512"
},
"Microsoft.CodeAnalysis.NetAnalyzers/8.0.0-preview.23468.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZhIvyxmUCqb8OiU/VQfxfuAmIB4lQsjqhMVYKeoyxzSI+d7uR5Pzx3ZKoaIhPizQ15wa4lnyD6wg3TnSJ6P4LA==",
"path": "microsoft.codeanalysis.netanalyzers/8.0.0-preview.23468.1",
"hashPath": "microsoft.codeanalysis.netanalyzers.8.0.0-preview.23468.1.nupkg.sha512"
},
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers/3.3.4-beta1.22504.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-2XRlqPAzVke7Sb80+UqaC7o57OwfK+tIr+aIOxrx41RWDMeR2SBUW7kL4sd6hfLFfBNsLo3W5PT+UwfvwPaOzA==",
"path": "microsoft.codeanalysis.performancesensitiveanalyzers/3.3.4-beta1.22504.1",
"hashPath": "microsoft.codeanalysis.performancesensitiveanalyzers.3.3.4-beta1.22504.1.nupkg.sha512"
},
"Microsoft.CodeAnalysis.PublicApiAnalyzers/3.11.0-beta1.24081.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3bYGBihvoNO0rhCOG1U9O50/4Q8suZ+glHqQLIAcKvnodSnSW+dYWYzTNb1UbS8pUS8nAUfxSFMwuMup/G5DtQ==",
"path": "microsoft.codeanalysis.publicapianalyzers/3.11.0-beta1.24081.1",
"hashPath": "microsoft.codeanalysis.publicapianalyzers.3.11.0-beta1.24081.1.nupkg.sha512"
},
"Microsoft.DotNet.XliffTasks/9.0.0-beta.25255.5": {
"type": "package",
"serviceable": true,
"sha512": "sha512-bb0fZB5ViPscdfYeWlmtyXJMzNkgcpkV5RWmXktfV9lwIUZgNZmFotUXrdcTyZzrN7v1tQK/Y6BGnbkP9gEsXg==",
"path": "microsoft.dotnet.xlifftasks/9.0.0-beta.25255.5",
"hashPath": "microsoft.dotnet.xlifftasks.9.0.0-beta.25255.5.nupkg.sha512"
},
"Microsoft.VisualStudio.Threading.Analyzers/17.13.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Qcd8IlaTXZVq3wolBnzby1P7kWihdWaExtD8riumiKuG1sHa8EgjV/o70TMjTaeUMhomBbhfdC9OPwAHoZfnjQ==",
"path": "microsoft.visualstudio.threading.analyzers/17.13.2",
"hashPath": "microsoft.visualstudio.threading.analyzers.17.13.2.nupkg.sha512"
},
"Newtonsoft.Json/13.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
"path": "newtonsoft.json/13.0.3",
"hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
},
"Roslyn.Diagnostics.Analyzers/3.11.0-beta1.24081.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-reHqZCDKifA+DURcL8jUfYkMGL4FpgNt5LI0uWTS6IpM8kKVbu/kO8byZsqfhBu4wUzT3MBDcoMfzhZPdENIpg==",
"path": "roslyn.diagnostics.analyzers/3.11.0-beta1.24081.1",
"hashPath": "roslyn.diagnostics.analyzers.3.11.0-beta1.24081.1.nupkg.sha512"
},
"System.Collections.Immutable/9.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==",
"path": "system.collections.immutable/9.0.0",
"hashPath": "system.collections.immutable.9.0.0.nupkg.sha512"
},
"System.CommandLine/2.0.0-beta4.24528.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Xt8tsSU8yd0ZpbT9gl5DAwkMYWLo8PV1fq2R/belrUbHVVOIKqhLfbWksbdknUDpmzMHZenBtD6AGAp9uJTa2w==",
"path": "system.commandline/2.0.0-beta4.24528.1",
"hashPath": "system.commandline.2.0.0-beta4.24528.1.nupkg.sha512"
},
"System.Memory/4.5.5": {
"type": "package",
"serviceable": true,
"sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"path": "system.memory/4.5.5",
"hashPath": "system.memory.4.5.5.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
"path": "system.runtime.compilerservices.unsafe/6.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
}
}
}
@@ -0,0 +1,605 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.VisualBasic.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Concurrent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.NonGeneric" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Specialized" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.EventBasedAsync" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.TypeConverter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.Common" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Contracts" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.FileVersionInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Process" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.TextWriterTraceListener" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.TraceSource" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Drawing.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression.ZipFile" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.DriveInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Watcher" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.IsolatedStorage" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.MemoryMappedFiles" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipes.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipes" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Linq.Expressions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Linq.Parallel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Linq.Queryable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Linq" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.HttpListener" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Mail" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.NameResolution" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.NetworkInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Ping" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Requests" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Security" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.ServicePoint" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Sockets" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.WebClient" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.WebHeaderCollection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.WebProxy" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.WebSockets.Client" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.WebSockets" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ObjectModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Emit.ILGeneration" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Emit.Lightweight" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Emit" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Resources.Writer" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.VisualC" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Numerics" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Formatters" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Json" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Xml" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Claims" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Cng" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Csp" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Encoding" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.X509Certificates" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Text.RegularExpressions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Overlapped" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Parallel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Thread" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.ThreadPool" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Transactions.Local" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.HttpUtility" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Xml.ReaderWriter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Xml.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Xml.XmlSerializer" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="netstandard" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Configuration.ConfigurationManager" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Xml" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.CodeDom" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -0,0 +1,13 @@
{
"runtimeOptions": {
"tfm": "net6.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
},
"rollForward": "Major",
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
}
}
}

Some files were not shown because too many files have changed in this diff Show More