From 7c557e20113e1efb82c739fc8311d24268763f05 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Wed, 10 Dec 2025 17:27:18 +0100 Subject: [PATCH 01/20] Basic E2E test --- .../test/E2ETest/Tests/TempDataTest.cs | 41 +++++++++++ .../Pages/TempData/TempDataComponent.razor | 68 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/Components/test/E2ETest/Tests/TempDataTest.cs create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor diff --git a/src/Components/test/E2ETest/Tests/TempDataTest.cs b/src/Components/test/E2ETest/Tests/TempDataTest.cs new file mode 100644 index 000000000000..ff3d0e205c86 --- /dev/null +++ b/src/Components/test/E2ETest/Tests/TempDataTest.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Components.TestServer.RazorComponents; +using Microsoft.AspNetCore.E2ETesting; +using Xunit.Abstractions; +using OpenQA.Selenium; +using TestServer; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests; + +public class TempDataTest : ServerTestBase>> +{ + public TempDataTest( + BrowserFixture browserFixture, + BasicTestAppServerSiteFixture> serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + public override Task InitializeAsync() => InitializeAsync(BrowserFixture.StreamingContext); + + [Fact] + public void TempDataCanPersistThroughNavigation() + { + Navigate($"{ServerPathBase}/tempdata"); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.FindElement(By.Id("navigate-to-the-same-page")).Click(); + + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + } + + //TO-DO: Add test for Peek() + //TO-DO: Add test for Keep() + //TO-DO: Add test for Keep(string) +} diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor new file mode 100644 index 000000000000..1fa878c07b47 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor @@ -0,0 +1,68 @@ +@page "/tempdata" +@using Microsoft.AspNetCore.Components.Forms +@inject NavigationManager NavigationManager + +

TempData Basic Test

+ +
Ready
+ +
+ + + + +
+ + + + +
+ +

@_message

+

@_peekedValue

+

@_keptValue

+ + +@code { + [CascadingParameter] + public ITempData? TempData { get; set; } + + [SupplyParameterFromQuery] + public bool ShouldKeep { get; set; } + + private string? _message; + private string? _peekedValue; + private string? _keptValue; + + protected override void OnInitialized() + { + if (TempData is null) + { + return; + } + _message = TempData.Get("Message") as string; + _message ??= "No message"; + _peekedValue = TempData.Peek("PeekedValue") as string; + _peekedValue ??= "No peeked value"; + _keptValue = TempData.Get("KeptValue") as string; + _keptValue ??= "No kept value"; + if (ShouldKeep && _keptValue is not null) + { + TempData.Keep("KeptValue"); + } + } + + private void SetValues() + { + if (TempData is null) + { + return; + } + + TempData["Message"] = "Message"; + TempData["PeekedValue"] = "Peeked value"; + TempData["KeptValue"] = "Kept valie"; + } + + private void NavigateToSamePage() => NavigationManager.NavigateTo("/subdir/tempdata", forceLoad: true); +} From 8f21417dc90cfa77869a5d4bc8fef1ead3c1bbb9 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Wed, 10 Dec 2025 17:27:48 +0100 Subject: [PATCH 02/20] First simple implementation that holds values no matter what --- src/Components/Components/src/ITempData.cs | 15 ++++++ .../Components/src/PublicAPI.Unshipped.txt | 15 ++++++ src/Components/Components/src/TempData.cs | 48 +++++++++++++++++++ ...orComponentsServiceCollectionExtensions.cs | 4 ++ 4 files changed, 82 insertions(+) create mode 100644 src/Components/Components/src/ITempData.cs create mode 100644 src/Components/Components/src/TempData.cs diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Components/src/ITempData.cs new file mode 100644 index 000000000000..994eaea7fc28 --- /dev/null +++ b/src/Components/Components/src/ITempData.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components; + +public interface ITempData +{ + object? this[string key] { get; set; } + object? Get(string key); + object? Peek(string key); + void Keep(); + void Keep(string key); + + //TO-DO: Add Save to save and clean-up after request +} diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..d8638dab5502 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -1 +1,16 @@ #nullable enable +Microsoft.AspNetCore.Components.ITempData +Microsoft.AspNetCore.Components.ITempData.Get(string! key) -> object? +Microsoft.AspNetCore.Components.ITempData.Keep() -> void +Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void +Microsoft.AspNetCore.Components.ITempData.this[string! key].get -> object? +Microsoft.AspNetCore.Components.ITempData.this[string! key].set -> void +Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? +Microsoft.AspNetCore.Components.TempData +Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? +Microsoft.AspNetCore.Components.TempData.Keep() -> void +Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void +Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object? +Microsoft.AspNetCore.Components.TempData.TempData() -> void +Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? +Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs new file mode 100644 index 000000000000..9452529001d9 --- /dev/null +++ b/src/Components/Components/src/TempData.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components; + +/// +public class TempData : ITempData +{ + private readonly Dictionary _data = new(); + private readonly HashSet _retainedKeys = new(); + + /// + public object? this[string key] + { + get => Get(key); + set => _data[key] = value; + } + + /// + public object? Get(string key) + { + return _data.TryGetValue(key, out var value) ? value : null; + } + + /// + public object? Peek(string key) + { + return _data.TryGetValue(key, out var value) ? value : null; + } + + /// + public void Keep() + { + foreach (var key in _data.Keys) + { + _retainedKeys.Add(key); + } + } + + /// + public void Keep(string key) + { + if (_data.ContainsKey(key)) + { + _retainedKeys.Add(key); + } + } +} diff --git a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs index dc365194fcbe..f6f6c191147e 100644 --- a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs +++ b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs @@ -75,6 +75,10 @@ public static IRazorComponentsBuilder AddRazorComponents(this IServiceCollection services.TryAddScoped(); services.TryAddScoped(); + // TO-DO: Change this for TempData to work correctly + services.TryAddSingleton(); + services.TryAddCascadingValue(sp => sp.GetRequiredService()); + services.TryAddScoped(); RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration(services, RenderMode.InteractiveWebAssembly); From 43608b0d1fecc4de7f6e1077b7906cee103755f3 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Thu, 11 Dec 2025 14:28:48 +0100 Subject: [PATCH 03/20] Made TempData connected to the HttpContext and improved TempData --- src/Components/Components/src/ITempData.cs | 2 - .../Components/src/PublicAPI.Unshipped.txt | 2 + src/Components/Components/src/TempData.cs | 34 +++- ...orComponentsServiceCollectionExtensions.cs | 24 ++- .../DependencyInjection/TempDataService.cs | 154 ++++++++++++++++++ 5 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 src/Components/Endpoints/src/DependencyInjection/TempDataService.cs diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Components/src/ITempData.cs index 994eaea7fc28..e8bf308629cf 100644 --- a/src/Components/Components/src/ITempData.cs +++ b/src/Components/Components/src/ITempData.cs @@ -10,6 +10,4 @@ public interface ITempData object? Peek(string key); void Keep(); void Keep(string key); - - //TO-DO: Add Save to save and clean-up after request } diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index d8638dab5502..2ceba88090dd 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -8,8 +8,10 @@ Microsoft.AspNetCore.Components.ITempData.this[string! key].set -> void Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? Microsoft.AspNetCore.Components.TempData Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? +Microsoft.AspNetCore.Components.TempData.GetDataToSave() -> System.Collections.Generic.IDictionary! Microsoft.AspNetCore.Components.TempData.Keep() -> void Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void +Microsoft.AspNetCore.Components.TempData.LoadDataFromCookie(System.Collections.Generic.IDictionary! data) -> void Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object? Microsoft.AspNetCore.Components.TempData.TempData() -> void Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs index 9452529001d9..93ebe73b7e24 100644 --- a/src/Components/Components/src/TempData.cs +++ b/src/Components/Components/src/TempData.cs @@ -13,19 +13,24 @@ public class TempData : ITempData public object? this[string key] { get => Get(key); - set => _data[key] = value; + set + { + _data[key] = value; + _retainedKeys.Add(key); + } } /// public object? Get(string key) { - return _data.TryGetValue(key, out var value) ? value : null; + _retainedKeys.Remove(key); + return _data.GetValueOrDefault(key); } /// public object? Peek(string key) { - return _data.TryGetValue(key, out var value) ? value : null; + return _data.GetValueOrDefault(key); } /// @@ -45,4 +50,27 @@ public void Keep(string key) _retainedKeys.Add(key); } } + + /// + public IDictionary GetDataToSave() + { + var dataToSave = new Dictionary(); + foreach (var key in _retainedKeys) + { + dataToSave[key] = _data[key]; + } + return dataToSave; + } + + /// + public void LoadDataFromCookie(IDictionary data) + { + _data.Clear(); + _retainedKeys.Clear(); + foreach (var kvp in data) + { + _data[kvp.Key] = kvp.Value; + _retainedKeys.Add(kvp.Key); + } + } } diff --git a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs index f6f6c191147e..4e3a0bd2a49f 100644 --- a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs +++ b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs @@ -74,10 +74,26 @@ public static IRazorComponentsBuilder AddRazorComponents(this IServiceCollection services.TryAddCascadingValue(sp => sp.GetRequiredService().HttpContext); services.TryAddScoped(); services.TryAddScoped(); - - // TO-DO: Change this for TempData to work correctly - services.TryAddSingleton(); - services.TryAddCascadingValue(sp => sp.GetRequiredService()); + services.TryAddCascadingValue(sp => + { + var httpContext = sp.GetRequiredService().HttpContext; + if (httpContext is null) + { + return null!; + } + var key = typeof(ITempData); + if (!httpContext.Items.TryGetValue(key, out var tempData)) + { + var tempDataInstance = TempDataService.Load(httpContext); + httpContext.Items[key] = tempDataInstance; + httpContext.Response.OnStarting(() => + { + TempDataService.Save(httpContext, tempDataInstance); + return Task.CompletedTask; + }); + } + return (ITempData)httpContext.Items[key]!; + }); services.TryAddScoped(); RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration(services, RenderMode.InteractiveWebAssembly); diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs new file mode 100644 index 000000000000..1a3ffcd4ca89 --- /dev/null +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -0,0 +1,154 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.Json; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Components.Endpoints; + +internal sealed class TempDataService +{ + private const string CookieName = ".AspNetCore.Components.TempData"; + + public TempDataService() + { + // TO-DO: Add encoding later if needed + } + + public static TempData Load(HttpContext httpContext) + { + var returnTempData = new TempData(); + var serializedDataFromCookie = httpContext.Request.Cookies[CookieName]; + if (serializedDataFromCookie is null) + { + return returnTempData; + } + + var dataFromCookie = JsonSerializer.Deserialize>(serializedDataFromCookie); + if (dataFromCookie is null) + { + return returnTempData; + } + + var convertedData = new Dictionary(); + foreach (var kvp in dataFromCookie) + { + convertedData[kvp.Key] = ConvertJsonElement(kvp.Value); + } + + returnTempData.LoadDataFromCookie(convertedData); + return returnTempData; + } + + private static object? ConvertJsonElement(JsonElement element) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + if (element.TryGetGuid(out var guid)) + { + return guid; + } + if (element.TryGetDateTime(out var dateTime)) + { + return dateTime; + } + return element.GetString(); + case JsonValueKind.Number: + return element.GetInt32(); + case JsonValueKind.True: + case JsonValueKind.False: + return element.GetBoolean(); + case JsonValueKind.Null: + return null; + case JsonValueKind.Array: + return DeserializeArray(element); + case JsonValueKind.Object: + return DeserializeDictionaryEntry(element); + default: + throw new InvalidOperationException($"TempData cannot deserialize value of type '{element.ValueKind}'."); + } + } + + private static object? DeserializeArray(JsonElement arrayElement) + { + var arrayLength = arrayElement.GetArrayLength(); + if (arrayLength == 0) + { + return null; + } + if (arrayElement[0].ValueKind == JsonValueKind.String) + { + var array = new List(arrayLength); + foreach (var item in arrayElement.EnumerateArray()) + { + array.Add(item.GetString()); + } + return array.ToArray(); + } + else if (arrayElement[0].ValueKind == JsonValueKind.Number) + { + var array = new List(arrayLength); + foreach (var item in arrayElement.EnumerateArray()) + { + array.Add(item.GetInt32()); + } + return array.ToArray(); + } + throw new InvalidOperationException($"TempData cannot deserialize array of type '{arrayElement[0].ValueKind}'."); + } + + private static Dictionary DeserializeDictionaryEntry(JsonElement objectElement) + { + var dictionary = new Dictionary(StringComparer.Ordinal); + foreach (var item in objectElement.EnumerateObject()) + { + dictionary[item.Name] = item.Value.GetString(); + } + return dictionary; + } + + public static void Save(HttpContext httpContext, TempData tempData) + { + var dataToSave = tempData.GetDataToSave(); + foreach (var kvp in dataToSave) + { + if (!CanSerializeType(kvp.Value?.GetType() ?? typeof(object))) + { + throw new InvalidOperationException($"TempData cannot store values of type '{kvp.Value?.GetType()}'."); + } + } + + if (dataToSave.Count == 0) + { + httpContext.Response.Cookies.Delete(CookieName, new CookieOptions + { + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + return; + } + httpContext.Response.Cookies.Append(CookieName, JsonSerializer.Serialize(dataToSave), new CookieOptions + { + HttpOnly = true, + IsEssential = true, + SameSite = SameSiteMode.Lax, + Secure = httpContext.Request.IsHttps, + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + } + + private static bool CanSerializeType(Type type) + { + type = Nullable.GetUnderlyingType(type) ?? type; + return + type.IsEnum || + type == typeof(int) || + type == typeof(string) || + type == typeof(bool) || + type == typeof(DateTime) || + type == typeof(Guid) || + typeof(ICollection).IsAssignableFrom(type) || + typeof(ICollection).IsAssignableFrom(type) || + typeof(IDictionary).IsAssignableFrom(type); + } +} From 5612308144266619133b22998fb4a757a3e85caa Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Thu, 11 Dec 2025 14:29:03 +0100 Subject: [PATCH 04/20] Fixed E2E test to be SSR --- src/Components/test/E2ETest/Tests/TempDataTest.cs | 5 ++--- .../Pages/TempData/TempDataComponent.razor | 8 ++------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Components/test/E2ETest/Tests/TempDataTest.cs b/src/Components/test/E2ETest/Tests/TempDataTest.cs index ff3d0e205c86..db15f3e2abc7 100644 --- a/src/Components/test/E2ETest/Tests/TempDataTest.cs +++ b/src/Components/test/E2ETest/Tests/TempDataTest.cs @@ -11,11 +11,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests; -public class TempDataTest : ServerTestBase>> +public class TempDataTest : ServerTestBase>> { public TempDataTest( BrowserFixture browserFixture, - BasicTestAppServerSiteFixture> serverFixture, + BasicTestAppServerSiteFixture> serverFixture, ITestOutputHelper output) : base(browserFixture, serverFixture, output) { @@ -30,7 +30,6 @@ public void TempDataCanPersistThroughNavigation() Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); Browser.FindElement(By.Id("set-values-button")).Click(); - Browser.FindElement(By.Id("navigate-to-the-same-page")).Click(); Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor index 1fa878c07b47..457994644a38 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor @@ -11,11 +11,6 @@ -
- - - -

@_message

@@ -61,7 +56,8 @@ TempData["Message"] = "Message"; TempData["PeekedValue"] = "Peeked value"; - TempData["KeptValue"] = "Kept valie"; + TempData["KeptValue"] = "Kept value"; + NavigateToSamePage(); } private void NavigateToSamePage() => NavigationManager.NavigateTo("/subdir/tempdata", forceLoad: true); From c73f3708c892144dc14a66f37576fa5c6a32d8f5 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Thu, 11 Dec 2025 18:05:06 +0100 Subject: [PATCH 05/20] Add for manual testing --- src/Components/test/testassets/Components.TestServer/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/test/testassets/Components.TestServer/Program.cs b/src/Components/test/testassets/Components.TestServer/Program.cs index 2f06b00b72ac..f42fbdc26f2e 100644 --- a/src/Components/test/testassets/Components.TestServer/Program.cs +++ b/src/Components/test/testassets/Components.TestServer/Program.cs @@ -38,6 +38,7 @@ public static async Task Main(string[] args) ["Hot Reload"] = (BuildWebHost(CreateAdditionalArgs(args)), "/subdir"), ["Dev server client-side blazor"] = CreateDevServerHost(CreateAdditionalArgs(args)), ["Global Interactivity"] = (BuildWebHost>(CreateAdditionalArgs(args)), "/subdir"), + ["SSR (No Interactivity)"] = (BuildWebHost>(CreateAdditionalArgs(args)), "/subdir"), }; var mainHost = BuildWebHost(args); From 9948bcdce0ff31d63ec82e6e69ea85283ba5d16b Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Fri, 12 Dec 2025 15:20:39 +0100 Subject: [PATCH 06/20] Added new E2E tests --- .../test/E2ETest/Tests/TempDataTest.cs | 52 +++++++++++++++- .../Pages/TempData/TempDataComponent.razor | 59 ++++++++++++------- .../TempData/TempDataReadComponent.razor | 33 +++++++++++ 3 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataReadComponent.razor diff --git a/src/Components/test/E2ETest/Tests/TempDataTest.cs b/src/Components/test/E2ETest/Tests/TempDataTest.cs index db15f3e2abc7..4b8d12377dcf 100644 --- a/src/Components/test/E2ETest/Tests/TempDataTest.cs +++ b/src/Components/test/E2ETest/Tests/TempDataTest.cs @@ -27,14 +27,60 @@ public TempDataTest( public void TempDataCanPersistThroughNavigation() { Navigate($"{ServerPathBase}/tempdata"); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + } + [Fact] + public void TempDataCanPersistThroughDifferentPages() + { + Navigate($"{ServerPathBase}/tempdata"); + + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("set-values-button-diff-page")).Click(); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + } + + [Fact] + public void TempDataPeekDoesntDelete() + { + Navigate($"{ServerPathBase}/tempdata"); + + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("redirect-button")).Click(); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.Equal("Peeked value", () => Browser.FindElement(By.Id("peeked-value")).Text); + } + [Fact] + public void TempDataKeepAllElements() + { + Navigate($"{ServerPathBase}/tempdata?ValueToKeep=all"); + + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("Kept value", () => Browser.FindElement(By.Id("kept-value")).Text); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("redirect-button")).Click(); + Browser.Equal("Kept value", () => Browser.FindElement(By.Id("kept-value")).Text); Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); } - //TO-DO: Add test for Peek() - //TO-DO: Add test for Keep() - //TO-DO: Add test for Keep(string) + [Fact] + public void TempDataKeepOneElement() + { + Navigate($"{ServerPathBase}/tempdata?ValueToKeep=KeptValue"); + + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("Kept value", () => Browser.FindElement(By.Id("kept-value")).Text); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("redirect-button")).Click(); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.Equal("Kept value", () => Browser.FindElement(By.Id("kept-value")).Text); + } } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor index 457994644a38..8a89af87b654 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor @@ -4,13 +4,21 @@

