diff --git a/samples/MvcSample.Web/HomeController.cs b/samples/MvcSample.Web/HomeController.cs
index ba95f76de5..b6cc868f8c 100644
--- a/samples/MvcSample.Web/HomeController.cs
+++ b/samples/MvcSample.Web/HomeController.cs
@@ -96,7 +96,8 @@ namespace MvcSample.Web
Address = "Dependents address",
Alive = false,
},
- About = "I am a Software Engineer"
+ Profession = "Software Engineer",
+ About = "I like playing Football"
};
return user;
diff --git a/samples/MvcSample.Web/Models/User.cs b/samples/MvcSample.Web/Models/User.cs
index 97189a7af1..1cc9b93066 100644
--- a/samples/MvcSample.Web/Models/User.cs
+++ b/samples/MvcSample.Web/Models/User.cs
@@ -13,6 +13,8 @@ namespace MvcSample.Web.Models
public User Dependent { get; set; }
public bool Alive { get; set; }
public string Password { get; set; }
+ [DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "You can explain about your profession")]
+ public string Profession { get; set; }
public string About { get; set; }
public string Log { get; set; }
}
diff --git a/samples/MvcSample.Web/Views/Home/Create.cshtml b/samples/MvcSample.Web/Views/Home/Create.cshtml
index f7fdcc49e2..f07cba929a 100644
--- a/samples/MvcSample.Web/Views/Home/Create.cshtml
+++ b/samples/MvcSample.Web/Views/Home/Create.cshtml
@@ -18,7 +18,7 @@
}
else
{
-
Hello @Model.Name! Happy @(Model.Age)th birthday.
+ Hello @Html.DisplayTextFor(model => model.Name)! Happy @(Model.Age)th birthday.
}
@{
@@ -69,10 +69,18 @@
|
-
+
|
- @Html.TextArea("About", "You can explain about your profession, hobbies etc.", 5, 40, htmlAttributes: new { style = "font-weight:bold" })
+
+ |
+
+
+ |
+
+ |
+
+ @Html.TextArea("About", "You can explain about your hobbies, work etc.", 5, 40, htmlAttributes: new { style = "font-weight:bold" })
|
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
index e39a0dfc28..13ae3bf9ba 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
@@ -258,6 +258,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
return GenerateDisplayName(metadata, expression);
}
+ ///
+ public HtmlString DisplayText(string name)
+ {
+ var metadata = ExpressionMetadataProvider.FromStringExpression(name, ViewData, MetadataProvider);
+
+ return GenerateDisplayText(metadata);
+ }
///
public HtmlString DropDownList(string name, IEnumerable selectList, string optionLabel,
@@ -291,6 +298,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes: htmlAttributes);
}
+ ///
+ public HtmlString Id(string name)
+ {
+ return GenerateId(name);
+ }
+
///
public HtmlString Label(string expression, string labelText, object htmlAttributes)
{
@@ -652,6 +665,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
return new HtmlString(Encode(resolvedDisplayName));
}
+
+ protected virtual HtmlString GenerateDisplayText(ModelMetadata metadata)
+ {
+ return new HtmlString(metadata.SimpleDisplayText);
+ }
protected HtmlString GenerateDropDown(ModelMetadata metadata, string expression,
IEnumerable selectList, string optionLabel, object htmlAttributes)
@@ -760,6 +778,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes: htmlAttributeDictionary);
}
+ protected virtual HtmlString GenerateId(string expression)
+ {
+ return new HtmlString(Encode(ViewData.TemplateInfo.GetFullHtmlFieldName(expression)));
+ }
+
protected virtual HtmlString GenerateLabel([NotNull] ModelMetadata metadata,
string htmlFieldName,
string labelText,
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelperOfT.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelperOfT.cs
index ad32c4e014..8141b33a2e 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelperOfT.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelperOfT.cs
@@ -108,6 +108,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
return GenerateDisplayName(metadata, expressionText);
}
+
+ ///
+ public HtmlString DisplayTextFor([NotNull] Expression> expression)
+ {
+ return GenerateDisplayText(GetModelMetadata(expression));
+ }
///
public HtmlString EditorFor(
@@ -134,6 +140,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes: htmlAttributes);
}
+ ///
+ public HtmlString IdFor([NotNull] Expression> expression)
+ {
+ return GenerateId(GetExpressionName(expression));
+ }
+
///
public HtmlString LabelFor([NotNull] Expression> expression, string labelText, object htmlAttributes)
{
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/HtmlHelperNameExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/HtmlHelperNameExtensions.cs
index 1c58924329..91e30c9f72 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/HtmlHelperNameExtensions.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/HtmlHelperNameExtensions.cs
@@ -15,5 +15,15 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
return htmlHelper.Name(string.Empty);
}
+
+ ///
+ /// Gets the full HTML field id for the current model.
+ ///
+ /// The instance that this method extends.
+ /// An that represents HTML markup.
+ public static HtmlString IdForModel([NotNull] this IHtmlHelper htmlHelper)
+ {
+ return htmlHelper.Id(string.Empty);
+ }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
index fe18fff9bc..80c37299ff 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
@@ -161,6 +161,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
///
HtmlString DisplayName(string expression);
+ /// Returns the HtmlString corresponding to the property in the model specified by the name.
+ ///
+ ///
+ /// The string which identifies the object for which the HtmlString should be returned.
+ ///
+ /// New containing the display text. If the value is null,
+ /// then it returns the ModelMetadata.NullDisplayText.
+ ///
+ HtmlString DisplayText(string name);
+
///
/// Returns a single-selection HTML {select} element using the specified name of the form field,
/// list items, option label, and HTML attributes.
@@ -248,6 +258,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// New containing the rendered HTML.
HtmlString Hidden(string name, object value, object htmlAttributes);
+ ///
+ /// Gets the Id of the given string.
+ ///
+ /// The string which identifies the object for which the Id should be returned.
+ /// New containing the Id.
+ HtmlString Id(string name);
+
///
/// Returns an HTML label element and the property name of the property that is represented by the specified
/// expression.
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelperOfT.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelperOfT.cs
index 1aea63244d..5eb8d91fe0 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelperOfT.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelperOfT.cs
@@ -70,6 +70,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
HtmlString DisplayNameForInnerType(
[NotNull] Expression> expression);
+ ///
+ /// Returns the HtmlString corresponding to the expression specified.
+ ///
+ ///
+ /// The expression identifies the object for which the HtmlString should be returned.
+ ///
+ ///
+ /// New containing the display text. If the value is null,
+ /// then it returns the ModelMetadata.NullDisplayText.
+ ///
+ HtmlString DisplayTextFor([NotNull] Expression> expression);
+
///
/// Returns a single-selection HTML {select} element for the object that is represented
/// by the specified expression using the specified list items, option label, and HTML attributes.
@@ -125,6 +137,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
HtmlString HiddenFor([NotNull] Expression> expression,
object htmlAttributes);
+ ///
+ /// Gets the Id of the given expression.
+ ///
+ /// The expression identifies the object for which the Id should be returned.
+ /// New containing the Id.
+ HtmlString IdFor([NotNull] Expression> expression);
+
///
/// Returns an HTML label element and the property name of the property that is represented by the specified
/// expression.
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
index 5c650e4d87..72c3455de2 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
@@ -31,6 +31,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
: base.ComputeConvertEmptyStringToNull();
}
+ protected override string ComputeNullDisplayText()
+ {
+ return PrototypeCache.DisplayFormat != null
+ ? PrototypeCache.DisplayFormat.NullDisplayText
+ : base.ComputeNullDisplayText();
+ }
+
protected override string ComputeDescription()
{
return PrototypeCache.Display != null
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
index 58ae174f7c..f612caee5b 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
@@ -17,11 +17,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public abstract class CachedModelMetadata : ModelMetadata
{
private bool _convertEmptyStringToNull;
+ private string _nullDisplayText;
private string _description;
private bool _isReadOnly;
private bool _isComplexType;
private bool _convertEmptyStringToNullComputed;
+ private bool _nullDisplayTextComputed;
private bool _descriptionComputed;
private bool _isReadOnlyComputed;
private bool _isComplexTypeComputed;
@@ -62,6 +64,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
+ public sealed override string NullDisplayText
+ {
+ get
+ {
+ if (!_nullDisplayTextComputed)
+ {
+ _nullDisplayText = ComputeNullDisplayText();
+ _nullDisplayTextComputed = true;
+ }
+ return _nullDisplayText;
+ }
+ set
+ {
+ _nullDisplayText = value;
+ _nullDisplayTextComputed = true;
+ }
+ }
+
public sealed override string Description
{
get
@@ -118,6 +138,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return base.ConvertEmptyStringToNull;
}
+ protected virtual string ComputeNullDisplayText()
+ {
+ return base.NullDisplayText;
+ }
+
protected virtual string ComputeDescription()
{
return base.Description;
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
index 87cad826d5..3a74a7aece 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@@ -20,6 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private int _order = DefaultOrder;
private IEnumerable _properties;
private Type _realModelType;
+ private string _simpleDisplayText;
public ModelMetadata([NotNull] IModelMetadataProvider provider,
Type containerType,
@@ -141,6 +144,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
+ public virtual string SimpleDisplayText
+ {
+ get
+ {
+ if (_simpleDisplayText == null)
+ {
+ _simpleDisplayText = ComputeSimpleDisplayText();
+ }
+
+ return _simpleDisplayText;
+ }
+
+ set { _simpleDisplayText = value; }
+ }
+
public virtual string TemplateHint { get; set; }
internal EfficientTypePropertyKey CacheKey
@@ -177,6 +195,38 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// return validatorProviders.SelectMany(provider => provider.GetValidators(this, validatorProviders));
//}
+ protected virtual string ComputeSimpleDisplayText()
+ {
+ if (Model == null)
+ {
+ return NullDisplayText;
+ }
+
+ var stringResult = Convert.ToString(Model, CultureInfo.CurrentCulture);
+ if (stringResult == null)
+ {
+ return string.Empty;
+ }
+
+ if (!stringResult.Equals(Model.GetType().FullName, StringComparison.Ordinal))
+ {
+ return stringResult;
+ }
+
+ var firstProperty = Properties.FirstOrDefault();
+ if (firstProperty == null)
+ {
+ return string.Empty;
+ }
+
+ if (firstProperty.Model == null)
+ {
+ return firstProperty.NullDisplayText;
+ }
+
+ return Convert.ToString(firstProperty.Model, CultureInfo.CurrentCulture);
+ }
+
private static EfficientTypePropertyKey CreateCacheKey(Type containerType, Type modelType, string propertyName)
{
// If metadata is for a property then containerType != null && propertyName != null
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs
index b67e8f8da9..2fe92cd57e 100644
--- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs
@@ -25,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Assert
Assert.Equal(typeof(Exception), metadata.ContainerType);
Assert.True(metadata.ConvertEmptyStringToNull);
+ Assert.Null(metadata.NullDisplayText);
Assert.Null(metadata.Description);
Assert.Equal("model", metadata.Model);
Assert.Equal(typeof(string), metadata.ModelType);