diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs
index 746d7456b2..548c8c0ea5 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs
@@ -186,7 +186,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
public static string HiddenInputTemplate(IHtmlHelper html)
{
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (return string.Empty)
+ if (html.ViewData.ModelMetadata.HideSurroundingHtml)
+ {
+ return string.Empty;
+ }
+
return StringTemplate(html);
}
@@ -219,7 +223,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
var divTag = new TagBuilder("div");
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (skip this block)
+ if (!propertyMetadata.HideSurroundingHtml)
{
var label = propertyMetadata.GetDisplayName();
if (!string.IsNullOrEmpty(label))
@@ -248,7 +252,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
builder.Append(templateBuilder.Build());
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (skip this block)
+ if (!propertyMetadata.HideSurroundingHtml)
{
builder.AppendLine(divTag.ToString(TagRenderMode.EndTag));
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs
index ef320cdac3..49d2bee693 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs
@@ -135,12 +135,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
public static string HiddenInputTemplate(IHtmlHelper html)
{
var viewData = html.ViewData;
-
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (set result to string.Empty)
- var result = DefaultDisplayTemplates.StringTemplate(html);
-
var model = viewData.Model;
+ string result;
+ if (viewData.ModelMetadata.HideSurroundingHtml)
+ {
+ result = string.Empty;
+ }
+ else
+ {
+ result = DefaultDisplayTemplates.StringTemplate(html);
+ }
+
// Special-case opaque values and arbitrary binary data.
var modelAsByteArray = model as byte[];
if (modelAsByteArray != null)
@@ -225,7 +231,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
var divTag = new TagBuilder("div");
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (skip this block)
+ if (!propertyMetadata.HideSurroundingHtml)
{
var label = html.Label(
propertyMetadata.PropertyName,
@@ -258,8 +264,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
builder.Append(templateBuilder.Build());
- // TODO: add ModelMetadata.HideSurroundingHtml and use here (skip this block)
// TODO: Add IHtmlHelper.ValidationMessage() and call just prior to closing the
tag
+ if (!propertyMetadata.HideSurroundingHtml)
{
builder.Append(" ");
builder.AppendLine(divTag.ToString(TagRenderMode.EndTag));
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/HiddenInputAttribute.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/HiddenInputAttribute.cs
new file mode 100644
index 0000000000..7647cb7fca
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/HiddenInputAttribute.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.Mvc
+{
+ ///
+ /// Indicates associated property or all properties of associated type should be edited using an <input>
+ /// element of type "hidden".
+ ///
+ ///
+ /// When overriding a inherited from a base class, should apply both
+ /// [HiddenInput(DisplayValue = true)] (if the inherited attribute had DisplayValue = false) and a
+ /// with some value other than "HiddenInput".
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ public sealed class HiddenInputAttribute : Attribute
+ {
+ ///
+ /// Instantiates a new instance of the class.
+ ///
+ public HiddenInputAttribute()
+ {
+ DisplayValue = true;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether to display the value as well as provide a hidden <input>
+ /// element. The default value is true.
+ ///
+ ///
+ /// If false, also causes the default display and editor templates to return HTML
+ /// lacking the usual per-property <div> wrapper around the associated property and the default display
+ /// "HiddenInput" template to return string.Empty for the associated property. Thus the default
+ /// display template effectively skips the property and the default
+ /// editor template returns only the hidden <input> element for the property.
+ ///
+ public bool DisplayValue { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs
index edcbd1556e..e262373881 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs
@@ -16,6 +16,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
DisplayFormat = attributes.OfType().FirstOrDefault();
DisplayColumn = attributes.OfType().FirstOrDefault();
Editable = attributes.OfType().FirstOrDefault();
+ HiddenInput = attributes.OfType().FirstOrDefault();
Required = attributes.OfType().FirstOrDefault();
ScaffoldColumn = attributes.OfType().FirstOrDefault();
}
@@ -28,6 +29,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public EditableAttribute Editable { get; protected set; }
+ ///
+ /// Gets (or sets in subclasses) found in collection passed to the
+ /// constructor, if any.
+ ///
+ public HiddenInputAttribute HiddenInput { get; protected set; }
+
public RequiredAttribute Required { get; protected set; }
public ScaffoldColumnAttribute ScaffoldColumn { get; protected set; }
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
index 8b6421b4e4..f082bbc038 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs
@@ -67,6 +67,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return base.ComputeDisplayName();
}
+ ///
+ /// Calculate based on presence of an
+ /// and its value.
+ ///
+ /// Calculated value. true if an
+ /// exists and its value is
+ /// false; false otherwise.
+ protected override bool ComputeHideSurroundingHtml()
+ {
+ if (PrototypeCache.HiddenInput != null)
+ {
+ return !PrototypeCache.HiddenInput.DisplayValue;
+ }
+
+ return base.ComputeHideSurroundingHtml();
+ }
+
protected override bool ComputeIsReadOnly()
{
if (PrototypeCache.Editable != null)
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
index 15b1acf53d..e94f166786 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs
@@ -19,6 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private string _nullDisplayText;
private string _description;
private string _displayName;
+ private bool _hideSurroundingHtml;
private bool _isReadOnly;
private bool _isComplexType;
private bool _isRequired;
@@ -29,6 +30,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private bool _nullDisplayTextComputed;
private bool _descriptionComputed;
private bool _displayNameComputed;
+ private bool _hideSurroundingHtmlComputed;
private bool _isReadOnlyComputed;
private bool _isComplexTypeComputed;
private bool _isRequiredComputed;
@@ -134,6 +136,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
+ ///
+ public sealed override bool HideSurroundingHtml
+ {
+ get
+ {
+ if (!_hideSurroundingHtmlComputed)
+ {
+ _hideSurroundingHtml = ComputeHideSurroundingHtml();
+ _hideSurroundingHtmlComputed = true;
+ }
+
+ return _hideSurroundingHtml;
+ }
+
+ set
+ {
+ _hideSurroundingHtml = value;
+ _hideSurroundingHtmlComputed = true;
+ }
+ }
+
public sealed override bool IsReadOnly
{
get
@@ -241,6 +264,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return base.DisplayName;
}
+ ///
+ /// Calculate the value.
+ ///
+ /// Calculated value.
+ protected virtual bool ComputeHideSurroundingHtml()
+ {
+ return base.HideSurroundingHtml;
+ }
+
protected virtual bool ComputeIsReadOnly()
{
return base.IsReadOnly;
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
index 921ea3c5f9..5e07928cbe 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs
@@ -69,6 +69,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public virtual string EditFormatString { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the "HiddenInput" display template should return
+ /// string.Empty (not the expression value) and whether the "HiddenInput" editor template should not
+ /// also return the expression value (together with the hidden <input> element).
+ ///
+ ///
+ /// If true, also causes the default display and editor templates to return HTML
+ /// lacking the usual per-property <div> wrapper around the associated property. Thus the default
+ /// display template effectively skips the property and the default
+ /// editor template returns only the hidden <input> element for the property.
+ ///
+ public virtual bool HideSurroundingHtml { get; set; }
+
public virtual bool IsComplexType
{
get { return !ValueProviderResult.CanConvertFromString(ModelType); }