diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs
index 15588722a6..4baad584d7 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// An implementation of and for
/// the System.ComponentModel.DataAnnotations attribute classes.
///
- public class DataAnnotationsMetadataProvider :
+ public class DataAnnotationsMetadataProvider :
IBindingMetadataProvider,
IDisplayMetadataProvider,
IValidationMetadataProvider
@@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
// Description
if (displayAttribute != null)
{
- displayMetadata.Description = displayAttribute.GetDescription();
+ displayMetadata.Description = () => displayAttribute.GetDescription();
}
// DisplayFormat
@@ -84,7 +84,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
// DisplayName
if (displayAttribute != null)
{
- displayMetadata.DisplayName = displayAttribute.GetName();
+ displayMetadata.DisplayName = () => displayAttribute.GetName();
}
if (displayFormatAttribute != null && displayFormatAttribute.ApplyFormatInEditMode)
@@ -216,8 +216,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
foreach (var attribute in context.Attributes.OfType())
{
- // If another provider has already added this attribute, do not repeat it.
- // This will prevent attributes like RemoteAttribute (which implement ValidationAttribute and
+ // If another provider has already added this attribute, do not repeat it.
+ // This will prevent attributes like RemoteAttribute (which implement ValidationAttribute and
// IClientModelValidator) to be added to the ValidationMetadata twice.
// This is to ensure we do not end up with duplication validation rules on the client side.
if (!context.ValidationMetadata.ValidatorMetadata.Contains(attribute))
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs
index 85cd371b8a..fe0f44204a 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs
@@ -179,7 +179,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{
get
{
- return DisplayMetadata.Description;
+ if (DisplayMetadata.Description == null)
+ {
+ return null;
+ }
+
+ return DisplayMetadata.Description();
}
}
@@ -197,7 +202,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{
get
{
- return DisplayMetadata.DisplayName;
+ if (DisplayMetadata.DisplayName == null)
+ {
+ return null;
+ }
+
+ return DisplayMetadata.DisplayName();
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DisplayMetadata.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DisplayMetadata.cs
index b4dc7253e1..d6ecfd9251 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DisplayMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DisplayMetadata.cs
@@ -1,6 +1,7 @@
// 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.Collections.Generic;
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
@@ -28,10 +29,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
public string DataTypeName { get; set; }
///
- /// Gets or sets a model description.
- /// See
+ /// Gets or sets a delegate which is used to get a value for the
+ /// model description. See .
///
- public string Description { get; set; }
+ public Func Description { get; set; }
///
/// Gets or sets a display format string for the model.
@@ -40,10 +41,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
public string DisplayFormatString { get; set; }
///
- /// Gets or sets a display name for the model.
- /// See
+ /// Gets or sets a delegate delegate which is used to get a value for the
+ /// display name of the model. See .
///
- public string DisplayName { get; set; }
+ public Func DisplayName { get; set; }
///
/// Gets or sets an edit format string for the model.
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DataAnnotationsMetadataProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DataAnnotationsMetadataProviderTest.cs
index 0d98e00894..e6152a0718 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DataAnnotationsMetadataProviderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DataAnnotationsMetadataProviderTest.cs
@@ -20,8 +20,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{
{ new DataTypeAttribute(DataType.Duration), d => d.DataTypeName, DataType.Duration.ToString() },
- { new DisplayAttribute() { Description = "d" }, d => d.Description, "d" },
- { new DisplayAttribute() { Name = "DN" }, d => d.DisplayName, "DN" },
+ { new DisplayAttribute() { Description = "d" }, d => d.Description(), "d" },
+ { new DisplayAttribute() { Name = "DN" }, d => d.DisplayName(), "DN" },
{ new DisplayAttribute() { Order = 3 }, d => d.Order, 3 },
{ new DisplayColumnAttribute("Property"), d => d.SimpleDisplayProperty, "Property" },
@@ -175,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
provider.GetDisplayMetadata(context);
// Assert
- Assert.Equal("name from resources", context.DisplayMetadata.DisplayName);
+ Assert.Equal("name from resources", context.DisplayMetadata.DisplayName());
}
// This is IMPORTANT. Product code needs to use GetDescription() instead of .Description. It's easy to regress.
@@ -204,7 +204,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
provider.GetDisplayMetadata(context);
// Assert
- Assert.Equal("description from resources", context.DisplayMetadata.Description);
+ Assert.Equal("description from resources", context.DisplayMetadata.Description());
}
[Theory]
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/ModelMetadataProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/ModelMetadataProviderTest.cs
index 42b397df92..5ff3946e60 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/ModelMetadataProviderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/ModelMetadataProviderTest.cs
@@ -7,6 +7,8 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
+using System.Threading;
+using Microsoft.AspNet.Testing;
using Microsoft.Framework.Internal;
using Xunit;
@@ -420,6 +422,58 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
Assert.Equal("description", result);
}
+ [Fact]
+ public void DisplayName_FromResources_GetsRecomputed()
+ {
+ // Arrange
+ var display = new DisplayAttribute()
+ {
+ Name = nameof(TestResources.DisplayAttribute_CultureSensitiveName),
+ ResourceType = typeof(TestResources),
+ };
+
+ var provider = CreateProvider(new[] { display });
+ var metadata = provider.GetMetadataForType(typeof(string));
+
+ // Act & Assert
+ var cultures = new[] { "fr-FR", "en-US", "en-GB" };
+ foreach (var culture in cultures)
+ {
+ using (new CultureReplacer(uiCulture: culture))
+ {
+ // Later iterations ensure value is recomputed.
+ var result = metadata.DisplayName;
+ Assert.Equal("name from resources" + culture, result);
+ }
+ }
+ }
+
+ [Fact]
+ public void Description_FromResources_GetsRecomputed()
+ {
+ // Arrange
+ var display = new DisplayAttribute()
+ {
+ Description = nameof(TestResources.DisplayAttribute_CultureSensitiveDescription),
+ ResourceType = typeof(TestResources),
+ };
+
+ var provider = CreateProvider(new[] { display });
+ var metadata = provider.GetMetadataForType(typeof(string));
+
+ // Act & Assert
+ var cultures = new[] { "fr-FR", "en-US", "en-GB" };
+ foreach (var culture in cultures)
+ {
+ using (new CultureReplacer(uiCulture: culture))
+ {
+ // Later iterations ensure value is recomputed.
+ var result = metadata.Description;
+ Assert.Equal("description from resources" + culture, result);
+ }
+ }
+ }
+
[Fact]
public void DataTypeName_Null_IfHtmlEncodeTrue()
{
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/TestResources.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/TestResources.cs
index 3ce4cc280b..5ded5a2057 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/TestResources.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/TestResources.cs
@@ -1,6 +1,7 @@
// 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.Threading;
using Microsoft.AspNet.Mvc.Core.Test;
namespace Microsoft.AspNet.Mvc.ModelBinding
@@ -12,5 +13,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public static string DisplayAttribute_Description { get; } = Resources.DisplayAttribute_Description;
public static string DisplayAttribute_Name { get; } = Resources.DisplayAttribute_Name;
+
+ public static string DisplayAttribute_CultureSensitiveName =>
+ Resources.DisplayAttribute_Name + Thread.CurrentThread.CurrentUICulture;
+
+ public static string DisplayAttribute_CultureSensitiveDescription =>
+ Resources.DisplayAttribute_Description + Thread.CurrentThread.CurrentUICulture;
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperDisplayNameExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperDisplayNameExtensionsTest.cs
index ce39b0429e..b0b1c99b2a 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperDisplayNameExtensionsTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperDisplayNameExtensionsTest.cs
@@ -97,7 +97,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForType()
- .DisplayDetails(dd => dd.DisplayName = displayName);
+ .DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
var enumerableHelper = DefaultTemplatesUtilities.GetHtmlHelperForEnumerable(provider: provider);
@@ -124,7 +124,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForProperty("Property1")
- .DisplayDetails(dd => dd.DisplayName = displayName);
+ .DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
var enumerableHelper = DefaultTemplatesUtilities.GetHtmlHelperForEnumerable(provider: provider);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLabelExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLabelExtensionsTest.cs
index 428f1b29ee..456445a423 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLabelExtensionsTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLabelExtensionsTest.cs
@@ -110,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForType()
- .DisplayDetails(dd => dd.DisplayName = string.Empty);
+ .DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
@@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForType()
- .DisplayDetails(dd => dd.DisplayName = displayName);
+ .DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
@@ -158,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForProperty("Property1")
- .DisplayDetails(dd => dd.DisplayName = string.Empty);
+ .DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var modelExplorer = provider
.GetModelExplorerForType(typeof(DefaultTemplatesUtilities.ObjectTemplateModel), model: null)
@@ -188,7 +188,7 @@ namespace Microsoft.AspNet.Mvc.Core
var provider = new TestModelMetadataProvider();
provider
.ForProperty("Property1")
- .DisplayDetails(dd => dd.DisplayName = displayName);
+ .DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);