lundi 19 mai 2014

ASP.net mvc 3 - copie ModelMetaData à la ModelMetaData de propriété Child - Stack Overflow


I've created a wrapper model which contains an inner property, Value, which is the property to be shown in the view. In the outermost model, I create a property which is the type of the wrapper and I apply some attributes and validations to that property. When the wrapper view is rendering, I want to copy all validations and attributes from the wrapper to the inner Value property so that when I finally call EditorFor(m => m.Value), the view that renders the child property also renders the validators, etc. related to the container property.


HomeController.cs


namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new IndexModel());
}
}
}

IndexModel.cs


namespace MvcApplication1.Models.Home
{
public class IndexModel
{
[Display(Name = "Test Edit Field")]
[MaxLength(10)]
[AdditionalMetadata("ViewName", "String")]
[TemplateVisibility(false, true)]
public BatchEditField<string> TestEditField { get; set; }

public IndexModel()
{
this.TestEditField = new BatchEditField<string>("TEST");
}
}
}

EditField.cs (The "wrapper" model.)


namespace MvcApplication1.Models.Home
{
public class EditField
{
public string RawValue { get; set; }
public object Value { get; set; }
public string Description { get; set; }

public EditField() { }

public EditField(string rawValue, object value, string description = null)
{
this.RawValue = rawValue;
this.Value = value;
this.Description = (description ?? Convert.ToString(value));
}

public override string ToString()
{
return this.Description;
}
}

public class EditField<T> : BatchEditField
{
public new T Value { get { return (T)base.Value; } set { base.Value = value; } }

public EditField() { }

public EditField(string defaultValue) : base(null, defaultValue, null) { }

public EditField(string rawValue, T value, string description = null)
: base(rawValue, value, description)
{
}
}
}

EditField.cshtml (The "wrapper" view.)


@using S3.Common.Extensions
@model MvcApplication1.Models.Home.EditField

@{
//Attempting to copy AdditionalValues from the wrapper property to the child Value property.
ModelMetadata property = this.ViewData.ModelMetadata.Properties.Single(o => "Value".Equals(o.PropertyName));

foreach (var item in this.ViewData.ModelMetadata.AdditionalValues)
{
property.AdditionalValues[item.Key] = item.Value;
}
}

@Html.EditorFor(m => m.Value, Convert.ToString(this.ViewData.ModelMetadata.AdditionalValues.ValueOrDefault("ViewName")))

@if (this.Model != null && !this.Model.RawValue.IsNullOrEmpty() && !this.Model.RawValue.Trim().IsNullOrEmpty())
{
<p class="RawValue@(this.ViewData.ModelMetadata.AdditionalValues.ContainsKey("Style") ? " " + this.ViewData.ModelMetadata.AdditionalValues["Style"] : "")">@(this.Model.RawValue.IsNullOrEmpty() ? "(Not Specified)" : this.Model.RawValue)</p>
}

String.cshtml (The child view.)


@* Inspecting this.ViewData.ModelMetaData.AdditionalValues shows that it is empty; the parent AdditionalValues that were copied in the wrapper view did not make it through. *@
@Html.TextBox(string.Empty, this.ViewData.TemplateInfo.FormattedModelValue)
@Html.ValidationMessage(string.Empty)

Summary


Finally, when the page is rendered, no validation elements, etc. are included because they don't exist in the ModelMetaData when String.cshtml is rendered.



I've created a wrapper model which contains an inner property, Value, which is the property to be shown in the view. In the outermost model, I create a property which is the type of the wrapper and I apply some attributes and validations to that property. When the wrapper view is rendering, I want to copy all validations and attributes from the wrapper to the inner Value property so that when I finally call EditorFor(m => m.Value), the view that renders the child property also renders the validators, etc. related to the container property.


HomeController.cs


namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new IndexModel());
}
}
}

IndexModel.cs


namespace MvcApplication1.Models.Home
{
public class IndexModel
{
[Display(Name = "Test Edit Field")]
[MaxLength(10)]
[AdditionalMetadata("ViewName", "String")]
[TemplateVisibility(false, true)]
public BatchEditField<string> TestEditField { get; set; }

public IndexModel()
{
this.TestEditField = new BatchEditField<string>("TEST");
}
}
}

EditField.cs (The "wrapper" model.)


namespace MvcApplication1.Models.Home
{
public class EditField
{
public string RawValue { get; set; }
public object Value { get; set; }
public string Description { get; set; }

public EditField() { }

public EditField(string rawValue, object value, string description = null)
{
this.RawValue = rawValue;
this.Value = value;
this.Description = (description ?? Convert.ToString(value));
}

public override string ToString()
{
return this.Description;
}
}

public class EditField<T> : BatchEditField
{
public new T Value { get { return (T)base.Value; } set { base.Value = value; } }

public EditField() { }

public EditField(string defaultValue) : base(null, defaultValue, null) { }

public EditField(string rawValue, T value, string description = null)
: base(rawValue, value, description)
{
}
}
}

EditField.cshtml (The "wrapper" view.)


@using S3.Common.Extensions
@model MvcApplication1.Models.Home.EditField

@{
//Attempting to copy AdditionalValues from the wrapper property to the child Value property.
ModelMetadata property = this.ViewData.ModelMetadata.Properties.Single(o => "Value".Equals(o.PropertyName));

foreach (var item in this.ViewData.ModelMetadata.AdditionalValues)
{
property.AdditionalValues[item.Key] = item.Value;
}
}

@Html.EditorFor(m => m.Value, Convert.ToString(this.ViewData.ModelMetadata.AdditionalValues.ValueOrDefault("ViewName")))

@if (this.Model != null && !this.Model.RawValue.IsNullOrEmpty() && !this.Model.RawValue.Trim().IsNullOrEmpty())
{
<p class="RawValue@(this.ViewData.ModelMetadata.AdditionalValues.ContainsKey("Style") ? " " + this.ViewData.ModelMetadata.AdditionalValues["Style"] : "")">@(this.Model.RawValue.IsNullOrEmpty() ? "(Not Specified)" : this.Model.RawValue)</p>
}

String.cshtml (The child view.)


@* Inspecting this.ViewData.ModelMetaData.AdditionalValues shows that it is empty; the parent AdditionalValues that were copied in the wrapper view did not make it through. *@
@Html.TextBox(string.Empty, this.ViewData.TemplateInfo.FormattedModelValue)
@Html.ValidationMessage(string.Empty)

Summary


Finally, when the page is rendered, no validation elements, etc. are included because they don't exist in the ModelMetaData when String.cshtml is rendered.


0 commentaires:

Enregistrer un commentaire