feat(admin): restore Blazor WebAssembly architecture for admin pages with hybrid Server routing
TaxBaik CI/CD / build-and-deploy (push) Successful in 2m40s
TaxBaik CI/CD / build-and-deploy (push) Successful in 2m40s
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
global using System.Net.Http;
|
||||||
|
global using System.Net.Http.Json;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@* WASM 기반(M3) 검증용 컴포넌트. 라우팅/렌더모드 전면 적용은 M4에서 처리한다. *@
|
||||||
|
@rendermode InteractiveWebAssembly
|
||||||
|
|
||||||
|
<MudPaper Class="pa-6 ma-4" Elevation="2">
|
||||||
|
<MudText Typo="Typo.h5" GutterBottom="true">WebAssembly 렌더 모드 점검</MudText>
|
||||||
|
<MudText Typo="Typo.body2" Class="mb-4">이 컴포넌트가 클릭에 반응하면 Interactive WebAssembly 기반이 정상 동작하는 것입니다.</MudText>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="Increment">카운트: @count</MudButton>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private int count;
|
||||||
|
private void Increment() => count++;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
|
using MudBlazor.Services;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
using TaxBaik.Web.Services;
|
||||||
|
using TaxBaik.Web.Services.AdminClients;
|
||||||
|
|
||||||
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
|
|
||||||
|
// MudBlazor (WASM 측 인터랙티브 컴포넌트용)
|
||||||
|
builder.Services.AddMudServices(config =>
|
||||||
|
{
|
||||||
|
config.SnackbarConfiguration.HideTransitionDuration = 400;
|
||||||
|
config.SnackbarConfiguration.ShowTransitionDuration = 300;
|
||||||
|
config.PopoverOptions.ThrowOnDuplicateProvider = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// API Base Url 동적 구성 (호스트 기준 /taxbaik/api/)
|
||||||
|
var apiBaseUrl = builder.HostEnvironment.BaseAddress.TrimEnd('/') + "/taxbaik/api/";
|
||||||
|
|
||||||
|
// HTTP Client for API (with automatic token refresh)
|
||||||
|
builder.Services.AddScoped<ITokenStore, TokenStore>();
|
||||||
|
builder.Services.AddScoped<TokenRefreshHandler>();
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient<IApiClient, ApiClient>(client =>
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri(apiBaseUrl);
|
||||||
|
}).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
|
||||||
|
// 각 Browser API Client 등록
|
||||||
|
builder.Services.AddHttpClient<IAdminDashboardClient, AdminDashboardClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IInquiryBrowserClient, InquiryBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IClientBrowserClient, ClientBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<ITaxFilingBrowserClient, TaxFilingBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IFaqBrowserClient, FaqBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IAnnouncementBrowserClient, AnnouncementBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<ITaxProfileBrowserClient, TaxProfileBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<ITaxFilingScheduleBrowserClient, TaxFilingScheduleBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IConsultingActivityBrowserClient, ConsultingActivityBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IContractBrowserClient, ContractBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<IRevenueTrackingBrowserClient, RevenueTrackingBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
builder.Services.AddHttpClient<ICommonCodeBrowserClient, CommonCodeBrowserClient>(client => client.BaseAddress = new Uri(apiBaseUrl)).AddHttpMessageHandler<TokenRefreshHandler>();
|
||||||
|
|
||||||
|
// Blazor 인증 (WASM 측 클라이언트)
|
||||||
|
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
|
||||||
|
builder.Services.AddScoped<AuthenticationStateProvider>(sp => sp.GetRequiredService<CustomAuthenticationStateProvider>());
|
||||||
|
builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();
|
||||||
|
builder.Services.AddCascadingAuthenticationState();
|
||||||
|
builder.Services.AddAuthorizationCore();
|
||||||
|
|
||||||
|
await builder.Build().RunAsync();
|
||||||
+38
-6
@@ -1,6 +1,7 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
|
||||||
namespace TaxBaik.Web.Services;
|
namespace TaxBaik.Web.Services;
|
||||||
|
|
||||||
@@ -8,18 +9,18 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|||||||
{
|
{
|
||||||
private readonly ILocalStorageService _localStorage;
|
private readonly ILocalStorageService _localStorage;
|
||||||
private readonly ITokenStore _tokenStore;
|
private readonly ITokenStore _tokenStore;
|
||||||
private readonly AuthService _authService;
|
private readonly IApiClient _apiClient;
|
||||||
private readonly ILogger<CustomAuthenticationStateProvider> _logger;
|
private readonly ILogger<CustomAuthenticationStateProvider> _logger;
|
||||||
|
|
||||||
public CustomAuthenticationStateProvider(
|
public CustomAuthenticationStateProvider(
|
||||||
ILocalStorageService localStorage,
|
ILocalStorageService localStorage,
|
||||||
ITokenStore tokenStore,
|
ITokenStore tokenStore,
|
||||||
AuthService authService,
|
IApiClient apiClient,
|
||||||
ILogger<CustomAuthenticationStateProvider> logger)
|
ILogger<CustomAuthenticationStateProvider> logger)
|
||||||
{
|
{
|
||||||
_localStorage = localStorage;
|
_localStorage = localStorage;
|
||||||
_tokenStore = tokenStore;
|
_tokenStore = tokenStore;
|
||||||
_authService = authService;
|
_apiClient = apiClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +65,9 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|||||||
if (!string.IsNullOrEmpty(_tokenStore.RefreshToken) && ShouldRefreshToken())
|
if (!string.IsNullOrEmpty(_tokenStore.RefreshToken) && ShouldRefreshToken())
|
||||||
{
|
{
|
||||||
_logger.LogInformation("토큰 만료 5분 전 - 자동 갱신 시작");
|
_logger.LogInformation("토큰 만료 5분 전 - 자동 갱신 시작");
|
||||||
var newTokenPair = await _authService.RefreshAccessTokenAsync(_tokenStore.RefreshToken);
|
var request = new { RefreshToken = _tokenStore.RefreshToken };
|
||||||
if (newTokenPair != null)
|
var newTokenPair = await _apiClient.PostAsync<WasmAuthTokenPair>("auth/refresh", request);
|
||||||
|
if (newTokenPair != null && !string.IsNullOrEmpty(newTokenPair.AccessToken))
|
||||||
{
|
{
|
||||||
await LoginAsync(newTokenPair.AccessToken, newTokenPair.RefreshToken, newTokenPair.ExpiresIn);
|
await LoginAsync(newTokenPair.AccessToken, newTokenPair.RefreshToken, newTokenPair.ExpiresIn);
|
||||||
_logger.LogInformation("토큰 자동 갱신 성공");
|
_logger.LogInformation("토큰 자동 갱신 성공");
|
||||||
@@ -79,7 +81,7 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var principal = _authService.ValidateToken(accessToken ?? string.Empty);
|
var principal = ValidateTokenWithoutDb(accessToken ?? string.Empty);
|
||||||
if (principal == null)
|
if (principal == null)
|
||||||
{
|
{
|
||||||
await LogoutAsync();
|
await LogoutAsync();
|
||||||
@@ -95,6 +97,22 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ClaimsPrincipal? ValidateTokenWithoutDb(string token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var jwtToken = handler.ReadJwtToken(token);
|
||||||
|
var identity = new ClaimsIdentity(jwtToken.Claims, "jwt");
|
||||||
|
return new ClaimsPrincipal(identity);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task LoginAsync(string accessToken, string refreshToken, int expiresIn)
|
public async Task LoginAsync(string accessToken, string refreshToken, int expiresIn)
|
||||||
{
|
{
|
||||||
var tokenExpiryTicks = DateTime.UtcNow.AddSeconds(expiresIn).Ticks;
|
var tokenExpiryTicks = DateTime.UtcNow.AddSeconds(expiresIn).Ticks;
|
||||||
@@ -158,3 +176,17 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class WasmAuthTokenPair
|
||||||
|
{
|
||||||
|
public WasmAuthTokenPair() { }
|
||||||
|
public WasmAuthTokenPair(string accessToken, string refreshToken, int expiresIn)
|
||||||
|
{
|
||||||
|
AccessToken = accessToken;
|
||||||
|
RefreshToken = refreshToken;
|
||||||
|
ExpiresIn = expiresIn;
|
||||||
|
}
|
||||||
|
public string AccessToken { get; set; } = "";
|
||||||
|
public string RefreshToken { get; set; } = "";
|
||||||
|
public int ExpiresIn { get; set; }
|
||||||
|
}
|
||||||
+2
-2
@@ -62,7 +62,7 @@ public class TokenRefreshHandler : DelegatingHandler
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<AuthTokenPair?> RefreshTokenAsync(string refreshToken, HttpRequestMessage originalRequest, CancellationToken ct)
|
private async Task<WasmAuthTokenPair?> RefreshTokenAsync(string refreshToken, HttpRequestMessage originalRequest, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -87,7 +87,7 @@ public class TokenRefreshHandler : DelegatingHandler
|
|||||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||||
|
|
||||||
return result != null
|
return result != null
|
||||||
? new AuthTokenPair(result.AccessToken, result.RefreshToken, result.ExpiresIn)
|
? new WasmAuthTokenPair(result.AccessToken, result.RefreshToken, result.ExpiresIn)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<RootNamespace>TaxBaik.WasmClient</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TaxBaik.Application\TaxBaik.Application.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.9" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.19.1" />
|
||||||
|
<PackageReference Include="MudBlazor" Version="6.10.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.19.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@using System.Net.Http
|
||||||
|
@using System.Net.Http.Json
|
||||||
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@using Microsoft.AspNetCore.Components.Authorization
|
||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
|
@using Microsoft.AspNetCore.Components.Routing
|
||||||
|
@using Microsoft.AspNetCore.Components.Web
|
||||||
|
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||||
|
@using Microsoft.JSInterop
|
||||||
|
@using MudBlazor
|
||||||
|
@using TaxBaik.WasmClient
|
||||||
|
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MudThemeProvider @bind-IsDarkMode="isDarkMode" Theme="mudTheme" />
|
<MudThemeProvider @bind-IsDarkMode="isDarkMode" Theme="mudTheme" />
|
||||||
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
|
<Routes />
|
||||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||||
<script src="js/admin-session.js"></script>
|
<script src="js/admin-session.js"></script>
|
||||||
<script src="_framework/blazor.web.js"></script>
|
<script src="_framework/blazor.web.js"></script>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
|
||||||
|
|
||||||
<MudPopoverProvider />
|
<MudPopoverProvider />
|
||||||
<MudDialogProvider />
|
<MudDialogProvider />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@page "/admin/blog/create"
|
@page "/admin/blog/create"
|
||||||
@attribute [Authorize]
|
@attribute [Authorize]
|
||||||
|
@rendermode @(new InteractiveServerRenderMode(prerender: false))
|
||||||
@using TaxBaik.Application.DTOs
|
@using TaxBaik.Application.DTOs
|
||||||
@using TaxBaik.Application.Services
|
@using TaxBaik.Application.Services
|
||||||
@using TaxBaik.Domain.Interfaces
|
@using TaxBaik.Domain.Interfaces
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@page "/admin/blog/{id:int}/edit"
|
@page "/admin/blog/{id:int}/edit"
|
||||||
@attribute [Authorize]
|
@attribute [Authorize]
|
||||||
|
@rendermode @(new InteractiveServerRenderMode(prerender: false))
|
||||||
@using TaxBaik.Application.DTOs
|
@using TaxBaik.Application.DTOs
|
||||||
@using TaxBaik.Application.Services
|
@using TaxBaik.Application.Services
|
||||||
@using TaxBaik.Domain.Interfaces
|
@using TaxBaik.Domain.Interfaces
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ builder.Services.AddHealthChecks();
|
|||||||
|
|
||||||
// Razor Pages + Blazor Server 통합
|
// Razor Pages + Blazor Server 통합
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
|
builder.Services.AddRazorComponents()
|
||||||
|
.AddInteractiveServerComponents()
|
||||||
|
.AddInteractiveWebAssemblyComponents();
|
||||||
builder.Services.Configure<Microsoft.AspNetCore.Components.Server.CircuitOptions>(options =>
|
builder.Services.Configure<Microsoft.AspNetCore.Components.Server.CircuitOptions>(options =>
|
||||||
{
|
{
|
||||||
options.DetailedErrors = true;
|
options.DetailedErrors = true;
|
||||||
@@ -354,6 +356,8 @@ app.MapRazorPages();
|
|||||||
// 인증은 Blazor AuthorizeRouteView → RedirectToLogin 에서 처리한다.
|
// 인증은 Blazor AuthorizeRouteView → RedirectToLogin 에서 처리한다.
|
||||||
app.MapRazorComponents<TaxBaik.Web.Components.Admin.App>()
|
app.MapRazorComponents<TaxBaik.Web.Components.Admin.App>()
|
||||||
.AddInteractiveServerRenderMode()
|
.AddInteractiveServerRenderMode()
|
||||||
|
.AddInteractiveWebAssemblyRenderMode()
|
||||||
|
.AddAdditionalAssemblies(typeof(TaxBaik.WasmClient._Imports).Assembly)
|
||||||
.AllowAnonymous();
|
.AllowAnonymous();
|
||||||
|
|
||||||
// 애플리케이션 시작/종료 로깅
|
// 애플리케이션 시작/종료 로깅
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\TaxBaik.Application\TaxBaik.Application.csproj" />
|
<ProjectReference Include="..\TaxBaik.Application\TaxBaik.Application.csproj" />
|
||||||
<ProjectReference Include="..\TaxBaik.Infrastructure\TaxBaik.Infrastructure.csproj" />
|
<ProjectReference Include="..\TaxBaik.Infrastructure\TaxBaik.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\TaxBaik.Web.Client\TaxBaik.Web.Client.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.9" />
|
||||||
<PackageReference Include="MudBlazor" Version="6.10.0" />
|
<PackageReference Include="MudBlazor" Version="6.10.0" />
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="10.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="10.0.9" />
|
||||||
|
|||||||
+14
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaxBaik.Web", "TaxBaik.Web\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaxBaik.Application.Tests", "TaxBaik.Application.Tests\TaxBaik.Application.Tests.csproj", "{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaxBaik.Application.Tests", "TaxBaik.Application.Tests\TaxBaik.Application.Tests.csproj", "{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaxBaik.Web.Client", "TaxBaik.Web.Client\TaxBaik.Web.Client.csproj", "{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -83,6 +85,18 @@ Global
|
|||||||
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x64.Build.0 = Release|Any CPU
|
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x86.ActiveCfg = Release|Any CPU
|
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x86.Build.0 = Release|Any CPU
|
{47D1F07D-F11B-4343-A3C3-1872F0C46AE3}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C46C51D4-9E87-47DF-AB76-2E794F64FD5F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user