TempData Basic Test

-
Ready
- -
+ +
+ + + + +
+ + + +

@_message

@@ -19,11 +27,14 @@ @code { + [SupplyParameterFromForm(Name = "_handler")] + public string? Handler { get; set; } + [CascadingParameter] public ITempData? TempData { get; set; } [SupplyParameterFromQuery] - public bool ShouldKeep { get; set; } + public string ValueToKeep { get; set; } = string.Empty; private string? _message; private string? _peekedValue; @@ -31,34 +42,40 @@ protected override void OnInitialized() { - if (TempData is null) + if (Handler is not null) { return; } - _message = TempData.Get("Message") as string; - _message ??= "No message"; - _peekedValue = TempData.Peek("PeekedValue") as string; - _peekedValue ??= "No peeked value"; - _keptValue = TempData.Get("KeptValue") as string; - _keptValue ??= "No kept value"; - if (ShouldKeep && _keptValue is not null) + _message = TempData!.Get("Message") as string ?? "No message"; + _peekedValue = TempData!.Peek("PeekedValue") as string ?? "No peeked value"; + _keptValue = TempData!.Get("KeptValue") as string ?? "No kept value"; + + Console.WriteLine("ValueToKeep = " + ValueToKeep); + + if (ValueToKeep == "all") { - TempData.Keep("KeptValue"); + TempData!.Keep(); } - } + else if (!string.IsNullOrEmpty(ValueToKeep)) + { + TempData!.Keep(ValueToKeep); + } + } - private void SetValues() + private void SetValues(bool differentPage = false) { - if (TempData is null) + TempData!["Message"] = "Message"; + TempData!["PeekedValue"] = "Peeked value"; + TempData!["KeptValue"] = "Kept value"; + if (differentPage) { + NavigateToDifferentPage(); return; } - - TempData["Message"] = "Message"; - TempData["PeekedValue"] = "Peeked value"; - TempData["KeptValue"] = "Kept value"; - NavigateToSamePage(); + NavigateToSamePageKeep(ValueToKeep); } private void NavigateToSamePage() => NavigationManager.NavigateTo("/subdir/tempdata", forceLoad: true); + private void NavigateToSamePageKeep(string valueToKeep) => NavigationManager.NavigateTo($"/subdir/tempdata?ValueToKeep={valueToKeep}", forceLoad: true); + private void NavigateToDifferentPage() => NavigationManager.NavigateTo("/subdir/tempdata/read", forceLoad: true); } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataReadComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataReadComponent.razor new file mode 100644 index 000000000000..950e58e1c24b --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataReadComponent.razor @@ -0,0 +1,33 @@ +@page "/tempdata/read" +@using Microsoft.AspNetCore.Components.Forms +@inject NavigationManager NavigationManager + +

TempData Read Test

+ +

@_message

+

@_peekedValue

+

@_keptValue

+ + +@code { + [CascadingParameter] + public ITempData? TempData { get; set; } + + private string? _message; + private string? _peekedValue; + private string? _keptValue; + + protected override void OnInitialized() + { + if (TempData is null) + { + return; + } + _message = TempData.Get("Message") as string; + _message ??= "No message"; + _peekedValue = TempData.Get("PeekedValue") as string; + _peekedValue ??= "No peeked value"; + _keptValue = TempData.Get("KeptValue") as string; + _keptValue ??= "No kept value"; + } +} From 9869aa7a3c94f15de4fb514fa756b66dbd3c8649 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Fri, 12 Dec 2025 16:09:39 +0100 Subject: [PATCH 07/20] Added XML comment --- src/Components/Components/src/ITempData.cs | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Components/src/ITempData.cs index e8bf308629cf..12ec4d4fc950 100644 --- a/src/Components/Components/src/ITempData.cs +++ b/src/Components/Components/src/ITempData.cs @@ -3,11 +3,35 @@ namespace Microsoft.AspNetCore.Components; +/// +/// Provides a dictionary for storing data that is needed for subsequent requests. +/// Data stored in TempData is automatically removed after it is read unless +/// or is called, or it is accessed via . +/// public interface ITempData { + /// + /// Gets or sets the value associated with the specified key. + /// object? this[string key] { get; set; } + + /// + /// Gets the value associated with the specified key and then schedules it for deletion. + /// object? Get(string key); + + /// + /// Gets the value associated with the specified key without scheduling it for deletion. + /// object? Peek(string key); + + /// + /// Makes all of the keys currently in TempData persist for another request. + /// void Keep(); + + /// + /// Makes the element with the persist for another request. + /// void Keep(string key); } From d93d2667de88dcf7bf197eb3078377021218e5ab Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Mon, 15 Dec 2025 11:54:49 +0100 Subject: [PATCH 08/20] Added new tests --- .../test/E2ETest/Tests/TempDataTest.cs | 40 +++++++++++++++++++ .../Pages/TempData/TempDataComponent.razor | 26 ++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/Components/test/E2ETest/Tests/TempDataTest.cs b/src/Components/test/E2ETest/Tests/TempDataTest.cs index 4b8d12377dcf..75ed38cdda2c 100644 --- a/src/Components/test/E2ETest/Tests/TempDataTest.cs +++ b/src/Components/test/E2ETest/Tests/TempDataTest.cs @@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests; public class TempDataTest : ServerTestBase>> { + private const string TempDataCookieName = ".AspNetCore.Components.TempData"; + public TempDataTest( BrowserFixture browserFixture, BasicTestAppServerSiteFixture> serverFixture, @@ -23,6 +25,12 @@ public TempDataTest( public override Task InitializeAsync() => InitializeAsync(BrowserFixture.StreamingContext); + protected override void InitializeAsyncCore() + { + base.InitializeAsyncCore(); + Browser.Manage().Cookies.DeleteCookieNamed(TempDataCookieName); + } + [Fact] public void TempDataCanPersistThroughNavigation() { @@ -83,4 +91,36 @@ public void TempDataKeepOneElement() Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); Browser.Equal("Kept value", () => Browser.FindElement(By.Id("kept-value")).Text); } + + [Fact] + public void CanRemoveTheElementWithRemove() + { + Navigate($"{ServerPathBase}/tempdata"); + + Browser.Equal("No peeked value", () => Browser.FindElement(By.Id("peeked-value")).Text); + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("Peeked value", () => Browser.FindElement(By.Id("peeked-value")).Text); + Browser.Equal("Message", () => Browser.FindElement(By.Id("message")).Text); + Browser.FindElement(By.Id("redirect-button")).Click(); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.Equal("Peeked value", () => Browser.FindElement(By.Id("peeked-value")).Text); + Browser.FindElement(By.Id("delete-button")).Click(); + Browser.Equal("No message", () => Browser.FindElement(By.Id("message")).Text); + Browser.Equal("No peeked value", () => Browser.FindElement(By.Id("peeked-value")).Text); + } + + [Fact] + public void CanCheckIfTempDataContainsKey() + { + Navigate($"{ServerPathBase}/tempdata"); + + Browser.Equal("False", () => Browser.FindElement(By.Id("contains-peeked-value")).Text); + Browser.Equal("False", () => Browser.FindElement(By.Id("contains-message")).Text); + Browser.FindElement(By.Id("set-values-button")).Click(); + Browser.Equal("True", () => Browser.FindElement(By.Id("contains-peeked-value")).Text); + Browser.Equal("True", () => Browser.FindElement(By.Id("contains-message")).Text); + Browser.FindElement(By.Id("redirect-button")).Click(); + Browser.Equal("True", () => Browser.FindElement(By.Id("contains-peeked-value")).Text); + Browser.Equal("False", () => Browser.FindElement(By.Id("contains-message")).Text); + } } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor index 8a89af87b654..ed4ce0680f49 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/TempData/TempDataComponent.razor @@ -19,12 +19,19 @@ +
+ + + +

@_message

@_peekedValue

@_keptValue

+

@_containsMessageKey

+

@_containsPeekedValueKey

@code { [SupplyParameterFromForm(Name = "_handler")] @@ -36,12 +43,21 @@ [SupplyParameterFromQuery] public string ValueToKeep { get; set; } = string.Empty; + [SupplyParameterFromQuery] + public string ContainsKey { get; set; } = string.Empty; + private string? _message; private string? _peekedValue; private string? _keptValue; + private bool _containsMessageKey; + private bool _containsPeekedValueKey; + protected override void OnInitialized() { + _containsMessageKey = TempData?.ContainsKey("Message") ?? false; + _containsPeekedValueKey = TempData?.ContainsKey("PeekedValue") ?? false; + if (Handler is not null) { return; @@ -50,8 +66,6 @@ _peekedValue = TempData!.Peek("PeekedValue") as string ?? "No peeked value"; _keptValue = TempData!.Get("KeptValue") as string ?? "No kept value"; - Console.WriteLine("ValueToKeep = " + ValueToKeep); - if (ValueToKeep == "all") { TempData!.Keep(); @@ -60,7 +74,7 @@ { TempData!.Keep(ValueToKeep); } - } + } private void SetValues(bool differentPage = false) { @@ -75,6 +89,12 @@ NavigateToSamePageKeep(ValueToKeep); } + private void DeletePeekedValue() + { + TempData!.Remove("PeekedValue"); + NavigateToSamePage(); + } + private void NavigateToSamePage() => NavigationManager.NavigateTo("/subdir/tempdata", forceLoad: true); private void NavigateToSamePageKeep(string valueToKeep) => NavigationManager.NavigateTo($"/subdir/tempdata?ValueToKeep={valueToKeep}", forceLoad: true); private void NavigateToDifferentPage() => NavigationManager.NavigateTo("/subdir/tempdata/read", forceLoad: true); From 7630764b6f75add74406281244fb3fc8681217f2 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Mon, 15 Dec 2025 12:05:42 +0100 Subject: [PATCH 09/20] Added inheritance from IDictionary --- src/Components/Components/src/ITempData.cs | 7 +- .../Components/src/PublicAPI.Unshipped.txt | 15 +-- src/Components/Components/src/TempData.cs | 93 +++++++++++++++++-- .../DependencyInjection/TempDataService.cs | 4 +- 4 files changed, 97 insertions(+), 22 deletions(-) diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Components/src/ITempData.cs index 12ec4d4fc950..70f637e7af6e 100644 --- a/src/Components/Components/src/ITempData.cs +++ b/src/Components/Components/src/ITempData.cs @@ -8,13 +8,8 @@ namespace Microsoft.AspNetCore.Components; /// Data stored in TempData is automatically removed after it is read unless /// or is called, or it is accessed via . /// -public interface ITempData +public interface ITempData : IDictionary { - /// - /// Gets or sets the value associated with the specified key. - /// - object? this[string key] { get; set; } - /// /// Gets the value associated with the specified key and then schedules it for deletion. /// diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index ff40a15ce028..9db8dbad4fdc 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -3,19 +3,20 @@ Microsoft.AspNetCore.Components.ITempData Microsoft.AspNetCore.Components.ITempData.Get(string! key) -> object? Microsoft.AspNetCore.Components.ITempData.Keep() -> void Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void -Microsoft.AspNetCore.Components.ITempData.this[string! key].get -> object? -Microsoft.AspNetCore.Components.ITempData.this[string! key].set -> void Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? Microsoft.AspNetCore.Components.TempData +Microsoft.AspNetCore.Components.TempData.TempData() -> void Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? -Microsoft.AspNetCore.Components.TempData.GetDataToSave() -> System.Collections.Generic.IDictionary! +Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? +Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void Microsoft.AspNetCore.Components.TempData.Keep() -> void Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void -Microsoft.AspNetCore.Components.TempData.LoadDataFromCookie(System.Collections.Generic.IDictionary! data) -> void Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object? -Microsoft.AspNetCore.Components.TempData.TempData() -> void -Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? -Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void +Microsoft.AspNetCore.Components.TempData.Clear() -> void +Microsoft.AspNetCore.Components.TempData.Remove(string! key) -> bool +Microsoft.AspNetCore.Components.TempData.ContainsKey(string! key) -> bool +Microsoft.AspNetCore.Components.TempData.Load(System.Collections.Generic.IDictionary! data) -> void +Microsoft.AspNetCore.Components.TempData.Save() -> System.Collections.Generic.IDictionary! *REMOVED*Microsoft.AspNetCore.Components.ResourceAsset.ResourceAsset(string! url, System.Collections.Generic.IReadOnlyList? properties) -> void *REMOVED*Microsoft.AspNetCore.Components.Routing.Router.PreferExactMatches.get -> bool *REMOVED*Microsoft.AspNetCore.Components.Routing.Router.PreferExactMatches.set -> void diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs index 93ebe73b7e24..54fe807f1a4b 100644 --- a/src/Components/Components/src/TempData.cs +++ b/src/Components/Components/src/TempData.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; + namespace Microsoft.AspNetCore.Components; /// @@ -36,10 +38,8 @@ public object? this[string key] /// public void Keep() { - foreach (var key in _data.Keys) - { - _retainedKeys.Add(key); - } + _retainedKeys.Clear(); + _retainedKeys.UnionWith(_data.Keys); } /// @@ -52,7 +52,22 @@ public void Keep(string key) } /// - public IDictionary GetDataToSave() + public bool ContainsKey(string key) + { + return _data.ContainsKey(key); + } + + /// + public bool Remove(string key) + { + _retainedKeys.Remove(key); + return _data.Remove(key); + } + + /// + /// Gets the data that should be saved for the next request. + /// + public IDictionary Save() { var dataToSave = new Dictionary(); foreach (var key in _retainedKeys) @@ -62,8 +77,10 @@ public void Keep(string key) return dataToSave; } - /// - public void LoadDataFromCookie(IDictionary data) + /// + /// Loads data from a into the TempData dictionary. + /// + public void Load(IDictionary data) { _data.Clear(); _retainedKeys.Clear(); @@ -73,4 +90,66 @@ public void LoadDataFromCookie(IDictionary data) _retainedKeys.Add(kvp.Key); } } + + /// + public void Clear() + { + _data.Clear(); + _retainedKeys.Clear(); + } + + ICollection IDictionary.Keys => _data.Keys; + + ICollection IDictionary.Values => _data.Values; + + int ICollection>.Count => _data.Count; + + bool ICollection>.IsReadOnly => ((ICollection>)_data).IsReadOnly; + + void IDictionary.Add(string key, object? value) + { + _data.Add(key, value); + _retainedKeys.Add(key); + } + + bool IDictionary.TryGetValue(string key, out object? value) + { + _retainedKeys.Remove(key); + return _data.TryGetValue(key, out value); + } + + void ICollection>.Add(KeyValuePair item) + { + ((IDictionary)this).Add(item.Key, item.Value); + } + + bool ICollection>.Contains(KeyValuePair item) + { + return ContainsKey(item.Key) && _data[item.Key] == item.Value; + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((ICollection>)_data).CopyTo(array, arrayIndex); + } + + bool ICollection>.Remove(KeyValuePair item) + { + if (((ICollection>)_data).Remove(item)) + { + _retainedKeys.Remove(item.Key); + return true; + } + return false; + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } } diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index 1a3ffcd4ca89..09374cf8ab9b 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -36,7 +36,7 @@ public static TempData Load(HttpContext httpContext) convertedData[kvp.Key] = ConvertJsonElement(kvp.Value); } - returnTempData.LoadDataFromCookie(convertedData); + returnTempData.Load(convertedData); return returnTempData; } @@ -110,7 +110,7 @@ public static TempData Load(HttpContext httpContext) public static void Save(HttpContext httpContext, TempData tempData) { - var dataToSave = tempData.GetDataToSave(); + var dataToSave = tempData.Save(); foreach (var kvp in dataToSave) { if (!CanSerializeType(kvp.Value?.GetType() ?? typeof(object))) From 8b5bbe2e41b12aa97d7a95b5f56cc74314863e06 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Mon, 15 Dec 2025 14:38:02 +0100 Subject: [PATCH 10/20] Added IDataProtector to TempDataService --- src/Components/Components.sln | 660 ++++++++++++++++++ .../DependencyInjection/TempDataService.cs | 77 +- 2 files changed, 705 insertions(+), 32 deletions(-) create mode 100644 src/Components/Components.sln diff --git a/src/Components/Components.sln b/src/Components/Components.sln new file mode 100644 index 000000000000..852246120981 --- /dev/null +++ b/src/Components/Components.sln @@ -0,0 +1,660 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{F883AD26-E2D9-0064-49F2-B333EF800629}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authorization", "Authorization", "{278F3FFB-8C21-435B-507F-61B78986A400}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{04B96F53-E713-70DE-173F-A95873598AF4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{F30895DC-C3AC-FF44-FFF8-D51D98AE1B61}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CustomElements", "CustomElements", "{1956B0E3-C3A6-1D29-BB64-D91F2292772C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Endpoints", "Endpoints", "{DCF9C18E-19C8-9748-4C1C-32AB5F62F46B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Forms", "Forms", "{5D4ABE75-A633-7578-A6F0-BB88D48E78A4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{5D20AA90-6969-D8BD-9DCD-8634F4692FDA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0C88DD14-F956-CE84-757C-A364CCF449FC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{256F4E96-6A73-9ABE-786F-840C672A50F4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QuickGrid", "QuickGrid", "{453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{032573FE-E973-EE49-F164-6E17D60C24C1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebView", "WebView", "{F75C3326-23C9-B46B-1CDE-63D2E405EED1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7188C2C0-F586-2E1C-E0B5-5DFC1FABF135}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Analyzers", "Analyzers\src\Microsoft.AspNetCore.Components.Analyzers.csproj", "{E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B4DAA744-D941-8AA5-7BB9-26961FB2C0FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Analyzers.Tests", "Analyzers\test\Microsoft.AspNetCore.Components.Analyzers.Tests.csproj", "{EB0043B9-6579-7370-BED1-D06FE9DFC755}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9EA3DC81-E26A-677F-6A25-3A91573DF4FE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Authorization", "Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj", "{BD2C8FC3-3703-7EF9-4551-70298314EF37}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Authorization.Tests", "Authorization\test\Microsoft.AspNetCore.Components.Authorization.Tests.csproj", "{CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazingPizza.Server", "benchmarkapps\BlazingPizza.Server\BlazingPizza.Server.csproj", "{A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{D27B063A-B8D1-101F-0A9A-82D5880B0092}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Performance", "Components\perf\Microsoft.AspNetCore.Components.Performance.csproj", "{99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B2FBA576-327C-1BE5-E29F-D95D457F7733}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components", "Components\src\Microsoft.AspNetCore.Components.csproj", "{C45B3BA4-7E52-73AB-4942-5899597D4C36}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5E7128C-C6CF-3B49-7306-A9D6E76AC385}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Tests", "Components\test\Microsoft.AspNetCore.Components.Tests.csproj", "{D554BB1E-51B7-3752-8566-135C9ADB7DCA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C1BECA30-1B7A-2AD9-E261-E8D798C74B5D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.CustomElements", "CustomElements\src\Microsoft.AspNetCore.Components.CustomElements.csproj", "{AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8E784D3B-3E6B-7A86-D8E3-544301E375D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Endpoints", "Endpoints\src\Microsoft.AspNetCore.Components.Endpoints.csproj", "{E8540B19-EB66-03C6-13D2-6EE233C61524}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Endpoints.Tests", "Endpoints\test\Microsoft.AspNetCore.Components.Endpoints.Tests.csproj", "{9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{97E78C61-B29B-A484-4CE9-4BB29EB9331A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Forms", "Forms\src\Microsoft.AspNetCore.Components.Forms.csproj", "{AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BD4137AF-3EE6-D962-BF72-9904BFD46A79}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Forms.Tests", "Forms\test\Microsoft.AspNetCore.Components.Forms.Tests.csproj", "{D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorServerApp", "Samples\BlazorServerApp\BlazorServerApp.csproj", "{FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorUnitedApp", "Samples\BlazorUnitedApp\BlazorUnitedApp.csproj", "{74BEC791-7060-4E1D-E77C-2490EFE2DFD0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorUnitedApp.Client", "Samples\BlazorUnitedApp.Client\BlazorUnitedApp.Client.csproj", "{1FCE400C-3875-3963-2105-084823B55013}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Server", "Server\src\Microsoft.AspNetCore.Components.Server.csproj", "{3893606D-3E03-0FFD-95B4-A93121438268}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{968FF768-FCED-1723-7BDD-DA5CA8774CA7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Server.Tests", "Server\test\Microsoft.AspNetCore.Components.Server.Tests.csproj", "{8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "E2ETest", "E2ETest", "{B7885BA3-4776-F672-E8F6-B5866B779C62}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.E2ETests", "test\E2ETest\Microsoft.AspNetCore.Components.E2ETests.csproj", "{AEEBE2B8-B7E4-178C-5640-626E89EF0C75}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{228B02D4-B903-8A36-6CC3-E6BEA647CE1E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Web", "Web\src\Microsoft.AspNetCore.Components.Web.csproj", "{B6384FF0-6E94-4ADE-F932-F4E886C1CADD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{28716C4F-1493-E9A1-BA33-F0DEF262A65A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Web.Tests", "Web\test\Microsoft.AspNetCore.Components.Web.Tests.csproj", "{8F18837A-BB27-ECF0-C1AA-4838E1C2A781}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wasm.Performance", "Wasm.Performance", "{595095FC-11E7-9A6C-713C-1AA81E4007ED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConsoleHost", "ConsoleHost", "{09B1DD90-461D-BA25-543A-2B9E36909F2A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.ConsoleHost", "benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Driver", "Driver", "{8C1BB3C5-A56A-60F2-587A-1CDE499093FF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.Driver", "benchmarkapps\Wasm.Performance\Driver\Wasm.Performance.Driver.csproj", "{672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApp", "TestApp", "{8AED47D8-E613-0A63-AFBD-DB2A96051743}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{A4977A0A-A95B-7C35-F319-521331739C01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.AspNetCore.Components.QuickGrid", "Microsoft.AspNetCore.Components.QuickGrid", "{E329DD7B-EA06-0E35-2452-F0374B45C92D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EE8635E8-7069-5440-4C4D-3E712D0A6E31}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid\src\Microsoft.AspNetCore.Components.QuickGrid.csproj", "{8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8C21E68A-654B-F80C-2D42-F0D033850D3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid.Tests", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid\test\Microsoft.AspNetCore.Components.QuickGrid.Tests.csproj", "{D5F75C44-4165-6BB9-BB83-C01241D5775F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "{8B02DB0C-FE4B-328D-C414-580634248F4A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AB061C51-2A24-F88C-EF6D-0215BD882074}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter\src\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter.csproj", "{62F0E24C-EE9B-D5B3-D2CF-19358722D081}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicTestApp", "test\testassets\BasicTestApp\BasicTestApp.csproj", "{94769285-DE8C-43CF-8F43-2E6081DE261F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.TestServer", "test\testassets\Components.TestServer\Components.TestServer.csproj", "{005A99AE-9829-5288-081E-6AA2C7068F41}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.WasmMinimal", "test\testassets\Components.WasmMinimal\Components.WasmMinimal.csproj", "{384D771F-1D94-6B01-A1C3-435584F4B3BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.WasmRemoteAuthentication", "test\testassets\Components.WasmRemoteAuthentication\Components.WasmRemoteAuthentication.csproj", "{DA514A3D-030F-3753-55AC-95601ADF7FE9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.App", "test\testassets\ComponentsApp.App\ComponentsApp.App.csproj", "{FEEE3D25-53D4-9F34-27B7-CBC04873009F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{ACC68622-35F7-164F-FD1B-E68510FB877C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationWasmApp", "test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyTestContentPackage", "test\testassets\LazyTestContentPackage\LazyTestContentPackage.csproj", "{42C50CDC-3AF3-2866-9186-AE532C918BBA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotReferencedInWasmCodePackage", "test\testassets\NotReferencedInWasmCodePackage\NotReferencedInWasmCodePackage.csproj", "{0262DCC6-3D46-CBCE-4888-9F37FDAAE470}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestContentPackage", "test\testassets\TestContentPackage\TestContentPackage.csproj", "{B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication.Msal", "Authentication.Msal", "{A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{805B4876-2550-7ADC-2FD1-6362247661A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Authentication.WebAssembly.Msal", "WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj", "{3C135F94-99F0-BF85-CD5D-F2BD288FC230}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{5ED11752-357D-2F9A-0D62-6FBFEC2923EA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4030600A-B42C-7665-4E1E-9DEDBAF9080A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.DevServer", "WebAssembly\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj", "{8FC99803-7FB1-E7FD-F579-4FF49A324139}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JSInterop", "JSInterop", "{2D1527BB-743D-5D96-93C8-1B5741ADC02B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2CF24191-5ACD-5999-EAB4-F3ED6F833833}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.JSInterop.WebAssembly", "WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj", "{C004A041-806C-248D-6972-BC44CBD8AFDB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{F24703D6-F12F-EE78-E988-49EB11C8433B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A6DB63EE-406F-8FC6-244C-D0DECD2202FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Server", "WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj", "{69AB9EB3-9FB3-F134-F7BB-6F20719F293D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BC25C024-DEC1-AC57-3E67-CBE61A818765}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Server.Tests", "WebAssembly\Server\test\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj", "{D9D391EA-769E-A96E-D230-453C9B9365DE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{F60C0A93-E7A1-AA4F-C800-18D21FD1802D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomBasePathApp", "WebAssembly\testassets\CustomBasePathApp\CustomBasePathApp.csproj", "{F2EF8EC2-4C19-61B5-DCF4-9014E729C057}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Client", "WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{2EEDD992-0F07-908F-52D7-52E0D0816172}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Server", "WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneApp", "WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreadingApp", "WebAssembly\testassets\ThreadingApp\ThreadingApp.csproj", "{D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreadingApp.Server", "WebAssembly\testassets\ThreadingApp.Server\ThreadingApp.Server.csproj", "{FEF03057-3DED-46E9-44C2-E5A71183CBF7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Prerendered.Client", "WebAssembly\testassets\Wasm.Prerendered.Client\Wasm.Prerendered.Client.csproj", "{D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Prerendered.Server", "WebAssembly\testassets\Wasm.Prerendered.Server\Wasm.Prerendered.Server.csproj", "{E7C427B4-5DAA-2DEC-D4FE-25513848B07E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WasmLinkerTest", "WebAssembly\testassets\WasmLinkerTest\WasmLinkerTest.csproj", "{8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{2114FDDC-431A-A228-9FBD-A2D77B669641}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly", "WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj", "{72B9C791-DBD1-32DB-C566-B5D3B1D405E1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{73AD86C9-A183-63E1-9E65-08B4582D7CA4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Tests", "WebAssembly\WebAssembly\test\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "{F3C7C76A-FF30-4935-E238-7C5A838E3BCE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly.Authentication", "WebAssembly.Authentication", "{2C226B6F-947F-806E-AB56-5318C87BE998}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{728874E7-57EA-5300-FDDD-4A392F892C62}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Authentication", "WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj", "{585E4EE6-E918-DDEC-79AD-C956E6A19E4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests", "WebAssembly\WebAssembly.Authentication\test\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj", "{C80EB816-1E52-8D59-6C14-5567A23B5D82}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E199B8FB-B34C-E815-5C68-8C4C236C3F5B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "E2ETest", "E2ETest", "{BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebViewE2E.Test", "WebView\test\E2ETest\Microsoft.AspNetCore.Components.WebViewE2E.Test.csproj", "{C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebView", "WebView", "{CA12ED3E-B35C-B56F-F8CA-F6C9996B003D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{75F0ABB4-98D0-A880-0F84-660DB1C46419}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView", "WebView\WebView\src\Microsoft.AspNetCore.Components.WebView.csproj", "{491EE542-B9EB-10C7-06A2-6F2053C50482}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView.Test", "WebView\WebView\test\Microsoft.AspNetCore.Components.WebView.Test.csproj", "{BD1EEC86-7644-5761-1346-089385B5A749}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HostedBlazorWebassemblyApp", "HostedBlazorWebassemblyApp", "{D8364222-347F-695D-960D-5F83D75F4A3E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{493470CA-BAAC-C311-15C4-BEEB81EB0E42}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Client", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Client\HostedBlazorWebassemblyApp.Client.csproj", "{3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{D6A88611-6F2F-36CC-9E71-609E6DC6CBAE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Server", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Server\HostedBlazorWebassemblyApp.Server.csproj", "{A46AAF9E-39CC-085A-4EA7-A99537EA00E6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{59BF9900-BDFB-2E52-B7D0-CA27D2239E1E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Shared", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Shared\HostedBlazorWebassemblyApp.Shared.csproj", "{A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{6636F944-0A81-C8B7-09AA-414B5978CE4C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PhotinoPlatform", "PhotinoPlatform", "{316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView.Photino", "WebView\Samples\PhotinoPlatform\src\Microsoft.AspNetCore.Components.WebView.Photino.csproj", "{DFB12E12-A532-EF12-87F4-BD537FF1662F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{978EA837-C2CB-DF69-BCE3-815ADE704D37}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhotinoTestApp", "WebView\Samples\PhotinoPlatform\testassets\PhotinoTestApp\PhotinoTestApp.csproj", "{9201E12B-135F-5E14-0672-AB5561520397}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Release|Any CPU.Build.0 = Release|Any CPU + {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Release|Any CPU.Build.0 = Release|Any CPU + {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Release|Any CPU.Build.0 = Release|Any CPU + {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Release|Any CPU.Build.0 = Release|Any CPU + {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Release|Any CPU.Build.0 = Release|Any CPU + {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Release|Any CPU.Build.0 = Release|Any CPU + {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Release|Any CPU.Build.0 = Release|Any CPU + {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Release|Any CPU.Build.0 = Release|Any CPU + {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Release|Any CPU.Build.0 = Release|Any CPU + {E8540B19-EB66-03C6-13D2-6EE233C61524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8540B19-EB66-03C6-13D2-6EE233C61524}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8540B19-EB66-03C6-13D2-6EE233C61524}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8540B19-EB66-03C6-13D2-6EE233C61524}.Release|Any CPU.Build.0 = Release|Any CPU + {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Release|Any CPU.Build.0 = Release|Any CPU + {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Release|Any CPU.Build.0 = Release|Any CPU + {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Release|Any CPU.Build.0 = Release|Any CPU + {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Release|Any CPU.Build.0 = Release|Any CPU + {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Release|Any CPU.Build.0 = Release|Any CPU + {1FCE400C-3875-3963-2105-084823B55013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FCE400C-3875-3963-2105-084823B55013}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FCE400C-3875-3963-2105-084823B55013}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FCE400C-3875-3963-2105-084823B55013}.Release|Any CPU.Build.0 = Release|Any CPU + {3893606D-3E03-0FFD-95B4-A93121438268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3893606D-3E03-0FFD-95B4-A93121438268}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3893606D-3E03-0FFD-95B4-A93121438268}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3893606D-3E03-0FFD-95B4-A93121438268}.Release|Any CPU.Build.0 = Release|Any CPU + {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Release|Any CPU.Build.0 = Release|Any CPU + {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Release|Any CPU.Build.0 = Release|Any CPU + {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Release|Any CPU.Build.0 = Release|Any CPU + {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Release|Any CPU.Build.0 = Release|Any CPU + {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Release|Any CPU.Build.0 = Release|Any CPU + {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Release|Any CPU.Build.0 = Release|Any CPU + {A4977A0A-A95B-7C35-F319-521331739C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4977A0A-A95B-7C35-F319-521331739C01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4977A0A-A95B-7C35-F319-521331739C01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4977A0A-A95B-7C35-F319-521331739C01}.Release|Any CPU.Build.0 = Release|Any CPU + {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Release|Any CPU.Build.0 = Release|Any CPU + {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Release|Any CPU.Build.0 = Release|Any CPU + {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Release|Any CPU.Build.0 = Release|Any CPU + {94769285-DE8C-43CF-8F43-2E6081DE261F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94769285-DE8C-43CF-8F43-2E6081DE261F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94769285-DE8C-43CF-8F43-2E6081DE261F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94769285-DE8C-43CF-8F43-2E6081DE261F}.Release|Any CPU.Build.0 = Release|Any CPU + {005A99AE-9829-5288-081E-6AA2C7068F41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {005A99AE-9829-5288-081E-6AA2C7068F41}.Debug|Any CPU.Build.0 = Debug|Any CPU + {005A99AE-9829-5288-081E-6AA2C7068F41}.Release|Any CPU.ActiveCfg = Release|Any CPU + {005A99AE-9829-5288-081E-6AA2C7068F41}.Release|Any CPU.Build.0 = Release|Any CPU + {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Release|Any CPU.Build.0 = Release|Any CPU + {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Release|Any CPU.Build.0 = Release|Any CPU + {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Release|Any CPU.Build.0 = Release|Any CPU + {ACC68622-35F7-164F-FD1B-E68510FB877C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACC68622-35F7-164F-FD1B-E68510FB877C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACC68622-35F7-164F-FD1B-E68510FB877C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACC68622-35F7-164F-FD1B-E68510FB877C}.Release|Any CPU.Build.0 = Release|Any CPU + {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Release|Any CPU.Build.0 = Release|Any CPU + {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Release|Any CPU.Build.0 = Release|Any CPU + {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Release|Any CPU.Build.0 = Release|Any CPU + {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Release|Any CPU.Build.0 = Release|Any CPU + {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Release|Any CPU.Build.0 = Release|Any CPU + {C004A041-806C-248D-6972-BC44CBD8AFDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C004A041-806C-248D-6972-BC44CBD8AFDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C004A041-806C-248D-6972-BC44CBD8AFDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C004A041-806C-248D-6972-BC44CBD8AFDB}.Release|Any CPU.Build.0 = Release|Any CPU + {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Release|Any CPU.Build.0 = Release|Any CPU + {D9D391EA-769E-A96E-D230-453C9B9365DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9D391EA-769E-A96E-D230-453C9B9365DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9D391EA-769E-A96E-D230-453C9B9365DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9D391EA-769E-A96E-D230-453C9B9365DE}.Release|Any CPU.Build.0 = Release|Any CPU + {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Release|Any CPU.Build.0 = Release|Any CPU + {2EEDD992-0F07-908F-52D7-52E0D0816172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EEDD992-0F07-908F-52D7-52E0D0816172}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EEDD992-0F07-908F-52D7-52E0D0816172}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2EEDD992-0F07-908F-52D7-52E0D0816172}.Release|Any CPU.Build.0 = Release|Any CPU + {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Release|Any CPU.Build.0 = Release|Any CPU + {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Release|Any CPU.Build.0 = Release|Any CPU + {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Release|Any CPU.Build.0 = Release|Any CPU + {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Release|Any CPU.Build.0 = Release|Any CPU + {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Release|Any CPU.Build.0 = Release|Any CPU + {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Release|Any CPU.Build.0 = Release|Any CPU + {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Release|Any CPU.Build.0 = Release|Any CPU + {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Release|Any CPU.Build.0 = Release|Any CPU + {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Release|Any CPU.Build.0 = Release|Any CPU + {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Release|Any CPU.Build.0 = Release|Any CPU + {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Release|Any CPU.Build.0 = Release|Any CPU + {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Release|Any CPU.Build.0 = Release|Any CPU + {491EE542-B9EB-10C7-06A2-6F2053C50482}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {491EE542-B9EB-10C7-06A2-6F2053C50482}.Debug|Any CPU.Build.0 = Debug|Any CPU + {491EE542-B9EB-10C7-06A2-6F2053C50482}.Release|Any CPU.ActiveCfg = Release|Any CPU + {491EE542-B9EB-10C7-06A2-6F2053C50482}.Release|Any CPU.Build.0 = Release|Any CPU + {BD1EEC86-7644-5761-1346-089385B5A749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD1EEC86-7644-5761-1346-089385B5A749}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD1EEC86-7644-5761-1346-089385B5A749}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD1EEC86-7644-5761-1346-089385B5A749}.Release|Any CPU.Build.0 = Release|Any CPU + {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Release|Any CPU.Build.0 = Release|Any CPU + {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Release|Any CPU.Build.0 = Release|Any CPU + {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Release|Any CPU.Build.0 = Release|Any CPU + {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Release|Any CPU.Build.0 = Release|Any CPU + {9201E12B-135F-5E14-0672-AB5561520397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9201E12B-135F-5E14-0672-AB5561520397}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9201E12B-135F-5E14-0672-AB5561520397}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9201E12B-135F-5E14-0672-AB5561520397}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {7188C2C0-F586-2E1C-E0B5-5DFC1FABF135} = {F883AD26-E2D9-0064-49F2-B333EF800629} + {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D} = {7188C2C0-F586-2E1C-E0B5-5DFC1FABF135} + {B4DAA744-D941-8AA5-7BB9-26961FB2C0FD} = {F883AD26-E2D9-0064-49F2-B333EF800629} + {EB0043B9-6579-7370-BED1-D06FE9DFC755} = {B4DAA744-D941-8AA5-7BB9-26961FB2C0FD} + {9EA3DC81-E26A-677F-6A25-3A91573DF4FE} = {278F3FFB-8C21-435B-507F-61B78986A400} + {BD2C8FC3-3703-7EF9-4551-70298314EF37} = {9EA3DC81-E26A-677F-6A25-3A91573DF4FE} + {4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA} = {278F3FFB-8C21-435B-507F-61B78986A400} + {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8} = {4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA} + {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F} = {04B96F53-E713-70DE-173F-A95873598AF4} + {D27B063A-B8D1-101F-0A9A-82D5880B0092} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} + {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE} = {D27B063A-B8D1-101F-0A9A-82D5880B0092} + {B2FBA576-327C-1BE5-E29F-D95D457F7733} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} + {C45B3BA4-7E52-73AB-4942-5899597D4C36} = {B2FBA576-327C-1BE5-E29F-D95D457F7733} + {F5E7128C-C6CF-3B49-7306-A9D6E76AC385} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} + {D554BB1E-51B7-3752-8566-135C9ADB7DCA} = {F5E7128C-C6CF-3B49-7306-A9D6E76AC385} + {C1BECA30-1B7A-2AD9-E261-E8D798C74B5D} = {1956B0E3-C3A6-1D29-BB64-D91F2292772C} + {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC} = {C1BECA30-1B7A-2AD9-E261-E8D798C74B5D} + {8E784D3B-3E6B-7A86-D8E3-544301E375D9} = {DCF9C18E-19C8-9748-4C1C-32AB5F62F46B} + {E8540B19-EB66-03C6-13D2-6EE233C61524} = {8E784D3B-3E6B-7A86-D8E3-544301E375D9} + {CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38} = {DCF9C18E-19C8-9748-4C1C-32AB5F62F46B} + {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452} = {CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38} + {97E78C61-B29B-A484-4CE9-4BB29EB9331A} = {5D4ABE75-A633-7578-A6F0-BB88D48E78A4} + {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039} = {97E78C61-B29B-A484-4CE9-4BB29EB9331A} + {BD4137AF-3EE6-D962-BF72-9904BFD46A79} = {5D4ABE75-A633-7578-A6F0-BB88D48E78A4} + {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9} = {BD4137AF-3EE6-D962-BF72-9904BFD46A79} + {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} + {74BEC791-7060-4E1D-E77C-2490EFE2DFD0} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} + {1FCE400C-3875-3963-2105-084823B55013} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} + {2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002} = {DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E} + {3893606D-3E03-0FFD-95B4-A93121438268} = {2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002} + {968FF768-FCED-1723-7BDD-DA5CA8774CA7} = {DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E} + {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF} = {968FF768-FCED-1723-7BDD-DA5CA8774CA7} + {B7885BA3-4776-F672-E8F6-B5866B779C62} = {0C88DD14-F956-CE84-757C-A364CCF449FC} + {AEEBE2B8-B7E4-178C-5640-626E89EF0C75} = {B7885BA3-4776-F672-E8F6-B5866B779C62} + {228B02D4-B903-8A36-6CC3-E6BEA647CE1E} = {256F4E96-6A73-9ABE-786F-840C672A50F4} + {B6384FF0-6E94-4ADE-F932-F4E886C1CADD} = {228B02D4-B903-8A36-6CC3-E6BEA647CE1E} + {28716C4F-1493-E9A1-BA33-F0DEF262A65A} = {256F4E96-6A73-9ABE-786F-840C672A50F4} + {8F18837A-BB27-ECF0-C1AA-4838E1C2A781} = {28716C4F-1493-E9A1-BA33-F0DEF262A65A} + {595095FC-11E7-9A6C-713C-1AA81E4007ED} = {04B96F53-E713-70DE-173F-A95873598AF4} + {09B1DD90-461D-BA25-543A-2B9E36909F2A} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} + {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68} = {09B1DD90-461D-BA25-543A-2B9E36909F2A} + {8C1BB3C5-A56A-60F2-587A-1CDE499093FF} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} + {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE} = {8C1BB3C5-A56A-60F2-587A-1CDE499093FF} + {8AED47D8-E613-0A63-AFBD-DB2A96051743} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} + {A4977A0A-A95B-7C35-F319-521331739C01} = {8AED47D8-E613-0A63-AFBD-DB2A96051743} + {E329DD7B-EA06-0E35-2452-F0374B45C92D} = {453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC} + {EE8635E8-7069-5440-4C4D-3E712D0A6E31} = {E329DD7B-EA06-0E35-2452-F0374B45C92D} + {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0} = {EE8635E8-7069-5440-4C4D-3E712D0A6E31} + {8C21E68A-654B-F80C-2D42-F0D033850D3B} = {E329DD7B-EA06-0E35-2452-F0374B45C92D} + {D5F75C44-4165-6BB9-BB83-C01241D5775F} = {8C21E68A-654B-F80C-2D42-F0D033850D3B} + {8B02DB0C-FE4B-328D-C414-580634248F4A} = {453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC} + {AB061C51-2A24-F88C-EF6D-0215BD882074} = {8B02DB0C-FE4B-328D-C414-580634248F4A} + {62F0E24C-EE9B-D5B3-D2CF-19358722D081} = {AB061C51-2A24-F88C-EF6D-0215BD882074} + {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} = {0C88DD14-F956-CE84-757C-A364CCF449FC} + {94769285-DE8C-43CF-8F43-2E6081DE261F} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {005A99AE-9829-5288-081E-6AA2C7068F41} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {384D771F-1D94-6B01-A1C3-435584F4B3BF} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {DA514A3D-030F-3753-55AC-95601ADF7FE9} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {FEEE3D25-53D4-9F34-27B7-CBC04873009F} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {ACC68622-35F7-164F-FD1B-E68510FB877C} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {42C50CDC-3AF3-2866-9186-AE532C918BBA} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {0262DCC6-3D46-CBCE-4888-9F37FDAAE470} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} + {A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {805B4876-2550-7ADC-2FD1-6362247661A7} = {A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC} + {3C135F94-99F0-BF85-CD5D-F2BD288FC230} = {805B4876-2550-7ADC-2FD1-6362247661A7} + {5ED11752-357D-2F9A-0D62-6FBFEC2923EA} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {4030600A-B42C-7665-4E1E-9DEDBAF9080A} = {5ED11752-357D-2F9A-0D62-6FBFEC2923EA} + {8FC99803-7FB1-E7FD-F579-4FF49A324139} = {4030600A-B42C-7665-4E1E-9DEDBAF9080A} + {2D1527BB-743D-5D96-93C8-1B5741ADC02B} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {2CF24191-5ACD-5999-EAB4-F3ED6F833833} = {2D1527BB-743D-5D96-93C8-1B5741ADC02B} + {C004A041-806C-248D-6972-BC44CBD8AFDB} = {2CF24191-5ACD-5999-EAB4-F3ED6F833833} + {F24703D6-F12F-EE78-E988-49EB11C8433B} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {A6DB63EE-406F-8FC6-244C-D0DECD2202FB} = {F24703D6-F12F-EE78-E988-49EB11C8433B} + {69AB9EB3-9FB3-F134-F7BB-6F20719F293D} = {A6DB63EE-406F-8FC6-244C-D0DECD2202FB} + {BC25C024-DEC1-AC57-3E67-CBE61A818765} = {F24703D6-F12F-EE78-E988-49EB11C8433B} + {D9D391EA-769E-A96E-D230-453C9B9365DE} = {BC25C024-DEC1-AC57-3E67-CBE61A818765} + {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {F2EF8EC2-4C19-61B5-DCF4-9014E729C057} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {2EEDD992-0F07-908F-52D7-52E0D0816172} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {FEF03057-3DED-46E9-44C2-E5A71183CBF7} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {E7C427B4-5DAA-2DEC-D4FE-25513848B07E} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} + {2114FDDC-431A-A228-9FBD-A2D77B669641} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8} = {2114FDDC-431A-A228-9FBD-A2D77B669641} + {72B9C791-DBD1-32DB-C566-B5D3B1D405E1} = {5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8} + {73AD86C9-A183-63E1-9E65-08B4582D7CA4} = {2114FDDC-431A-A228-9FBD-A2D77B669641} + {F3C7C76A-FF30-4935-E238-7C5A838E3BCE} = {73AD86C9-A183-63E1-9E65-08B4582D7CA4} + {2C226B6F-947F-806E-AB56-5318C87BE998} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {728874E7-57EA-5300-FDDD-4A392F892C62} = {2C226B6F-947F-806E-AB56-5318C87BE998} + {585E4EE6-E918-DDEC-79AD-C956E6A19E4B} = {728874E7-57EA-5300-FDDD-4A392F892C62} + {F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719} = {2C226B6F-947F-806E-AB56-5318C87BE998} + {C80EB816-1E52-8D59-6C14-5567A23B5D82} = {F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719} + {E199B8FB-B34C-E815-5C68-8C4C236C3F5B} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} + {BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828} = {E199B8FB-B34C-E815-5C68-8C4C236C3F5B} + {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7} = {BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828} + {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} + {75F0ABB4-98D0-A880-0F84-660DB1C46419} = {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} + {491EE542-B9EB-10C7-06A2-6F2053C50482} = {75F0ABB4-98D0-A880-0F84-660DB1C46419} + {7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE} = {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} + {BD1EEC86-7644-5761-1346-089385B5A749} = {7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE} + {83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED} = {032573FE-E973-EE49-F164-6E17D60C24C1} + {D8364222-347F-695D-960D-5F83D75F4A3E} = {83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED} + {493470CA-BAAC-C311-15C4-BEEB81EB0E42} = {D8364222-347F-695D-960D-5F83D75F4A3E} + {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425} = {493470CA-BAAC-C311-15C4-BEEB81EB0E42} + {D6A88611-6F2F-36CC-9E71-609E6DC6CBAE} = {D8364222-347F-695D-960D-5F83D75F4A3E} + {A46AAF9E-39CC-085A-4EA7-A99537EA00E6} = {D6A88611-6F2F-36CC-9E71-609E6DC6CBAE} + {59BF9900-BDFB-2E52-B7D0-CA27D2239E1E} = {D8364222-347F-695D-960D-5F83D75F4A3E} + {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B} = {59BF9900-BDFB-2E52-B7D0-CA27D2239E1E} + {6636F944-0A81-C8B7-09AA-414B5978CE4C} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} + {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} = {6636F944-0A81-C8B7-09AA-414B5978CE4C} + {7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F} = {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} + {DFB12E12-A532-EF12-87F4-BD537FF1662F} = {7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F} + {978EA837-C2CB-DF69-BCE3-815ADE704D37} = {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} + {9201E12B-135F-5E14-0672-AB5561520397} = {978EA837-C2CB-DF69-BCE3-815ADE704D37} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7F5C71B7-6B0B-40C5-A3E7-E9811996ECAA} + EndGlobalSection +EndGlobal diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index 09374cf8ab9b..cd732e27e496 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -2,17 +2,22 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Components.Endpoints; internal sealed class TempDataService { private const string CookieName = ".AspNetCore.Components.TempData"; + private const string PurposeString = "Microsoft.AspNetCore.Components.Endpoints.TempDataService"; - public TempDataService() + private static IDataProtector GetDataProtector(HttpContext httpContext) { - // TO-DO: Add encoding later if needed + var dataProtectionProvider = httpContext.RequestServices.GetRequiredService(); + return dataProtectionProvider.CreateProtector(PurposeString); } public static TempData Load(HttpContext httpContext) @@ -24,7 +29,10 @@ public static TempData Load(HttpContext httpContext) return returnTempData; } - var dataFromCookie = JsonSerializer.Deserialize>(serializedDataFromCookie); + var protectedBytes = WebEncoders.Base64UrlDecode(serializedDataFromCookie); + var unprotectedBytes = GetDataProtector(httpContext).Unprotect(protectedBytes); + var dataFromCookie = JsonSerializer.Deserialize>(unprotectedBytes); + if (dataFromCookie is null) { return returnTempData; @@ -40,6 +48,40 @@ public static TempData Load(HttpContext httpContext) return returnTempData; } + public static void Save(HttpContext httpContext, TempData tempData) + { + var dataToSave = tempData.Save(); + foreach (var kvp in dataToSave) + { + if (!CanSerializeType(kvp.Value?.GetType() ?? typeof(object))) + { + throw new InvalidOperationException($"TempData cannot store values of type '{kvp.Value?.GetType()}'."); + } + } + + if (dataToSave.Count == 0) + { + httpContext.Response.Cookies.Delete(CookieName, new CookieOptions + { + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + return; + } + + var bytes = JsonSerializer.SerializeToUtf8Bytes(dataToSave); + var protectedBytes = GetDataProtector(httpContext).Protect(bytes); + var encodedValue = WebEncoders.Base64UrlEncode(protectedBytes); + + httpContext.Response.Cookies.Append(CookieName, encodedValue, new CookieOptions + { + HttpOnly = true, + IsEssential = true, + SameSite = SameSiteMode.Lax, + Secure = httpContext.Request.IsHttps, + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + } + private static object? ConvertJsonElement(JsonElement element) { switch (element.ValueKind) @@ -108,35 +150,6 @@ public static TempData Load(HttpContext httpContext) return dictionary; } - public static void Save(HttpContext httpContext, TempData tempData) - { - var dataToSave = tempData.Save(); - foreach (var kvp in dataToSave) - { - if (!CanSerializeType(kvp.Value?.GetType() ?? typeof(object))) - { - throw new InvalidOperationException($"TempData cannot store values of type '{kvp.Value?.GetType()}'."); - } - } - - if (dataToSave.Count == 0) - { - httpContext.Response.Cookies.Delete(CookieName, new CookieOptions - { - Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", - }); - return; - } - httpContext.Response.Cookies.Append(CookieName, JsonSerializer.Serialize(dataToSave), new CookieOptions - { - HttpOnly = true, - IsEssential = true, - SameSite = SameSiteMode.Lax, - Secure = httpContext.Request.IsHttps, - Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", - }); - } - private static bool CanSerializeType(Type type) { type = Nullable.GetUnderlyingType(type) ?? type; From 1d2fc6d0f086cabf07d4cac830d1ccdb997f8dff Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Mon, 15 Dec 2025 15:38:53 +0100 Subject: [PATCH 11/20] Fix + Enumerator --- src/Components/Components/src/TempData.cs | 37 ++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs index 54fe807f1a4b..7a29d0601e5b 100644 --- a/src/Components/Components/src/TempData.cs +++ b/src/Components/Components/src/TempData.cs @@ -8,8 +8,8 @@ namespace Microsoft.AspNetCore.Components; /// public class TempData : ITempData { - private readonly Dictionary _data = new(); - private readonly HashSet _retainedKeys = new(); + private readonly Dictionary _data = new(StringComparer.OrdinalIgnoreCase); + private readonly HashSet _retainedKeys = new(StringComparer.OrdinalIgnoreCase); /// public object? this[string key] @@ -145,11 +145,40 @@ public void Clear() IEnumerator> IEnumerable>.GetEnumerator() { - throw new NotImplementedException(); + return new TempDataEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { - throw new NotImplementedException(); + return new TempDataEnumerator(this); + } + + class TempDataEnumerator : IEnumerator> + { + private readonly IEnumerator> _innerEnumerator; + + public TempDataEnumerator(TempData tempData) + { + _innerEnumerator = tempData._data.GetEnumerator(); + } + + public KeyValuePair Current => _innerEnumerator.Current; + + object IEnumerator.Current => _innerEnumerator.Current; + + public void Dispose() + { + _innerEnumerator.Dispose(); + } + + public bool MoveNext() + { + return _innerEnumerator.MoveNext(); + } + + public void Reset() + { + _innerEnumerator.Reset(); + } } } From 31ead26fec56f1be102c58d1ac057b494d588e8f Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Mon, 15 Dec 2025 17:20:39 +0100 Subject: [PATCH 12/20] Fix + unit tests --- src/Components/Components/src/TempData.cs | 14 +- .../Components/test/TempDataTest.cs | 210 ++++++++++++++++++ 2 files changed, 216 insertions(+), 8 deletions(-) create mode 100644 src/Components/Components/test/TempDataTest.cs diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs index 7a29d0601e5b..1c24aeeda307 100644 --- a/src/Components/Components/src/TempData.cs +++ b/src/Components/Components/src/TempData.cs @@ -108,14 +108,13 @@ public void Clear() void IDictionary.Add(string key, object? value) { - _data.Add(key, value); - _retainedKeys.Add(key); + this[key] = value; } bool IDictionary.TryGetValue(string key, out object? value) { - _retainedKeys.Remove(key); - return _data.TryGetValue(key, out value); + value = Get(key); + return ContainsKey(key); } void ICollection>.Add(KeyValuePair item) @@ -125,7 +124,7 @@ public void Clear() bool ICollection>.Contains(KeyValuePair item) { - return ContainsKey(item.Key) && _data[item.Key] == item.Value; + return ContainsKey(item.Key) && Equals(Peek(item.Key), item.Value); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) @@ -135,10 +134,9 @@ public void Clear() bool ICollection>.Remove(KeyValuePair item) { - if (((ICollection>)_data).Remove(item)) + if (ContainsKey(item.Key) && Equals(Peek(item.Key), item.Value)) { - _retainedKeys.Remove(item.Key); - return true; + return Remove(item.Key); } return false; } diff --git a/src/Components/Components/test/TempDataTest.cs b/src/Components/Components/test/TempDataTest.cs new file mode 100644 index 000000000000..6544ebab5567 --- /dev/null +++ b/src/Components/Components/test/TempDataTest.cs @@ -0,0 +1,210 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components; + +public class TempDataTest +{ + [Fact] + public void Indexer_CanSetAndGetValues() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + var value = tempData["Key1"]; + Assert.Equal("Value1", value); + } + + [Fact] + public void Get_ReturnsValueAndRemovesFromRetainedKeys() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + + var value = tempData.Get("Key1"); + + Assert.Equal("Value1", value); + var saved = tempData.Save(); + Assert.Empty(saved); + } + + [Fact] + public void Get_ReturnsNullForNonExistentKey() + { + var tempData = new TempData(); + var value = tempData.Get("NonExistent"); + Assert.Null(value); + } + + [Fact] + public void Peek_ReturnsValueWithoutRemovingFromRetainedKeys() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + var value = tempData.Peek("Key1"); + Assert.Equal("Value1", value); + value = tempData.Get("Key1"); + Assert.Equal("Value1", value); + } + + [Fact] + public void Peek_ReturnsNullForNonExistentKey() + { + var tempData = new TempData(); + var value = tempData.Peek("NonExistent"); + Assert.Null(value); + } + + [Fact] + public void Keep_RetainsAllKeys() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + tempData["Key2"] = "Value2"; + _ = tempData.Get("Key1"); + _ = tempData.Get("Key2"); + + tempData.Keep(); + + var value1 = tempData.Get("Key1"); + var value2 = tempData.Get("Key2"); + Assert.Equal("Value1", value1); + Assert.Equal("Value2", value2); + } + + [Fact] + public void KeepWithKey_RetainsSpecificKey() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + tempData["Key2"] = "Value2"; + _ = tempData.Get("Key1"); + _ = tempData.Get("Key2"); + + tempData.Keep("Key1"); + + var saved = tempData.Save(); + Assert.Single(saved); + Assert.Equal("Value1", saved["Key1"]); + } + + [Fact] + public void KeepWithKey_DoesNothingForNonExistentKey() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + _ = tempData.Get("Key1"); + + tempData.Keep("NonExistent"); + + var value = tempData.Get("NonExistent"); + Assert.Null(value); + } + + [Fact] + public void ContainsKey_ReturnsTrueForExistingKey() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + var result = tempData.ContainsKey("Key1"); + Assert.True(result); + } + + [Fact] + public void ContainsKey_ReturnsFalseForNonExistentKey() + { + var tempData = new TempData(); + var result = tempData.ContainsKey("NonExistent"); + Assert.False(result); + } + + [Fact] + public void Remove_RemovesKeyAndReturnsTrue() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + + var result = tempData.Remove("Key1"); + + Assert.True(result); + var value = tempData.Get("Key1"); + Assert.Null(value); + } + + [Fact] + public void Remove_ReturnsFalseForNonExistentKey() + { + var tempData = new TempData(); + var result = tempData.Remove("NonExistent"); + Assert.False(result); + } + + [Fact] + public void Save_ReturnsOnlyRetainedKeys() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + tempData["Key2"] = "Value2"; + tempData["Key3"] = "Value3"; + _ = tempData.Get("Key1"); + _ = tempData.Get("Key2"); + + var saved = tempData.Save(); + + Assert.Single(saved); + Assert.Equal("Value3", saved["Key3"]); + } + + [Fact] + public void Load_PopulatesDataFromDictionary() + { + var tempData = new TempData(); + var dataToLoad = new Dictionary + { + ["Key1"] = "Value1", + ["Key2"] = "Value2" + }; + + tempData.Load(dataToLoad); + + Assert.Equal("Value1", tempData.Get("Key1")); + Assert.Equal("Value2", tempData.Get("Key2")); + } + + [Fact] + public void Load_ClearsExistingDataBeforeLoading() + { + var tempData = new TempData(); + tempData["ExistingKey"] = "ExistingValue"; + var dataToLoad = new Dictionary + { + ["NewKey"] = "NewValue" + }; + + tempData.Load(dataToLoad); + + Assert.False(tempData.ContainsKey("ExistingKey")); + Assert.True(tempData.ContainsKey("NewKey")); + } + + [Fact] + public void Clear_RemovesAllData() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + tempData["Key2"] = "Value2"; + + tempData.Clear(); + + Assert.Null(tempData.Get("Key1")); + Assert.Null(tempData.Get("Key2")); + } + + [Fact] + public void Indexer_IsCaseInsensitive() + { + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + var value = tempData["KEY1"]; + Assert.Equal("Value1", value); + } +} From 21a3c3b728b78d8694f300b065ee51e64b510fa4 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Tue, 16 Dec 2025 14:20:18 +0100 Subject: [PATCH 13/20] Fix --- .../Components/src/PublicAPI.Unshipped.txt | 1 + src/Components/Components/src/TempData.cs | 20 ++++++++++++++++++- .../Components/test/TempDataTest.cs | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index 0a4d409fea69..2e3f440a6e8b 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -5,6 +5,7 @@ Microsoft.AspNetCore.Components.ITempData.Keep() -> void Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? Microsoft.AspNetCore.Components.TempData +Microsoft.AspNetCore.Components.TempData.ContainsValue(object? value) -> bool Microsoft.AspNetCore.Components.TempData.TempData() -> void Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs index 1c24aeeda307..3778e385bf32 100644 --- a/src/Components/Components/src/TempData.cs +++ b/src/Components/Components/src/TempData.cs @@ -64,6 +64,14 @@ public bool Remove(string key) return _data.Remove(key); } + /// + /// Returns true if the TempData dictionary contains the specified . + /// + public bool ContainsValue(object? value) + { + return _data.ContainsValue(value); + } + /// /// Gets the data that should be saved for the next request. /// @@ -153,14 +161,24 @@ IEnumerator IEnumerable.GetEnumerator() class TempDataEnumerator : IEnumerator> { + private readonly TempData _tempData; private readonly IEnumerator> _innerEnumerator; public TempDataEnumerator(TempData tempData) { + _tempData = tempData; _innerEnumerator = tempData._data.GetEnumerator(); } - public KeyValuePair Current => _innerEnumerator.Current; + public KeyValuePair Current + { + get + { + var kvp = _innerEnumerator.Current; + _tempData.Remove(kvp.Key); + return kvp; + } + } object IEnumerator.Current => _innerEnumerator.Current; diff --git a/src/Components/Components/test/TempDataTest.cs b/src/Components/Components/test/TempDataTest.cs index 6544ebab5567..e02c062ffaad 100644 --- a/src/Components/Components/test/TempDataTest.cs +++ b/src/Components/Components/test/TempDataTest.cs @@ -158,7 +158,7 @@ public void Save_ReturnsOnlyRetainedKeys() public void Load_PopulatesDataFromDictionary() { var tempData = new TempData(); - var dataToLoad = new Dictionary + var dataToLoad = new Dictionary { ["Key1"] = "Value1", ["Key2"] = "Value2" @@ -175,7 +175,7 @@ public void Load_ClearsExistingDataBeforeLoading() { var tempData = new TempData(); tempData["ExistingKey"] = "ExistingValue"; - var dataToLoad = new Dictionary + var dataToLoad = new Dictionary { ["NewKey"] = "NewValue" }; From 7b50676207aeaf8293a7f36462de2e3171c395a0 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Tue, 16 Dec 2025 14:20:31 +0100 Subject: [PATCH 14/20] TempDataTest --- .../DependencyInjection/TempDataService.cs | 47 ++- .../Endpoints/test/TempDataServiceTest.cs | 297 ++++++++++++++++++ src/submodules/googletest | 2 +- 3 files changed, 328 insertions(+), 18 deletions(-) create mode 100644 src/Components/Endpoints/test/TempDataServiceTest.cs diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index cd732e27e496..e78fc62139d0 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -22,30 +22,43 @@ private static IDataProtector GetDataProtector(HttpContext httpContext) public static TempData Load(HttpContext httpContext) { - var returnTempData = new TempData(); - var serializedDataFromCookie = httpContext.Request.Cookies[CookieName]; - if (serializedDataFromCookie is null) + try { - return returnTempData; - } + var returnTempData = new TempData(); + var serializedDataFromCookie = httpContext.Request.Cookies[CookieName]; + if (serializedDataFromCookie is null) + { + return returnTempData; + } - var protectedBytes = WebEncoders.Base64UrlDecode(serializedDataFromCookie); - var unprotectedBytes = GetDataProtector(httpContext).Unprotect(protectedBytes); - var dataFromCookie = JsonSerializer.Deserialize>(unprotectedBytes); + var protectedBytes = WebEncoders.Base64UrlDecode(serializedDataFromCookie); + var unprotectedBytes = GetDataProtector(httpContext).Unprotect(protectedBytes); + var dataFromCookie = JsonSerializer.Deserialize>(unprotectedBytes); - if (dataFromCookie is null) - { + if (dataFromCookie is null) + { + return returnTempData; + } + + var convertedData = new Dictionary(); + foreach (var kvp in dataFromCookie) + { + convertedData[kvp.Key] = ConvertJsonElement(kvp.Value); + } + + returnTempData.Load(convertedData); return returnTempData; } - - var convertedData = new Dictionary(); - foreach (var kvp in dataFromCookie) + catch { - convertedData[kvp.Key] = ConvertJsonElement(kvp.Value); + // If any error occurs during loading (e.g. data protection key changed, malformed cookie), + // return an empty TempData dictionary. + httpContext.Response.Cookies.Delete(CookieName, new CookieOptions + { + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + return new TempData(); } - - returnTempData.Load(convertedData); - return returnTempData; } public static void Save(HttpContext httpContext, TempData tempData) diff --git a/src/Components/Endpoints/test/TempDataServiceTest.cs b/src/Components/Endpoints/test/TempDataServiceTest.cs new file mode 100644 index 000000000000..8b49658d8f3f --- /dev/null +++ b/src/Components/Endpoints/test/TempDataServiceTest.cs @@ -0,0 +1,297 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Endpoints; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; + +namespace Microsoft.Extensions.DependencyInjection; + +public class TempDataServiceTest +{ + [Fact] + public void Load_ReturnsEmptyTempData_WhenNoCookieExists() + { + var httpContext = CreateHttpContext(); + + var tempData = TempDataService.Load(httpContext); + + Assert.NotNull(tempData); + Assert.Empty(tempData.Save()); + } + + [Fact] + public void Save_DeletesCookie_WhenNoDataToSave() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + + TempDataService.Save(httpContext, tempData); + + var cookieFeature = httpContext.Features.Get(); + Assert.NotNull(cookieFeature); + Assert.Contains(".AspNetCore.Components.TempData", cookieFeature.DeletedCookies); + } + + [Fact] + public void Save_SetsCookie_WhenDataExists() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + + TempDataService.Save(httpContext, tempData); + + var cookieFeature = httpContext.Features.Get(); + Assert.NotNull(cookieFeature); + Assert.True(cookieFeature.SetCookies.ContainsKey(".AspNetCore.Components.TempData")); + } + + [Fact] + public void RoundTrip_PreservesStringValue() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["StringKey"] = "StringValue"; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal("StringValue", loadedTempData.Peek("StringKey")); + } + + [Fact] + public void RoundTrip_PreservesIntValue() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["IntKey"] = 42; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(42, loadedTempData.Peek("IntKey")); + } + + [Fact] + public void RoundTrip_PreservesBoolValue() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["BoolKey"] = true; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(true, loadedTempData.Peek("BoolKey")); + } + + [Fact] + public void RoundTrip_PreservesGuidValue() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + var guid = Guid.NewGuid(); + tempData["GuidKey"] = guid; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(guid, loadedTempData.Peek("GuidKey")); + } + + [Fact] + public void RoundTrip_PreservesDateTimeValue() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + var dateTime = new DateTime(2025, 12, 15, 10, 30, 0, DateTimeKind.Utc); + tempData["DateTimeKey"] = dateTime; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(dateTime, loadedTempData.Peek("DateTimeKey")); + } + + [Fact] + public void RoundTrip_PreservesStringArray() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + var array = new[] { "one", "two", "three" }; + tempData["ArrayKey"] = array; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(array, loadedTempData.Peek("ArrayKey")); + } + + [Fact] + public void RoundTrip_PreservesIntArray() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + var array = new[] { 1, 2, 3 }; + tempData["ArrayKey"] = array; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal(array, loadedTempData.Peek("ArrayKey")); + } + + [Fact] + public void RoundTrip_PreservesDictionary() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + var dict = new Dictionary { ["a"] = "1", ["b"] = "2" }; + tempData["DictKey"] = dict; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + var loadedDict = Assert.IsType>(loadedTempData.Peek("DictKey")); + Assert.Equal("1", loadedDict["a"]); + Assert.Equal("2", loadedDict["b"]); + } + + [Fact] + public void RoundTrip_PreservesMultipleDifferentValues() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["Key1"] = "Value1"; + tempData["Key2"] = 123; + tempData["Key3"] = true; + + TempDataService.Save(httpContext, tempData); + SimulateCookieRoundTrip(httpContext); + var loadedTempData = TempDataService.Load(httpContext); + + Assert.Equal("Value1", loadedTempData.Peek("Key1")); + Assert.Equal(123, loadedTempData.Peek("Key2")); + Assert.Equal(true, loadedTempData.Peek("Key3")); + } + + [Fact] + public void Save_ThrowsForUnsupportedType() + { + var httpContext = CreateHttpContext(); + var tempData = new TempData(); + tempData["Key"] = new object(); + + Assert.Throws(() => TempDataService.Save(httpContext, tempData)); + } + + [Fact] + public void Load_ReturnsEmptyTempData_ForInvalidBase64Cookie() + { + var httpContext = CreateHttpContext(); + httpContext.Request.Headers["Cookie"] = ".AspNetCore.Components.TempData=not-valid-base64!!!"; + + var tempData = TempDataService.Load(httpContext); + + Assert.NotNull(tempData); + Assert.Empty(tempData.Save()); + } + + [Fact] + public void Load_ReturnsEmptyTempData_ForUnsupportedType() + { + var httpContext = CreateHttpContext(); + var json = "{\"Key\":[true, false, true]}"; + var encoded = Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode(System.Text.Encoding.UTF8.GetBytes(json)); + httpContext.Request.Headers["Cookie"] = $".AspNetCore.Components.TempData={encoded}"; + + var tempData = TempDataService.Load(httpContext); + + Assert.NotNull(tempData); + Assert.Empty(tempData.Save()); + } + + private static DefaultHttpContext CreateHttpContext() + { + var services = new ServiceCollection() + .AddSingleton() + .BuildServiceProvider(); + + var httpContext = new DefaultHttpContext + { + RequestServices = services + }; + httpContext.Request.Scheme = "https"; + httpContext.Request.Host = new HostString("localhost"); + + var cookieFeature = new TestResponseCookiesFeature(); + httpContext.Features.Set(cookieFeature); + httpContext.Features.Set(cookieFeature); + + return httpContext; + } + + private static void SimulateCookieRoundTrip(HttpContext httpContext) + { + var cookieFeature = httpContext.Features.Get(); + if (cookieFeature != null && cookieFeature.SetCookies.TryGetValue(".AspNetCore.Components.TempData", out var cookieValue)) + { + httpContext.Request.Headers["Cookie"] = $".AspNetCore.Components.TempData={cookieValue}"; + } + } + + private class PassThroughDataProtectionProvider : IDataProtectionProvider + { + public IDataProtector CreateProtector(string purpose) => new PassThroughDataProtector(); + + private class PassThroughDataProtector : IDataProtector + { + public IDataProtector CreateProtector(string purpose) => this; + public byte[] Protect(byte[] plaintext) => plaintext; + public byte[] Unprotect(byte[] protectedData) => protectedData; + } + } + + private class TestResponseCookiesFeature : IResponseCookiesFeature + { + public Dictionary SetCookies { get; } = new(); + public HashSet DeletedCookies { get; } = new(); + + public IResponseCookies Cookies => new TestResponseCookies(this); + + private class TestResponseCookies : IResponseCookies + { + private readonly TestResponseCookiesFeature _feature; + + public TestResponseCookies(TestResponseCookiesFeature feature) + { + _feature = feature; + } + + public void Append(string key, string value) => Append(key, value, new CookieOptions()); + + public void Append(string key, string value, CookieOptions options) + { + _feature.SetCookies[key] = value; + } + + public void Delete(string key) => Delete(key, new CookieOptions()); + + public void Delete(string key, CookieOptions options) + { + _feature.DeletedCookies.Add(key); + } + } + } +} diff --git a/src/submodules/googletest b/src/submodules/googletest index 065127f1e4b4..1b96fa13f549 160000 --- a/src/submodules/googletest +++ b/src/submodules/googletest @@ -1 +1 @@ -Subproject commit 065127f1e4b46c5f14fc73cf8d323c221f9dc68e +Subproject commit 1b96fa13f549387b7549cc89e1a785cf143a1a50 From ecebef853b0eb874cf1c6deadfa81148ae1495f7 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Tue, 16 Dec 2025 14:44:20 +0100 Subject: [PATCH 15/20] Fix --- .../src/DependencyInjection/TempDataService.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index e78fc62139d0..aa26f4e7352b 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -6,10 +6,11 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Components.Endpoints; -internal sealed class TempDataService +internal sealed partial class TempDataService { private const string CookieName = ".AspNetCore.Components.TempData"; private const string PurposeString = "Microsoft.AspNetCore.Components.Endpoints.TempDataService"; @@ -33,6 +34,7 @@ public static TempData Load(HttpContext httpContext) var protectedBytes = WebEncoders.Base64UrlDecode(serializedDataFromCookie); var unprotectedBytes = GetDataProtector(httpContext).Unprotect(protectedBytes); + var dataFromCookie = JsonSerializer.Deserialize>(unprotectedBytes); if (dataFromCookie is null) @@ -49,10 +51,15 @@ public static TempData Load(HttpContext httpContext) returnTempData.Load(convertedData); return returnTempData; } - catch + catch (Exception ex) { // If any error occurs during loading (e.g. data protection key changed, malformed cookie), // return an empty TempData dictionary. + if (httpContext.RequestServices.GetService>() is { } logger) + { + Log.TempDataCookieLoadFailure(logger, CookieName, ex); + } + httpContext.Response.Cookies.Delete(CookieName, new CookieOptions { Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", @@ -177,4 +184,10 @@ private static bool CanSerializeType(Type type) typeof(ICollection).IsAssignableFrom(type) || typeof(IDictionary).IsAssignableFrom(type); } + + private static partial class Log + { + [LoggerMessage(3, LogLevel.Warning, "The temp data cookie {CookieName} could not be loaded.", EventName = "TempDataCookieLoadFailure")] + public static partial void TempDataCookieLoadFailure(ILogger logger, string cookieName, Exception exception); + } } From 6002ab12ee96910b4f94524f0facf10533923961 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Tue, 16 Dec 2025 14:51:27 +0100 Subject: [PATCH 16/20] Clean-up --- src/Components/Components.sln | 660 ---------------------------------- src/submodules/googletest | 2 +- 2 files changed, 1 insertion(+), 661 deletions(-) delete mode 100644 src/Components/Components.sln diff --git a/src/Components/Components.sln b/src/Components/Components.sln deleted file mode 100644 index 852246120981..000000000000 --- a/src/Components/Components.sln +++ /dev/null @@ -1,660 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.2.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{F883AD26-E2D9-0064-49F2-B333EF800629}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authorization", "Authorization", "{278F3FFB-8C21-435B-507F-61B78986A400}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{04B96F53-E713-70DE-173F-A95873598AF4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{F30895DC-C3AC-FF44-FFF8-D51D98AE1B61}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CustomElements", "CustomElements", "{1956B0E3-C3A6-1D29-BB64-D91F2292772C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Endpoints", "Endpoints", "{DCF9C18E-19C8-9748-4C1C-32AB5F62F46B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Forms", "Forms", "{5D4ABE75-A633-7578-A6F0-BB88D48E78A4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{5D20AA90-6969-D8BD-9DCD-8634F4692FDA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0C88DD14-F956-CE84-757C-A364CCF449FC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{256F4E96-6A73-9ABE-786F-840C672A50F4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QuickGrid", "QuickGrid", "{453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{032573FE-E973-EE49-F164-6E17D60C24C1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebView", "WebView", "{F75C3326-23C9-B46B-1CDE-63D2E405EED1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7188C2C0-F586-2E1C-E0B5-5DFC1FABF135}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Analyzers", "Analyzers\src\Microsoft.AspNetCore.Components.Analyzers.csproj", "{E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B4DAA744-D941-8AA5-7BB9-26961FB2C0FD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Analyzers.Tests", "Analyzers\test\Microsoft.AspNetCore.Components.Analyzers.Tests.csproj", "{EB0043B9-6579-7370-BED1-D06FE9DFC755}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9EA3DC81-E26A-677F-6A25-3A91573DF4FE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Authorization", "Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj", "{BD2C8FC3-3703-7EF9-4551-70298314EF37}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Authorization.Tests", "Authorization\test\Microsoft.AspNetCore.Components.Authorization.Tests.csproj", "{CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazingPizza.Server", "benchmarkapps\BlazingPizza.Server\BlazingPizza.Server.csproj", "{A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{D27B063A-B8D1-101F-0A9A-82D5880B0092}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Performance", "Components\perf\Microsoft.AspNetCore.Components.Performance.csproj", "{99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B2FBA576-327C-1BE5-E29F-D95D457F7733}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components", "Components\src\Microsoft.AspNetCore.Components.csproj", "{C45B3BA4-7E52-73AB-4942-5899597D4C36}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5E7128C-C6CF-3B49-7306-A9D6E76AC385}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Tests", "Components\test\Microsoft.AspNetCore.Components.Tests.csproj", "{D554BB1E-51B7-3752-8566-135C9ADB7DCA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C1BECA30-1B7A-2AD9-E261-E8D798C74B5D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.CustomElements", "CustomElements\src\Microsoft.AspNetCore.Components.CustomElements.csproj", "{AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8E784D3B-3E6B-7A86-D8E3-544301E375D9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Endpoints", "Endpoints\src\Microsoft.AspNetCore.Components.Endpoints.csproj", "{E8540B19-EB66-03C6-13D2-6EE233C61524}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Endpoints.Tests", "Endpoints\test\Microsoft.AspNetCore.Components.Endpoints.Tests.csproj", "{9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{97E78C61-B29B-A484-4CE9-4BB29EB9331A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Forms", "Forms\src\Microsoft.AspNetCore.Components.Forms.csproj", "{AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BD4137AF-3EE6-D962-BF72-9904BFD46A79}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Forms.Tests", "Forms\test\Microsoft.AspNetCore.Components.Forms.Tests.csproj", "{D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorServerApp", "Samples\BlazorServerApp\BlazorServerApp.csproj", "{FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorUnitedApp", "Samples\BlazorUnitedApp\BlazorUnitedApp.csproj", "{74BEC791-7060-4E1D-E77C-2490EFE2DFD0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorUnitedApp.Client", "Samples\BlazorUnitedApp.Client\BlazorUnitedApp.Client.csproj", "{1FCE400C-3875-3963-2105-084823B55013}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Server", "Server\src\Microsoft.AspNetCore.Components.Server.csproj", "{3893606D-3E03-0FFD-95B4-A93121438268}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{968FF768-FCED-1723-7BDD-DA5CA8774CA7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Server.Tests", "Server\test\Microsoft.AspNetCore.Components.Server.Tests.csproj", "{8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "E2ETest", "E2ETest", "{B7885BA3-4776-F672-E8F6-B5866B779C62}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.E2ETests", "test\E2ETest\Microsoft.AspNetCore.Components.E2ETests.csproj", "{AEEBE2B8-B7E4-178C-5640-626E89EF0C75}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{228B02D4-B903-8A36-6CC3-E6BEA647CE1E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Web", "Web\src\Microsoft.AspNetCore.Components.Web.csproj", "{B6384FF0-6E94-4ADE-F932-F4E886C1CADD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{28716C4F-1493-E9A1-BA33-F0DEF262A65A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.Web.Tests", "Web\test\Microsoft.AspNetCore.Components.Web.Tests.csproj", "{8F18837A-BB27-ECF0-C1AA-4838E1C2A781}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wasm.Performance", "Wasm.Performance", "{595095FC-11E7-9A6C-713C-1AA81E4007ED}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConsoleHost", "ConsoleHost", "{09B1DD90-461D-BA25-543A-2B9E36909F2A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.ConsoleHost", "benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Driver", "Driver", "{8C1BB3C5-A56A-60F2-587A-1CDE499093FF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.Driver", "benchmarkapps\Wasm.Performance\Driver\Wasm.Performance.Driver.csproj", "{672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApp", "TestApp", "{8AED47D8-E613-0A63-AFBD-DB2A96051743}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{A4977A0A-A95B-7C35-F319-521331739C01}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.AspNetCore.Components.QuickGrid", "Microsoft.AspNetCore.Components.QuickGrid", "{E329DD7B-EA06-0E35-2452-F0374B45C92D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EE8635E8-7069-5440-4C4D-3E712D0A6E31}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid\src\Microsoft.AspNetCore.Components.QuickGrid.csproj", "{8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8C21E68A-654B-F80C-2D42-F0D033850D3B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid.Tests", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid\test\Microsoft.AspNetCore.Components.QuickGrid.Tests.csproj", "{D5F75C44-4165-6BB9-BB83-C01241D5775F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "{8B02DB0C-FE4B-328D-C414-580634248F4A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AB061C51-2A24-F88C-EF6D-0215BD882074}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter", "QuickGrid\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter\src\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter.csproj", "{62F0E24C-EE9B-D5B3-D2CF-19358722D081}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicTestApp", "test\testassets\BasicTestApp\BasicTestApp.csproj", "{94769285-DE8C-43CF-8F43-2E6081DE261F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.TestServer", "test\testassets\Components.TestServer\Components.TestServer.csproj", "{005A99AE-9829-5288-081E-6AA2C7068F41}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.WasmMinimal", "test\testassets\Components.WasmMinimal\Components.WasmMinimal.csproj", "{384D771F-1D94-6B01-A1C3-435584F4B3BF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.WasmRemoteAuthentication", "test\testassets\Components.WasmRemoteAuthentication\Components.WasmRemoteAuthentication.csproj", "{DA514A3D-030F-3753-55AC-95601ADF7FE9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.App", "test\testassets\ComponentsApp.App\ComponentsApp.App.csproj", "{FEEE3D25-53D4-9F34-27B7-CBC04873009F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{ACC68622-35F7-164F-FD1B-E68510FB877C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationWasmApp", "test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyTestContentPackage", "test\testassets\LazyTestContentPackage\LazyTestContentPackage.csproj", "{42C50CDC-3AF3-2866-9186-AE532C918BBA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotReferencedInWasmCodePackage", "test\testassets\NotReferencedInWasmCodePackage\NotReferencedInWasmCodePackage.csproj", "{0262DCC6-3D46-CBCE-4888-9F37FDAAE470}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestContentPackage", "test\testassets\TestContentPackage\TestContentPackage.csproj", "{B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication.Msal", "Authentication.Msal", "{A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{805B4876-2550-7ADC-2FD1-6362247661A7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Authentication.WebAssembly.Msal", "WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj", "{3C135F94-99F0-BF85-CD5D-F2BD288FC230}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{5ED11752-357D-2F9A-0D62-6FBFEC2923EA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4030600A-B42C-7665-4E1E-9DEDBAF9080A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.DevServer", "WebAssembly\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj", "{8FC99803-7FB1-E7FD-F579-4FF49A324139}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JSInterop", "JSInterop", "{2D1527BB-743D-5D96-93C8-1B5741ADC02B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2CF24191-5ACD-5999-EAB4-F3ED6F833833}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.JSInterop.WebAssembly", "WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj", "{C004A041-806C-248D-6972-BC44CBD8AFDB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{F24703D6-F12F-EE78-E988-49EB11C8433B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A6DB63EE-406F-8FC6-244C-D0DECD2202FB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Server", "WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj", "{69AB9EB3-9FB3-F134-F7BB-6F20719F293D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BC25C024-DEC1-AC57-3E67-CBE61A818765}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Server.Tests", "WebAssembly\Server\test\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj", "{D9D391EA-769E-A96E-D230-453C9B9365DE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{F60C0A93-E7A1-AA4F-C800-18D21FD1802D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomBasePathApp", "WebAssembly\testassets\CustomBasePathApp\CustomBasePathApp.csproj", "{F2EF8EC2-4C19-61B5-DCF4-9014E729C057}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Client", "WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{2EEDD992-0F07-908F-52D7-52E0D0816172}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Server", "WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneApp", "WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreadingApp", "WebAssembly\testassets\ThreadingApp\ThreadingApp.csproj", "{D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreadingApp.Server", "WebAssembly\testassets\ThreadingApp.Server\ThreadingApp.Server.csproj", "{FEF03057-3DED-46E9-44C2-E5A71183CBF7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Prerendered.Client", "WebAssembly\testassets\Wasm.Prerendered.Client\Wasm.Prerendered.Client.csproj", "{D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Prerendered.Server", "WebAssembly\testassets\Wasm.Prerendered.Server\Wasm.Prerendered.Server.csproj", "{E7C427B4-5DAA-2DEC-D4FE-25513848B07E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WasmLinkerTest", "WebAssembly\testassets\WasmLinkerTest\WasmLinkerTest.csproj", "{8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{2114FDDC-431A-A228-9FBD-A2D77B669641}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly", "WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj", "{72B9C791-DBD1-32DB-C566-B5D3B1D405E1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{73AD86C9-A183-63E1-9E65-08B4582D7CA4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Tests", "WebAssembly\WebAssembly\test\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "{F3C7C76A-FF30-4935-E238-7C5A838E3BCE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly.Authentication", "WebAssembly.Authentication", "{2C226B6F-947F-806E-AB56-5318C87BE998}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{728874E7-57EA-5300-FDDD-4A392F892C62}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Authentication", "WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj", "{585E4EE6-E918-DDEC-79AD-C956E6A19E4B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests", "WebAssembly\WebAssembly.Authentication\test\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj", "{C80EB816-1E52-8D59-6C14-5567A23B5D82}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E199B8FB-B34C-E815-5C68-8C4C236C3F5B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "E2ETest", "E2ETest", "{BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebViewE2E.Test", "WebView\test\E2ETest\Microsoft.AspNetCore.Components.WebViewE2E.Test.csproj", "{C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebView", "WebView", "{CA12ED3E-B35C-B56F-F8CA-F6C9996B003D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{75F0ABB4-98D0-A880-0F84-660DB1C46419}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView", "WebView\WebView\src\Microsoft.AspNetCore.Components.WebView.csproj", "{491EE542-B9EB-10C7-06A2-6F2053C50482}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView.Test", "WebView\WebView\test\Microsoft.AspNetCore.Components.WebView.Test.csproj", "{BD1EEC86-7644-5761-1346-089385B5A749}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HostedBlazorWebassemblyApp", "HostedBlazorWebassemblyApp", "{D8364222-347F-695D-960D-5F83D75F4A3E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{493470CA-BAAC-C311-15C4-BEEB81EB0E42}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Client", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Client\HostedBlazorWebassemblyApp.Client.csproj", "{3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{D6A88611-6F2F-36CC-9E71-609E6DC6CBAE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Server", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Server\HostedBlazorWebassemblyApp.Server.csproj", "{A46AAF9E-39CC-085A-4EA7-A99537EA00E6}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{59BF9900-BDFB-2E52-B7D0-CA27D2239E1E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedBlazorWebassemblyApp.Shared", "WebAssembly\Samples\HostedBlazorWebassemblyApp\Shared\HostedBlazorWebassemblyApp.Shared.csproj", "{A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{6636F944-0A81-C8B7-09AA-414B5978CE4C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PhotinoPlatform", "PhotinoPlatform", "{316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebView.Photino", "WebView\Samples\PhotinoPlatform\src\Microsoft.AspNetCore.Components.WebView.Photino.csproj", "{DFB12E12-A532-EF12-87F4-BD537FF1662F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{978EA837-C2CB-DF69-BCE3-815ADE704D37}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhotinoTestApp", "WebView\Samples\PhotinoPlatform\testassets\PhotinoTestApp\PhotinoTestApp.csproj", "{9201E12B-135F-5E14-0672-AB5561520397}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D}.Release|Any CPU.Build.0 = Release|Any CPU - {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EB0043B9-6579-7370-BED1-D06FE9DFC755}.Release|Any CPU.Build.0 = Release|Any CPU - {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD2C8FC3-3703-7EF9-4551-70298314EF37}.Release|Any CPU.Build.0 = Release|Any CPU - {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8}.Release|Any CPU.Build.0 = Release|Any CPU - {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F}.Release|Any CPU.Build.0 = Release|Any CPU - {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE}.Release|Any CPU.Build.0 = Release|Any CPU - {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C45B3BA4-7E52-73AB-4942-5899597D4C36}.Release|Any CPU.Build.0 = Release|Any CPU - {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D554BB1E-51B7-3752-8566-135C9ADB7DCA}.Release|Any CPU.Build.0 = Release|Any CPU - {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC}.Release|Any CPU.Build.0 = Release|Any CPU - {E8540B19-EB66-03C6-13D2-6EE233C61524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E8540B19-EB66-03C6-13D2-6EE233C61524}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E8540B19-EB66-03C6-13D2-6EE233C61524}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E8540B19-EB66-03C6-13D2-6EE233C61524}.Release|Any CPU.Build.0 = Release|Any CPU - {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452}.Release|Any CPU.Build.0 = Release|Any CPU - {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039}.Release|Any CPU.Build.0 = Release|Any CPU - {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9}.Release|Any CPU.Build.0 = Release|Any CPU - {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754}.Release|Any CPU.Build.0 = Release|Any CPU - {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74BEC791-7060-4E1D-E77C-2490EFE2DFD0}.Release|Any CPU.Build.0 = Release|Any CPU - {1FCE400C-3875-3963-2105-084823B55013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1FCE400C-3875-3963-2105-084823B55013}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1FCE400C-3875-3963-2105-084823B55013}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1FCE400C-3875-3963-2105-084823B55013}.Release|Any CPU.Build.0 = Release|Any CPU - {3893606D-3E03-0FFD-95B4-A93121438268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3893606D-3E03-0FFD-95B4-A93121438268}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3893606D-3E03-0FFD-95B4-A93121438268}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3893606D-3E03-0FFD-95B4-A93121438268}.Release|Any CPU.Build.0 = Release|Any CPU - {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF}.Release|Any CPU.Build.0 = Release|Any CPU - {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AEEBE2B8-B7E4-178C-5640-626E89EF0C75}.Release|Any CPU.Build.0 = Release|Any CPU - {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B6384FF0-6E94-4ADE-F932-F4E886C1CADD}.Release|Any CPU.Build.0 = Release|Any CPU - {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8F18837A-BB27-ECF0-C1AA-4838E1C2A781}.Release|Any CPU.Build.0 = Release|Any CPU - {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68}.Release|Any CPU.Build.0 = Release|Any CPU - {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE}.Release|Any CPU.Build.0 = Release|Any CPU - {A4977A0A-A95B-7C35-F319-521331739C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4977A0A-A95B-7C35-F319-521331739C01}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4977A0A-A95B-7C35-F319-521331739C01}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4977A0A-A95B-7C35-F319-521331739C01}.Release|Any CPU.Build.0 = Release|Any CPU - {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0}.Release|Any CPU.Build.0 = Release|Any CPU - {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5F75C44-4165-6BB9-BB83-C01241D5775F}.Release|Any CPU.Build.0 = Release|Any CPU - {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Debug|Any CPU.Build.0 = Debug|Any CPU - {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Release|Any CPU.ActiveCfg = Release|Any CPU - {62F0E24C-EE9B-D5B3-D2CF-19358722D081}.Release|Any CPU.Build.0 = Release|Any CPU - {94769285-DE8C-43CF-8F43-2E6081DE261F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {94769285-DE8C-43CF-8F43-2E6081DE261F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94769285-DE8C-43CF-8F43-2E6081DE261F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {94769285-DE8C-43CF-8F43-2E6081DE261F}.Release|Any CPU.Build.0 = Release|Any CPU - {005A99AE-9829-5288-081E-6AA2C7068F41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {005A99AE-9829-5288-081E-6AA2C7068F41}.Debug|Any CPU.Build.0 = Debug|Any CPU - {005A99AE-9829-5288-081E-6AA2C7068F41}.Release|Any CPU.ActiveCfg = Release|Any CPU - {005A99AE-9829-5288-081E-6AA2C7068F41}.Release|Any CPU.Build.0 = Release|Any CPU - {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {384D771F-1D94-6B01-A1C3-435584F4B3BF}.Release|Any CPU.Build.0 = Release|Any CPU - {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA514A3D-030F-3753-55AC-95601ADF7FE9}.Release|Any CPU.Build.0 = Release|Any CPU - {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FEEE3D25-53D4-9F34-27B7-CBC04873009F}.Release|Any CPU.Build.0 = Release|Any CPU - {ACC68622-35F7-164F-FD1B-E68510FB877C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ACC68622-35F7-164F-FD1B-E68510FB877C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ACC68622-35F7-164F-FD1B-E68510FB877C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ACC68622-35F7-164F-FD1B-E68510FB877C}.Release|Any CPU.Build.0 = Release|Any CPU - {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE}.Release|Any CPU.Build.0 = Release|Any CPU - {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42C50CDC-3AF3-2866-9186-AE532C918BBA}.Release|Any CPU.Build.0 = Release|Any CPU - {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0262DCC6-3D46-CBCE-4888-9F37FDAAE470}.Release|Any CPU.Build.0 = Release|Any CPU - {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937}.Release|Any CPU.Build.0 = Release|Any CPU - {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C135F94-99F0-BF85-CD5D-F2BD288FC230}.Release|Any CPU.Build.0 = Release|Any CPU - {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8FC99803-7FB1-E7FD-F579-4FF49A324139}.Release|Any CPU.Build.0 = Release|Any CPU - {C004A041-806C-248D-6972-BC44CBD8AFDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C004A041-806C-248D-6972-BC44CBD8AFDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C004A041-806C-248D-6972-BC44CBD8AFDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C004A041-806C-248D-6972-BC44CBD8AFDB}.Release|Any CPU.Build.0 = Release|Any CPU - {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {69AB9EB3-9FB3-F134-F7BB-6F20719F293D}.Release|Any CPU.Build.0 = Release|Any CPU - {D9D391EA-769E-A96E-D230-453C9B9365DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9D391EA-769E-A96E-D230-453C9B9365DE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9D391EA-769E-A96E-D230-453C9B9365DE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9D391EA-769E-A96E-D230-453C9B9365DE}.Release|Any CPU.Build.0 = Release|Any CPU - {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2EF8EC2-4C19-61B5-DCF4-9014E729C057}.Release|Any CPU.Build.0 = Release|Any CPU - {2EEDD992-0F07-908F-52D7-52E0D0816172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2EEDD992-0F07-908F-52D7-52E0D0816172}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2EEDD992-0F07-908F-52D7-52E0D0816172}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2EEDD992-0F07-908F-52D7-52E0D0816172}.Release|Any CPU.Build.0 = Release|Any CPU - {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3}.Release|Any CPU.Build.0 = Release|Any CPU - {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90}.Release|Any CPU.Build.0 = Release|Any CPU - {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF}.Release|Any CPU.Build.0 = Release|Any CPU - {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FEF03057-3DED-46E9-44C2-E5A71183CBF7}.Release|Any CPU.Build.0 = Release|Any CPU - {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565}.Release|Any CPU.Build.0 = Release|Any CPU - {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7C427B4-5DAA-2DEC-D4FE-25513848B07E}.Release|Any CPU.Build.0 = Release|Any CPU - {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86}.Release|Any CPU.Build.0 = Release|Any CPU - {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72B9C791-DBD1-32DB-C566-B5D3B1D405E1}.Release|Any CPU.Build.0 = Release|Any CPU - {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F3C7C76A-FF30-4935-E238-7C5A838E3BCE}.Release|Any CPU.Build.0 = Release|Any CPU - {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {585E4EE6-E918-DDEC-79AD-C956E6A19E4B}.Release|Any CPU.Build.0 = Release|Any CPU - {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C80EB816-1E52-8D59-6C14-5567A23B5D82}.Release|Any CPU.Build.0 = Release|Any CPU - {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7}.Release|Any CPU.Build.0 = Release|Any CPU - {491EE542-B9EB-10C7-06A2-6F2053C50482}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {491EE542-B9EB-10C7-06A2-6F2053C50482}.Debug|Any CPU.Build.0 = Debug|Any CPU - {491EE542-B9EB-10C7-06A2-6F2053C50482}.Release|Any CPU.ActiveCfg = Release|Any CPU - {491EE542-B9EB-10C7-06A2-6F2053C50482}.Release|Any CPU.Build.0 = Release|Any CPU - {BD1EEC86-7644-5761-1346-089385B5A749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD1EEC86-7644-5761-1346-089385B5A749}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD1EEC86-7644-5761-1346-089385B5A749}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD1EEC86-7644-5761-1346-089385B5A749}.Release|Any CPU.Build.0 = Release|Any CPU - {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425}.Release|Any CPU.Build.0 = Release|Any CPU - {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A46AAF9E-39CC-085A-4EA7-A99537EA00E6}.Release|Any CPU.Build.0 = Release|Any CPU - {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B}.Release|Any CPU.Build.0 = Release|Any CPU - {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFB12E12-A532-EF12-87F4-BD537FF1662F}.Release|Any CPU.Build.0 = Release|Any CPU - {9201E12B-135F-5E14-0672-AB5561520397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9201E12B-135F-5E14-0672-AB5561520397}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9201E12B-135F-5E14-0672-AB5561520397}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9201E12B-135F-5E14-0672-AB5561520397}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {7188C2C0-F586-2E1C-E0B5-5DFC1FABF135} = {F883AD26-E2D9-0064-49F2-B333EF800629} - {E1ED6FA5-4DEB-A512-45B4-EDB7CD97BA9D} = {7188C2C0-F586-2E1C-E0B5-5DFC1FABF135} - {B4DAA744-D941-8AA5-7BB9-26961FB2C0FD} = {F883AD26-E2D9-0064-49F2-B333EF800629} - {EB0043B9-6579-7370-BED1-D06FE9DFC755} = {B4DAA744-D941-8AA5-7BB9-26961FB2C0FD} - {9EA3DC81-E26A-677F-6A25-3A91573DF4FE} = {278F3FFB-8C21-435B-507F-61B78986A400} - {BD2C8FC3-3703-7EF9-4551-70298314EF37} = {9EA3DC81-E26A-677F-6A25-3A91573DF4FE} - {4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA} = {278F3FFB-8C21-435B-507F-61B78986A400} - {CA605D3B-4E98-B5CB-64BA-5F4BB643CEC8} = {4DB0CE2E-3A72-329B-A6AA-ED8743CB06CA} - {A19F1FF1-BB91-3A1F-2D5C-FA6137FD214F} = {04B96F53-E713-70DE-173F-A95873598AF4} - {D27B063A-B8D1-101F-0A9A-82D5880B0092} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} - {99B7D762-BB6F-C5F9-41F8-9A7D13A9B9FE} = {D27B063A-B8D1-101F-0A9A-82D5880B0092} - {B2FBA576-327C-1BE5-E29F-D95D457F7733} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} - {C45B3BA4-7E52-73AB-4942-5899597D4C36} = {B2FBA576-327C-1BE5-E29F-D95D457F7733} - {F5E7128C-C6CF-3B49-7306-A9D6E76AC385} = {F30895DC-C3AC-FF44-FFF8-D51D98AE1B61} - {D554BB1E-51B7-3752-8566-135C9ADB7DCA} = {F5E7128C-C6CF-3B49-7306-A9D6E76AC385} - {C1BECA30-1B7A-2AD9-E261-E8D798C74B5D} = {1956B0E3-C3A6-1D29-BB64-D91F2292772C} - {AD2A718F-7A4F-70A8-DEF8-2A89689A36DC} = {C1BECA30-1B7A-2AD9-E261-E8D798C74B5D} - {8E784D3B-3E6B-7A86-D8E3-544301E375D9} = {DCF9C18E-19C8-9748-4C1C-32AB5F62F46B} - {E8540B19-EB66-03C6-13D2-6EE233C61524} = {8E784D3B-3E6B-7A86-D8E3-544301E375D9} - {CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38} = {DCF9C18E-19C8-9748-4C1C-32AB5F62F46B} - {9B6BB5AE-8E5B-531A-F5B6-AB5D3B952452} = {CF6FAFD1-3A02-EA33-ECEB-FFE3AA875C38} - {97E78C61-B29B-A484-4CE9-4BB29EB9331A} = {5D4ABE75-A633-7578-A6F0-BB88D48E78A4} - {AF6B0E54-144A-5ECE-91FF-55B1BFEE5039} = {97E78C61-B29B-A484-4CE9-4BB29EB9331A} - {BD4137AF-3EE6-D962-BF72-9904BFD46A79} = {5D4ABE75-A633-7578-A6F0-BB88D48E78A4} - {D3B32404-5953-67EE-DBA7-6A8F1AB1A0B9} = {BD4137AF-3EE6-D962-BF72-9904BFD46A79} - {FC12C86F-5866-69D4-B7E5-3F0EB4E3F754} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} - {74BEC791-7060-4E1D-E77C-2490EFE2DFD0} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} - {1FCE400C-3875-3963-2105-084823B55013} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} - {2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002} = {DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E} - {3893606D-3E03-0FFD-95B4-A93121438268} = {2132E9AA-A8A6-6DB3-1CCB-FE240A8CB002} - {968FF768-FCED-1723-7BDD-DA5CA8774CA7} = {DAD03CFC-D5FA-AC94-41C7-9ABAB326F09E} - {8A37E723-99EF-15F0-8C1F-E9755F8EDEEF} = {968FF768-FCED-1723-7BDD-DA5CA8774CA7} - {B7885BA3-4776-F672-E8F6-B5866B779C62} = {0C88DD14-F956-CE84-757C-A364CCF449FC} - {AEEBE2B8-B7E4-178C-5640-626E89EF0C75} = {B7885BA3-4776-F672-E8F6-B5866B779C62} - {228B02D4-B903-8A36-6CC3-E6BEA647CE1E} = {256F4E96-6A73-9ABE-786F-840C672A50F4} - {B6384FF0-6E94-4ADE-F932-F4E886C1CADD} = {228B02D4-B903-8A36-6CC3-E6BEA647CE1E} - {28716C4F-1493-E9A1-BA33-F0DEF262A65A} = {256F4E96-6A73-9ABE-786F-840C672A50F4} - {8F18837A-BB27-ECF0-C1AA-4838E1C2A781} = {28716C4F-1493-E9A1-BA33-F0DEF262A65A} - {595095FC-11E7-9A6C-713C-1AA81E4007ED} = {04B96F53-E713-70DE-173F-A95873598AF4} - {09B1DD90-461D-BA25-543A-2B9E36909F2A} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} - {CC7E1BFF-D2BF-D91B-92DC-5B5B99898A68} = {09B1DD90-461D-BA25-543A-2B9E36909F2A} - {8C1BB3C5-A56A-60F2-587A-1CDE499093FF} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} - {672746A2-DFDD-0444-0D70-E6B7CB8A4ABE} = {8C1BB3C5-A56A-60F2-587A-1CDE499093FF} - {8AED47D8-E613-0A63-AFBD-DB2A96051743} = {595095FC-11E7-9A6C-713C-1AA81E4007ED} - {A4977A0A-A95B-7C35-F319-521331739C01} = {8AED47D8-E613-0A63-AFBD-DB2A96051743} - {E329DD7B-EA06-0E35-2452-F0374B45C92D} = {453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC} - {EE8635E8-7069-5440-4C4D-3E712D0A6E31} = {E329DD7B-EA06-0E35-2452-F0374B45C92D} - {8BF2A51C-F22C-0D39-AAC7-7AE776B3D3D0} = {EE8635E8-7069-5440-4C4D-3E712D0A6E31} - {8C21E68A-654B-F80C-2D42-F0D033850D3B} = {E329DD7B-EA06-0E35-2452-F0374B45C92D} - {D5F75C44-4165-6BB9-BB83-C01241D5775F} = {8C21E68A-654B-F80C-2D42-F0D033850D3B} - {8B02DB0C-FE4B-328D-C414-580634248F4A} = {453459A7-61B0-99BD-5FE4-DC2B7EAB7FCC} - {AB061C51-2A24-F88C-EF6D-0215BD882074} = {8B02DB0C-FE4B-328D-C414-580634248F4A} - {62F0E24C-EE9B-D5B3-D2CF-19358722D081} = {AB061C51-2A24-F88C-EF6D-0215BD882074} - {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} = {0C88DD14-F956-CE84-757C-A364CCF449FC} - {94769285-DE8C-43CF-8F43-2E6081DE261F} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {005A99AE-9829-5288-081E-6AA2C7068F41} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {384D771F-1D94-6B01-A1C3-435584F4B3BF} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {DA514A3D-030F-3753-55AC-95601ADF7FE9} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {FEEE3D25-53D4-9F34-27B7-CBC04873009F} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {ACC68622-35F7-164F-FD1B-E68510FB877C} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {DB54C63C-C3DD-FDB5-0D9E-EE12177496DE} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {42C50CDC-3AF3-2866-9186-AE532C918BBA} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {0262DCC6-3D46-CBCE-4888-9F37FDAAE470} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {B7BBE6FD-A4D7-3416-ECEB-05A6B5239937} = {BEC57E9A-3A13-6F27-EBDA-E7240D8E32C7} - {A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {805B4876-2550-7ADC-2FD1-6362247661A7} = {A79C6110-8F76-1DB1-0FD8-A69EDA72E8BC} - {3C135F94-99F0-BF85-CD5D-F2BD288FC230} = {805B4876-2550-7ADC-2FD1-6362247661A7} - {5ED11752-357D-2F9A-0D62-6FBFEC2923EA} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {4030600A-B42C-7665-4E1E-9DEDBAF9080A} = {5ED11752-357D-2F9A-0D62-6FBFEC2923EA} - {8FC99803-7FB1-E7FD-F579-4FF49A324139} = {4030600A-B42C-7665-4E1E-9DEDBAF9080A} - {2D1527BB-743D-5D96-93C8-1B5741ADC02B} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {2CF24191-5ACD-5999-EAB4-F3ED6F833833} = {2D1527BB-743D-5D96-93C8-1B5741ADC02B} - {C004A041-806C-248D-6972-BC44CBD8AFDB} = {2CF24191-5ACD-5999-EAB4-F3ED6F833833} - {F24703D6-F12F-EE78-E988-49EB11C8433B} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {A6DB63EE-406F-8FC6-244C-D0DECD2202FB} = {F24703D6-F12F-EE78-E988-49EB11C8433B} - {69AB9EB3-9FB3-F134-F7BB-6F20719F293D} = {A6DB63EE-406F-8FC6-244C-D0DECD2202FB} - {BC25C024-DEC1-AC57-3E67-CBE61A818765} = {F24703D6-F12F-EE78-E988-49EB11C8433B} - {D9D391EA-769E-A96E-D230-453C9B9365DE} = {BC25C024-DEC1-AC57-3E67-CBE61A818765} - {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {F2EF8EC2-4C19-61B5-DCF4-9014E729C057} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {2EEDD992-0F07-908F-52D7-52E0D0816172} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {BABB04C9-D860-D830-3E50-7AF5D1CDB1C3} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {35FF93EC-4CEB-09BC-C3C1-B218E4FEBB90} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {D94FCCB0-E6DD-75AF-9D33-8B2E88D851DF} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {FEF03057-3DED-46E9-44C2-E5A71183CBF7} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {D7372AB6-0FF4-A406-B5D8-2DD7AEA27565} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {E7C427B4-5DAA-2DEC-D4FE-25513848B07E} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {8C83C95C-9A82-1DFA-A4DB-90EC50F32D86} = {F60C0A93-E7A1-AA4F-C800-18D21FD1802D} - {2114FDDC-431A-A228-9FBD-A2D77B669641} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8} = {2114FDDC-431A-A228-9FBD-A2D77B669641} - {72B9C791-DBD1-32DB-C566-B5D3B1D405E1} = {5C5577CB-F2D2-8B06-6E0B-E95FF80B1BD8} - {73AD86C9-A183-63E1-9E65-08B4582D7CA4} = {2114FDDC-431A-A228-9FBD-A2D77B669641} - {F3C7C76A-FF30-4935-E238-7C5A838E3BCE} = {73AD86C9-A183-63E1-9E65-08B4582D7CA4} - {2C226B6F-947F-806E-AB56-5318C87BE998} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {728874E7-57EA-5300-FDDD-4A392F892C62} = {2C226B6F-947F-806E-AB56-5318C87BE998} - {585E4EE6-E918-DDEC-79AD-C956E6A19E4B} = {728874E7-57EA-5300-FDDD-4A392F892C62} - {F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719} = {2C226B6F-947F-806E-AB56-5318C87BE998} - {C80EB816-1E52-8D59-6C14-5567A23B5D82} = {F76B3B9A-CBDD-C9E5-2FCE-3B2EEF21E719} - {E199B8FB-B34C-E815-5C68-8C4C236C3F5B} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} - {BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828} = {E199B8FB-B34C-E815-5C68-8C4C236C3F5B} - {C44AFCA8-EDE5-0389-CFE8-22A83AC3ECF7} = {BA4E4483-9F0E-0EA1-9A48-5D10BD1CE828} - {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} - {75F0ABB4-98D0-A880-0F84-660DB1C46419} = {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} - {491EE542-B9EB-10C7-06A2-6F2053C50482} = {75F0ABB4-98D0-A880-0F84-660DB1C46419} - {7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE} = {CA12ED3E-B35C-B56F-F8CA-F6C9996B003D} - {BD1EEC86-7644-5761-1346-089385B5A749} = {7A9BA3EE-168D-6DA9-50D7-7007A7B1FDBE} - {83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED} = {032573FE-E973-EE49-F164-6E17D60C24C1} - {D8364222-347F-695D-960D-5F83D75F4A3E} = {83B7D554-7FE9-7791-B8EF-9CEB0E9B38ED} - {493470CA-BAAC-C311-15C4-BEEB81EB0E42} = {D8364222-347F-695D-960D-5F83D75F4A3E} - {3F8E5EC2-DB89-39DB-E3FA-43EB5A64A425} = {493470CA-BAAC-C311-15C4-BEEB81EB0E42} - {D6A88611-6F2F-36CC-9E71-609E6DC6CBAE} = {D8364222-347F-695D-960D-5F83D75F4A3E} - {A46AAF9E-39CC-085A-4EA7-A99537EA00E6} = {D6A88611-6F2F-36CC-9E71-609E6DC6CBAE} - {59BF9900-BDFB-2E52-B7D0-CA27D2239E1E} = {D8364222-347F-695D-960D-5F83D75F4A3E} - {A0ACE183-5E76-FEB4-09F5-7ABE8795E99B} = {59BF9900-BDFB-2E52-B7D0-CA27D2239E1E} - {6636F944-0A81-C8B7-09AA-414B5978CE4C} = {F75C3326-23C9-B46B-1CDE-63D2E405EED1} - {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} = {6636F944-0A81-C8B7-09AA-414B5978CE4C} - {7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F} = {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} - {DFB12E12-A532-EF12-87F4-BD537FF1662F} = {7DE6D604-1AB1-EB79-3DD0-2CC5CB926D2F} - {978EA837-C2CB-DF69-BCE3-815ADE704D37} = {316E34B4-CD88-C8D3-E9E3-33F5B40E2CD1} - {9201E12B-135F-5E14-0672-AB5561520397} = {978EA837-C2CB-DF69-BCE3-815ADE704D37} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7F5C71B7-6B0B-40C5-A3E7-E9811996ECAA} - EndGlobalSection -EndGlobal diff --git a/src/submodules/googletest b/src/submodules/googletest index 1b96fa13f549..065127f1e4b4 160000 --- a/src/submodules/googletest +++ b/src/submodules/googletest @@ -1 +1 @@ -Subproject commit 1b96fa13f549387b7549cc89e1a785cf143a1a50 +Subproject commit 065127f1e4b46c5f14fc73cf8d323c221f9dc68e From 902cdc9c38d00f63f50e69ab3bea09f57d0d2d7b Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Tue, 16 Dec 2025 17:16:38 +0100 Subject: [PATCH 17/20] Add limit for encoded value --- .../src/DependencyInjection/TempDataService.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index aa26f4e7352b..2800d45a224f 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -14,6 +14,7 @@ internal sealed partial class TempDataService { private const string CookieName = ".AspNetCore.Components.TempData"; private const string PurposeString = "Microsoft.AspNetCore.Components.Endpoints.TempDataService"; + private const int MaxEncodedLength = 4050; private static IDataProtector GetDataProtector(HttpContext httpContext) { @@ -92,6 +93,20 @@ public static void Save(HttpContext httpContext, TempData tempData) var protectedBytes = GetDataProtector(httpContext).Protect(bytes); var encodedValue = WebEncoders.Base64UrlEncode(protectedBytes); + if (encodedValue.Length > MaxEncodedLength) + { + if (httpContext.RequestServices.GetService>() is { } logger) + { + Log.TempDataCookieSaveFailure(logger, CookieName); + } + + httpContext.Response.Cookies.Delete(CookieName, new CookieOptions + { + Path = httpContext.Request.PathBase.HasValue ? httpContext.Request.PathBase.Value : "/", + }); + return; + } + httpContext.Response.Cookies.Append(CookieName, encodedValue, new CookieOptions { HttpOnly = true, @@ -189,5 +204,8 @@ private static partial class Log { [LoggerMessage(3, LogLevel.Warning, "The temp data cookie {CookieName} could not be loaded.", EventName = "TempDataCookieLoadFailure")] public static partial void TempDataCookieLoadFailure(ILogger logger, string cookieName, Exception exception); + + [LoggerMessage(3, LogLevel.Warning, "The temp data cookie {CookieName} could not be saved, because it is too large to fit in a single cookie.", EventName = "TempDataCookieSaveFailure")] + public static partial void TempDataCookieSaveFailure(ILogger logger, string cookieName); } } From eff02b67023531a846f58dd3ddbe20f75624a582 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Wed, 17 Dec 2025 17:34:27 +0100 Subject: [PATCH 18/20] Small decoupling --- ...orComponentsServiceCollectionExtensions.cs | 21 +-------- .../Endpoints/src/PublicAPI.Unshipped.txt | 1 + ...DataProviderServiceCollectionExtensions.cs | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs diff --git a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs index 4e3a0bd2a49f..14155786f769 100644 --- a/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs +++ b/src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs @@ -74,26 +74,7 @@ public static IRazorComponentsBuilder AddRazorComponents(this IServiceCollection services.TryAddCascadingValue(sp => sp.GetRequiredService().HttpContext); services.TryAddScoped(); services.TryAddScoped(); - services.TryAddCascadingValue(sp => - { - var httpContext = sp.GetRequiredService().HttpContext; - if (httpContext is null) - { - return null!; - } - var key = typeof(ITempData); - if (!httpContext.Items.TryGetValue(key, out var tempData)) - { - var tempDataInstance = TempDataService.Load(httpContext); - httpContext.Items[key] = tempDataInstance; - httpContext.Response.OnStarting(() => - { - TempDataService.Save(httpContext, tempDataInstance); - return Task.CompletedTask; - }); - } - return (ITempData)httpContext.Items[key]!; - }); + services.AddTempDataValueProvider(); services.TryAddScoped(); RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration(services, RenderMode.InteractiveWebAssembly); diff --git a/src/Components/Endpoints/src/PublicAPI.Unshipped.txt b/src/Components/Endpoints/src/PublicAPI.Unshipped.txt index ac1780ba883e..b68275551dce 100644 --- a/src/Components/Endpoints/src/PublicAPI.Unshipped.txt +++ b/src/Components/Endpoints/src/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ #nullable enable Microsoft.AspNetCore.Components.Endpoints.BasePath Microsoft.AspNetCore.Components.Endpoints.BasePath.BasePath() -> void +Microsoft.AspNetCore.Components.Endpoints.TempDataProviderServiceCollectionExtensions diff --git a/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs b/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs new file mode 100644 index 000000000000..74cf7fe9ae41 --- /dev/null +++ b/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Components.Endpoints; + +/// +/// Enables component parameters to be supplied from the string with . +/// +public static class TempDataProviderServiceCollectionExtensions +{ + public static IServiceCollection AddTempDataValueProvider(this IServiceCollection services) + { + services.TryAddCascadingValue(sp => + { + var httpContext = sp.GetRequiredService().HttpContext; + if (httpContext is null) + { + return null!; + } + return GetOrCreateTempData(httpContext); + }); + return services; + } + + private static ITempData GetOrCreateTempData(HttpContext httpContext) + { + var key = typeof(ITempData); + if (!httpContext.Items.TryGetValue(key, out var tempData)) + { + var tempDataInstance = TempDataService.Load(httpContext); + httpContext.Items[key] = tempDataInstance; + httpContext.Response.OnStarting(() => + { + TempDataService.Save(httpContext, tempDataInstance); + return Task.CompletedTask; + }); + } + return (ITempData)httpContext.Items[key]!; + } +} From 1f23e69b554605d59f00fc2d6950146bbc573530 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Thu, 18 Dec 2025 11:19:52 +0100 Subject: [PATCH 19/20] Moved to Endpoints --- .../Components/src/PublicAPI.Unshipped.txt | 19 ------------------ .../Endpoints/src/PublicAPI.Unshipped.txt | 20 +++++++++++++++++++ .../src/TempData}/ITempData.cs | 0 .../src/TempData}/TempData.cs | 0 ...DataProviderServiceCollectionExtensions.cs | 5 ++++- .../test/TempDataTest.cs | 2 +- 6 files changed, 25 insertions(+), 21 deletions(-) rename src/Components/{Components/src => Endpoints/src/TempData}/ITempData.cs (100%) rename src/Components/{Components/src => Endpoints/src/TempData}/TempData.cs (100%) rename src/Components/{Components => Endpoints}/test/TempDataTest.cs (99%) diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index 2e3f440a6e8b..908e19bcf6f2 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -1,23 +1,4 @@ #nullable enable -Microsoft.AspNetCore.Components.ITempData -Microsoft.AspNetCore.Components.ITempData.Get(string! key) -> object? -Microsoft.AspNetCore.Components.ITempData.Keep() -> void -Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void -Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? -Microsoft.AspNetCore.Components.TempData -Microsoft.AspNetCore.Components.TempData.ContainsValue(object? value) -> bool -Microsoft.AspNetCore.Components.TempData.TempData() -> void -Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? -Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? -Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void -Microsoft.AspNetCore.Components.TempData.Keep() -> void -Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void -Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object? -Microsoft.AspNetCore.Components.TempData.Clear() -> void -Microsoft.AspNetCore.Components.TempData.Remove(string! key) -> bool -Microsoft.AspNetCore.Components.TempData.ContainsKey(string! key) -> bool -Microsoft.AspNetCore.Components.TempData.Load(System.Collections.Generic.IDictionary! data) -> void -Microsoft.AspNetCore.Components.TempData.Save() -> System.Collections.Generic.IDictionary! Microsoft.AspNetCore.Components.IComponentPropertyActivator Microsoft.AspNetCore.Components.IComponentPropertyActivator.GetActivator(System.Type! componentType) -> System.Action! *REMOVED*Microsoft.AspNetCore.Components.ResourceAsset.ResourceAsset(string! url, System.Collections.Generic.IReadOnlyList? properties) -> void diff --git a/src/Components/Endpoints/src/PublicAPI.Unshipped.txt b/src/Components/Endpoints/src/PublicAPI.Unshipped.txt index b68275551dce..fa169c158438 100644 --- a/src/Components/Endpoints/src/PublicAPI.Unshipped.txt +++ b/src/Components/Endpoints/src/PublicAPI.Unshipped.txt @@ -2,3 +2,23 @@ Microsoft.AspNetCore.Components.Endpoints.BasePath Microsoft.AspNetCore.Components.Endpoints.BasePath.BasePath() -> void Microsoft.AspNetCore.Components.Endpoints.TempDataProviderServiceCollectionExtensions +Microsoft.AspNetCore.Components.ITempData +Microsoft.AspNetCore.Components.ITempData.Get(string! key) -> object? +Microsoft.AspNetCore.Components.ITempData.Keep() -> void +Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void +Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object? +Microsoft.AspNetCore.Components.TempData +Microsoft.AspNetCore.Components.TempData.TempData() -> void +Microsoft.AspNetCore.Components.TempData.Clear() -> void +Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object? +Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void +Microsoft.AspNetCore.Components.TempData.ContainsKey(string! key) -> bool +Microsoft.AspNetCore.Components.TempData.ContainsValue(object? value) -> bool +Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object? +Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object? +Microsoft.AspNetCore.Components.TempData.Keep() -> void +Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void +Microsoft.AspNetCore.Components.TempData.Remove(string! key) -> bool +Microsoft.AspNetCore.Components.TempData.Load(System.Collections.Generic.IDictionary! data) -> void +Microsoft.AspNetCore.Components.TempData.Save() -> System.Collections.Generic.IDictionary! +static Microsoft.AspNetCore.Components.Endpoints.TempDataProviderServiceCollectionExtensions.AddTempDataValueProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Endpoints/src/TempData/ITempData.cs similarity index 100% rename from src/Components/Components/src/ITempData.cs rename to src/Components/Endpoints/src/TempData/ITempData.cs diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Endpoints/src/TempData/TempData.cs similarity index 100% rename from src/Components/Components/src/TempData.cs rename to src/Components/Endpoints/src/TempData/TempData.cs diff --git a/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs b/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs index 74cf7fe9ae41..3c3c333c35c2 100644 --- a/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs +++ b/src/Components/Endpoints/src/TempDataProviderServiceCollectionExtensions.cs @@ -7,10 +7,13 @@ namespace Microsoft.AspNetCore.Components.Endpoints; /// -/// Enables component parameters to be supplied from the string with . +/// Enables component parameters to be supplied from the . /// public static class TempDataProviderServiceCollectionExtensions { + /// + /// Enables component parameters to be supplied from the . + /// public static IServiceCollection AddTempDataValueProvider(this IServiceCollection services) { services.TryAddCascadingValue(sp => diff --git a/src/Components/Components/test/TempDataTest.cs b/src/Components/Endpoints/test/TempDataTest.cs similarity index 99% rename from src/Components/Components/test/TempDataTest.cs rename to src/Components/Endpoints/test/TempDataTest.cs index e02c062ffaad..f0511ca1f4ab 100644 --- a/src/Components/Components/test/TempDataTest.cs +++ b/src/Components/Endpoints/test/TempDataTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.AspNetCore.Components; +namespace Microsoft.AspNetCore.Components.Endpoints; public class TempDataTest { From 98ece70d9bcd76d92a2a6714c8b2fd7e100bade4 Mon Sep 17 00:00:00 2001 From: Daria Tiurina Date: Thu, 18 Dec 2025 14:55:42 +0100 Subject: [PATCH 20/20] Lazy loading --- .../DependencyInjection/TempDataService.cs | 5 +++ .../Endpoints/src/TempData/TempData.cs | 37 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs index 2800d45a224f..13f96f9caecb 100644 --- a/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/TempDataService.cs @@ -22,6 +22,11 @@ private static IDataProtector GetDataProtector(HttpContext httpContext) return dataProtectionProvider.CreateProtector(PurposeString); } + public static TempData CreateEmpty(HttpContext httpContext) + { + return new TempData(() => Load(httpContext)); + } + public static TempData Load(HttpContext httpContext) { try diff --git a/src/Components/Endpoints/src/TempData/TempData.cs b/src/Components/Endpoints/src/TempData/TempData.cs index 3778e385bf32..bd4f4c40a551 100644 --- a/src/Components/Endpoints/src/TempData/TempData.cs +++ b/src/Components/Endpoints/src/TempData/TempData.cs @@ -10,13 +10,36 @@ public class TempData : ITempData { private readonly Dictionary _data = new(StringComparer.OrdinalIgnoreCase); private readonly HashSet _retainedKeys = new(StringComparer.OrdinalIgnoreCase); + private Func>? _loadFunc; + private bool _loaded; + + internal TempData(Func>? loadFunc = null) + { + _loadFunc = loadFunc; + } + + private void EnsureLoaded() + { + if (!_loaded && _loadFunc is not null) + { + var dataToLoad = _loadFunc(); + Load(dataToLoad); + _loadFunc = null!; + _loaded = true; + } + } /// public object? this[string key] { - get => Get(key); + get + { + EnsureLoaded(); + return Get(key); + } set { + EnsureLoaded(); _data[key] = value; _retainedKeys.Add(key); } @@ -25,6 +48,7 @@ public object? this[string key] /// public object? Get(string key) { + EnsureLoaded(); _retainedKeys.Remove(key); return _data.GetValueOrDefault(key); } @@ -32,12 +56,14 @@ public object? this[string key] /// public object? Peek(string key) { + EnsureLoaded(); return _data.GetValueOrDefault(key); } /// public void Keep() { + EnsureLoaded(); _retainedKeys.Clear(); _retainedKeys.UnionWith(_data.Keys); } @@ -45,6 +71,7 @@ public void Keep() /// public void Keep(string key) { + EnsureLoaded(); if (_data.ContainsKey(key)) { _retainedKeys.Add(key); @@ -54,12 +81,14 @@ public void Keep(string key) /// public bool ContainsKey(string key) { + EnsureLoaded(); return _data.ContainsKey(key); } /// public bool Remove(string key) { + EnsureLoaded(); _retainedKeys.Remove(key); return _data.Remove(key); } @@ -69,6 +98,7 @@ public bool Remove(string key) /// public bool ContainsValue(object? value) { + EnsureLoaded(); return _data.ContainsValue(value); } @@ -77,6 +107,7 @@ public bool ContainsValue(object? value) /// public IDictionary Save() { + EnsureLoaded(); var dataToSave = new Dictionary(); foreach (var key in _retainedKeys) { @@ -102,6 +133,7 @@ public void Load(IDictionary data) /// public void Clear() { + EnsureLoaded(); _data.Clear(); _retainedKeys.Clear(); } @@ -137,6 +169,7 @@ public void Clear() void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { + EnsureLoaded(); ((ICollection>)_data).CopyTo(array, arrayIndex); } @@ -151,11 +184,13 @@ public void Clear() IEnumerator> IEnumerable>.GetEnumerator() { + EnsureLoaded(); return new TempDataEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { + EnsureLoaded(); return new TempDataEnumerator(this); }