parent
57eb52ad47
commit
d9f035ad7c
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
|
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
|
||||||
|
|
@ -32,6 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
private const string VaryByRouteName = "VaryByRoute";
|
private const string VaryByRouteName = "VaryByRoute";
|
||||||
private const string VaryByCookieName = "VaryByCookie";
|
private const string VaryByCookieName = "VaryByCookie";
|
||||||
private const string VaryByUserName = "VaryByUser";
|
private const string VaryByUserName = "VaryByUser";
|
||||||
|
private const string VaryByCulture = "VaryByCulture";
|
||||||
|
|
||||||
private readonly string _prefix;
|
private readonly string _prefix;
|
||||||
private readonly string _varyBy;
|
private readonly string _varyBy;
|
||||||
|
|
@ -43,7 +45,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
private readonly IList<KeyValuePair<string, string>> _routeValues;
|
private readonly IList<KeyValuePair<string, string>> _routeValues;
|
||||||
private readonly IList<KeyValuePair<string, string>> _cookies;
|
private readonly IList<KeyValuePair<string, string>> _cookies;
|
||||||
private readonly bool _varyByUser;
|
private readonly bool _varyByUser;
|
||||||
|
private readonly bool _varyByCulture;
|
||||||
private readonly string _username;
|
private readonly string _username;
|
||||||
|
private readonly CultureInfo _requestCulture;
|
||||||
|
private readonly CultureInfo _requestUICulture;
|
||||||
|
|
||||||
private string _generatedKey;
|
private string _generatedKey;
|
||||||
private int? _hashcode;
|
private int? _hashcode;
|
||||||
|
|
@ -87,11 +92,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
_queries = ExtractCollection(tagHelper.VaryByQuery, request.Query, QueryAccessor);
|
_queries = ExtractCollection(tagHelper.VaryByQuery, request.Query, QueryAccessor);
|
||||||
_routeValues = ExtractCollection(tagHelper.VaryByRoute, tagHelper.ViewContext.RouteData.Values, RouteValueAccessor);
|
_routeValues = ExtractCollection(tagHelper.VaryByRoute, tagHelper.ViewContext.RouteData.Values, RouteValueAccessor);
|
||||||
_varyByUser = tagHelper.VaryByUser;
|
_varyByUser = tagHelper.VaryByUser;
|
||||||
|
_varyByCulture = tagHelper.VaryByCulture;
|
||||||
|
|
||||||
if (_varyByUser)
|
if (_varyByUser)
|
||||||
{
|
{
|
||||||
_username = httpContext.User?.Identity?.Name;
|
_username = httpContext.User?.Identity?.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_varyByCulture)
|
||||||
|
{
|
||||||
|
_requestCulture = CultureInfo.CurrentCulture;
|
||||||
|
_requestUICulture = CultureInfo.CurrentUICulture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for unit testing.
|
// Internal for unit testing.
|
||||||
|
|
@ -137,6 +149,17 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
.Append(_username);
|
.Append(_username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_varyByCulture)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.Append(CacheKeyTokenSeparator)
|
||||||
|
.Append(VaryByCulture)
|
||||||
|
.Append(CacheKeyTokenSeparator)
|
||||||
|
.Append(_requestCulture)
|
||||||
|
.Append(CacheKeyTokenSeparator)
|
||||||
|
.Append(_requestUICulture);
|
||||||
|
}
|
||||||
|
|
||||||
_generatedKey = builder.ToString();
|
_generatedKey = builder.ToString();
|
||||||
|
|
||||||
return _generatedKey;
|
return _generatedKey;
|
||||||
|
|
@ -164,13 +187,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
var other = obj as CacheTagKey;
|
if (obj is CacheTagKey other)
|
||||||
if (other == null)
|
|
||||||
{
|
{
|
||||||
return false;
|
return Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Equals(other);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -185,8 +207,26 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
AreSame(_headers, other._headers) &&
|
AreSame(_headers, other._headers) &&
|
||||||
AreSame(_queries, other._queries) &&
|
AreSame(_queries, other._queries) &&
|
||||||
AreSame(_routeValues, other._routeValues) &&
|
AreSame(_routeValues, other._routeValues) &&
|
||||||
_varyByUser == other._varyByUser &&
|
(_varyByUser == other._varyByUser &&
|
||||||
(!_varyByUser || string.Equals(other._username, _username, StringComparison.Ordinal));
|
(!_varyByUser || string.Equals(other._username, _username, StringComparison.Ordinal))) &&
|
||||||
|
CultureEquals();
|
||||||
|
|
||||||
|
bool CultureEquals()
|
||||||
|
{
|
||||||
|
if (_varyByCulture != other._varyByCulture)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_varyByCulture)
|
||||||
|
{
|
||||||
|
// Neither has culture set.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _requestCulture.Equals(other._requestCulture) &&
|
||||||
|
_requestUICulture.Equals(other._requestUICulture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -211,6 +251,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
hashCodeCombiner.Add(_expiresSliding);
|
hashCodeCombiner.Add(_expiresSliding);
|
||||||
hashCodeCombiner.Add(_varyBy, StringComparer.Ordinal);
|
hashCodeCombiner.Add(_varyBy, StringComparer.Ordinal);
|
||||||
hashCodeCombiner.Add(_username, StringComparer.Ordinal);
|
hashCodeCombiner.Add(_username, StringComparer.Ordinal);
|
||||||
|
hashCodeCombiner.Add(_requestCulture);
|
||||||
|
hashCodeCombiner.Add(_requestUICulture);
|
||||||
|
|
||||||
CombineCollectionHashCode(hashCodeCombiner, VaryByCookieName, _cookies);
|
CombineCollectionHashCode(hashCodeCombiner, VaryByCookieName, _cookies);
|
||||||
CombineCollectionHashCode(hashCodeCombiner, VaryByHeaderName, _headers);
|
CombineCollectionHashCode(hashCodeCombiner, VaryByHeaderName, _headers);
|
||||||
|
|
@ -222,7 +264,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
return _hashcode.Value;
|
return _hashcode.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IList<KeyValuePair<string, string>> ExtractCollection<TSourceCollection>(string keys, TSourceCollection collection, Func<TSourceCollection, string, string> accessor)
|
private static IList<KeyValuePair<string, string>> ExtractCollection<TSourceCollection>(
|
||||||
|
string keys,
|
||||||
|
TSourceCollection collection,
|
||||||
|
Func<TSourceCollection, string, string> accessor)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(keys))
|
if (string.IsNullOrEmpty(keys))
|
||||||
{
|
{
|
||||||
|
|
@ -323,4 +368,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
|
@ -20,6 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
private const string VaryByRouteAttributeName = "vary-by-route";
|
private const string VaryByRouteAttributeName = "vary-by-route";
|
||||||
private const string VaryByCookieAttributeName = "vary-by-cookie";
|
private const string VaryByCookieAttributeName = "vary-by-cookie";
|
||||||
private const string VaryByUserAttributeName = "vary-by-user";
|
private const string VaryByUserAttributeName = "vary-by-user";
|
||||||
|
private const string VaryByCultureAttributeName = "vary-by-culture";
|
||||||
private const string ExpiresOnAttributeName = "expires-on";
|
private const string ExpiresOnAttributeName = "expires-on";
|
||||||
private const string ExpiresAfterAttributeName = "expires-after";
|
private const string ExpiresAfterAttributeName = "expires-after";
|
||||||
private const string ExpiresSlidingAttributeName = "expires-sliding";
|
private const string ExpiresSlidingAttributeName = "expires-sliding";
|
||||||
|
|
@ -93,6 +95,16 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
[HtmlAttributeName(VaryByUserAttributeName)]
|
[HtmlAttributeName(VaryByUserAttributeName)]
|
||||||
public bool VaryByUser { get; set; }
|
public bool VaryByUser { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value that determines if the cached result is to be varied by request culture.
|
||||||
|
/// <para>
|
||||||
|
/// Setting this to <c>true</c> would result in the result to be varied by <see cref="CultureInfo.CurrentCulture" />
|
||||||
|
/// and <see cref="CultureInfo.CurrentUICulture" />.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName(VaryByCultureAttributeName)]
|
||||||
|
public bool VaryByCulture { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the exact <see cref="DateTimeOffset"/> the cache entry should be evicted.
|
/// Gets or sets the exact <see cref="DateTimeOffset"/> the cache entry should be evicted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -117,4 +129,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
[HtmlAttributeName(EnabledAttributeName)]
|
[HtmlAttributeName(EnabledAttributeName)]
|
||||||
public bool Enabled { get; set; } = true;
|
public bool Enabled { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using HtmlGenerationWebSite;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public class HtmlGenerationWithCultureTest : IClassFixture<MvcTestFixture<StartupWithCultureReplace>>
|
||||||
|
{
|
||||||
|
public HtmlGenerationWithCultureTest(MvcTestFixture<StartupWithCultureReplace> fixture)
|
||||||
|
{
|
||||||
|
var factory = fixture.WithWebHostBuilder(builder => builder.UseStartup<StartupWithCultureReplace>());
|
||||||
|
Client = factory.CreateDefaultClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClient Client { get; }
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CacheTagHelper_AllowsVaryingByCulture()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string culture;
|
||||||
|
string correlationId;
|
||||||
|
string cachedCorrelationId;
|
||||||
|
|
||||||
|
// Act - 1
|
||||||
|
var document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&correlationId=10");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 1
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("10", correlationId);
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 2
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=en-GB&correlationId=11");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 2
|
||||||
|
Assert.Equal("en-GB", culture);
|
||||||
|
Assert.Equal("11", correlationId);
|
||||||
|
Assert.Equal("11", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 3
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&correlationId=14");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 3
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("14", correlationId);
|
||||||
|
// Verify we're reading a cached value
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
void ReadValuesFromDocument()
|
||||||
|
{
|
||||||
|
culture = QuerySelector(document, "#culture").TextContent;
|
||||||
|
correlationId = QuerySelector(document, "#correlation-id").TextContent;
|
||||||
|
cachedCorrelationId = QuerySelector(document, "#cached-correlation-id").TextContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CacheTagHelper_AllowsVaryingByUICulture()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string culture;
|
||||||
|
string uiCulture;
|
||||||
|
string correlationId;
|
||||||
|
string cachedCorrelationId;
|
||||||
|
|
||||||
|
// Act - 1
|
||||||
|
var document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&ui-culture=fr-FR&correlationId=10");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 1
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("fr-FR", uiCulture);
|
||||||
|
Assert.Equal("10", correlationId);
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 2
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&ui-culture=fr-CA&correlationId=11");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 2
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("fr-CA", uiCulture);
|
||||||
|
Assert.Equal("11", correlationId);
|
||||||
|
Assert.Equal("11", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 3
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&ui-culture=fr-FR&correlationId=14");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 3
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("fr-FR", uiCulture);
|
||||||
|
Assert.Equal("14", correlationId);
|
||||||
|
// Verify we're reading a cached value
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
void ReadValuesFromDocument()
|
||||||
|
{
|
||||||
|
culture = QuerySelector(document, "#culture").TextContent;
|
||||||
|
uiCulture = QuerySelector(document, "#ui-culture").TextContent;
|
||||||
|
correlationId = QuerySelector(document, "#correlation-id").TextContent;
|
||||||
|
cachedCorrelationId = QuerySelector(document, "#cached-correlation-id").TextContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CacheTagHelper_VaryByCultureComposesWithOtherVaryByOptions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string culture;
|
||||||
|
string correlationId;
|
||||||
|
string cachedCorrelationId;
|
||||||
|
|
||||||
|
// Act - 1
|
||||||
|
var document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&correlationId=10");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 1
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("10", correlationId);
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 2
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&correlationId=11&varyByQueryKey=new-key");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 2
|
||||||
|
// vary-by-query should produce a new cached value.
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("11", correlationId);
|
||||||
|
Assert.Equal("11", cachedCorrelationId);
|
||||||
|
|
||||||
|
// Act - 3
|
||||||
|
document = await Client.GetHtmlDocumentAsync("/CacheTagHelper_VaryByCulture?culture=fr-Fr&correlationId=14");
|
||||||
|
ReadValuesFromDocument();
|
||||||
|
|
||||||
|
// Assert - 3
|
||||||
|
Assert.Equal("fr-FR", culture);
|
||||||
|
Assert.Equal("14", correlationId);
|
||||||
|
Assert.Equal("10", cachedCorrelationId);
|
||||||
|
|
||||||
|
void ReadValuesFromDocument()
|
||||||
|
{
|
||||||
|
culture = QuerySelector(document, "#culture").TextContent;
|
||||||
|
correlationId = QuerySelector(document, "#correlation-id").TextContent;
|
||||||
|
cachedCorrelationId = QuerySelector(document, "#cached-correlation-id").TextContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IElement QuerySelector(IHtmlDocument document, string selector)
|
||||||
|
{
|
||||||
|
var element = document.QuerySelector(selector);
|
||||||
|
if (element == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Document does not contain element that matches the selector {selector}: " + Environment.NewLine + document.DocumentElement.OuterHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.WebEncoders.Testing;
|
using Microsoft.Extensions.WebEncoders.Testing;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -345,6 +346,27 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
Assert.Equal(expected, key);
|
Assert.Equal(expected, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture("fr-FR", "es-ES")]
|
||||||
|
public void GenerateKey_UsesCultureAndUICultureName_IfVaryByCulture_IsSet()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "CacheTagHelper||testid||VaryByCulture||fr-FR||es-ES";
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(Mock.Of<IMemoryCache>()), new HtmlTestEncoder())
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
VaryByCulture = true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var cacheTagKey = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
var key = cacheTagKey.GenerateKey();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, key);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GenerateKey_WithMultipleVaryByOptions_CreatesCombinedKey()
|
public void GenerateKey_WithMultipleVaryByOptions_CreatesCombinedKey()
|
||||||
{
|
{
|
||||||
|
|
@ -371,15 +393,137 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
Assert.Equal(expected, key);
|
Assert.Equal(expected, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture("zh", "zh-Hans")]
|
||||||
|
public void GenerateKey_WithVaryByCulture_ComposesWithOtherOptions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "CacheTagHelper||testid||VaryBy||custom-value||" +
|
||||||
|
"VaryByHeader(content-type||text/html)||VaryByCulture||zh||zh-Hans";
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(Mock.Of<IMemoryCache>()), new HtmlTestEncoder())
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
VaryByCulture = true,
|
||||||
|
VaryByHeader = "content-type",
|
||||||
|
VaryBy = "custom-value"
|
||||||
|
};
|
||||||
|
cacheTagHelper.ViewContext.HttpContext.Request.Headers["Content-Type"] = "text/html";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var cacheTagKey = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
var key = cacheTagKey.GenerateKey();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equality_ReturnsFalse_WhenVaryByCultureIsTrue_AndCultureIsDifferent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(Mock.Of<IMemoryCache>()), new HtmlTestEncoder())
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
VaryByCulture = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CacheTagKey key1;
|
||||||
|
using (new CultureReplacer("fr-FR"))
|
||||||
|
{
|
||||||
|
key1 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheTagKey key2;
|
||||||
|
using (new CultureReplacer("es-ES"))
|
||||||
|
{
|
||||||
|
key2 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
var equals = key1.Equals(key2);
|
||||||
|
var hashCode1 = key1.GetHashCode();
|
||||||
|
var hashCode2 = key2.GetHashCode();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(equals, "CacheTagKeys must not be equal");
|
||||||
|
Assert.NotEqual(hashCode1, hashCode2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equality_ReturnsFalse_WhenVaryByCultureIsTrue_AndUICultureIsDifferent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(Mock.Of<IMemoryCache>()), new HtmlTestEncoder())
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
VaryByCulture = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CacheTagKey key1;
|
||||||
|
using (new CultureReplacer("fr", "fr-FR"))
|
||||||
|
{
|
||||||
|
key1 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheTagKey key2;
|
||||||
|
using (new CultureReplacer("fr", "fr-CA"))
|
||||||
|
{
|
||||||
|
key2 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
var equals = key1.Equals(key2);
|
||||||
|
var hashCode1 = key1.GetHashCode();
|
||||||
|
var hashCode2 = key2.GetHashCode();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(equals, "CacheTagKeys must not be equal");
|
||||||
|
Assert.NotEqual(hashCode1, hashCode2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equality_ReturnsTrue_WhenVaryByCultureIsTrue_AndCultureIsSame()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(Mock.Of<IMemoryCache>()), new HtmlTestEncoder())
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
VaryByCulture = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CacheTagKey key1;
|
||||||
|
CacheTagKey key2;
|
||||||
|
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||||
|
{
|
||||||
|
key1 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (new CultureReplacer("fr-fr", "fr-fr"))
|
||||||
|
{
|
||||||
|
key2 = new CacheTagKey(cacheTagHelper, tagHelperContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var equals = key1.Equals(key2);
|
||||||
|
var hashCode1 = key1.GetHashCode();
|
||||||
|
var hashCode2 = key2.GetHashCode();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(equals, "CacheTagKeys must be equal");
|
||||||
|
Assert.Equal(hashCode1, hashCode2);
|
||||||
|
}
|
||||||
|
|
||||||
private static ViewContext GetViewContext()
|
private static ViewContext GetViewContext()
|
||||||
{
|
{
|
||||||
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||||
return new ViewContext(actionContext,
|
return new ViewContext(actionContext,
|
||||||
Mock.Of<IView>(),
|
Mock.Of<IView>(),
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
||||||
Mock.Of<ITempDataDictionary>(),
|
Mock.Of<ITempDataDictionary>(),
|
||||||
TextWriter.Null,
|
TextWriter.Null,
|
||||||
new HtmlHelperOptions());
|
new HtmlHelperOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TagHelperContext GetTagHelperContext(string id = "testid")
|
private static TagHelperContext GetTagHelperContext(string id = "testid")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
@page
|
||||||
|
@using System.Globalization
|
||||||
|
@functions
|
||||||
|
{
|
||||||
|
[BindProperty(SupportsGet = true)]
|
||||||
|
public int CorrelationId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
<h2 id="culture">@CultureInfo.CurrentCulture</h2>
|
||||||
|
<h2 id="ui-culture">@CultureInfo.CurrentUICulture</h2>
|
||||||
|
<span id="correlation-id">@CorrelationId</span>
|
||||||
|
<cache vary-by-culture="true" vary-by-query="varyByQueryKey">
|
||||||
|
<span id="cached-correlation-id">@CorrelationId</span>
|
||||||
|
</cache>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Localization;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace HtmlGenerationWebSite
|
||||||
|
{
|
||||||
|
public class StartupWithCultureReplace
|
||||||
|
{
|
||||||
|
private readonly Startup Startup = new Startup();
|
||||||
|
|
||||||
|
// Set up application services
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddLocalization();
|
||||||
|
Startup.ConfigureServices(services);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseRequestLocalization(options =>
|
||||||
|
{
|
||||||
|
options.SupportedCultures.Add(new CultureInfo("fr-FR"));
|
||||||
|
options.SupportedCultures.Add(new CultureInfo("en-GB"));
|
||||||
|
|
||||||
|
options.SupportedUICultures.Add(new CultureInfo("fr-FR"));
|
||||||
|
options.SupportedUICultures.Add(new CultureInfo("fr-CA"));
|
||||||
|
options.SupportedUICultures.Add(new CultureInfo("en-GB"));
|
||||||
|
});
|
||||||
|
|
||||||
|
Startup.Configure(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||||
|
new WebHostBuilder()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseStartup<StartupWithCultureReplace>()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseIISIntegration();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue