I have a custom HtmlHelper where I am trying to get values of a generic type property.
My ViewModel has properties of type ChangeRequestFormField. The relevant parts of my ViewModel, class/interface, and the html helper are shown below.
In my helper, I need to access the IsRequired and ValueHasChanged properties from my ViewModel properties. This is working fine for ChangeRequestFormField. But when I get to ChangeRequestFormField, I get a the following error:
Unable to cast object of type
'StaffChanges.Models.ChangeRequestFormField1[System.Nullable
1[System.Boolean]]'
to type
'StaffChanges.Models.IChangeRequestFormField`1[System.Object]'.
The error occurs at this line in the helper:
var isRequired = ((IChangeRequestFormField<object>)metadata.Model).IsRequired;
Maybe I'm approaching this wrong, but I need a way to access those properties in the helper, not knowing the type in the ChangeFormField until runtime.
ViewModel:
public class JobChangeModel
{
public ChangeRequestFormField<string> Reason1 { get; set; }
public ChangeRequestFormField<bool?> IsTransferEventNeeded { get; set; }
}
public class ChangeRequestFormField<T> : IChangeRequestFormField<T>
{
public ChangeRequestFormField(string formFieldType, T fieldValue, T originalValue)
{
this.FieldValue = fieldValue;
this.OriginalValue = originalValue;
switch (formFieldType)
{
case FormFieldTypes.DoNotRender:
this.RenderField = false;
this.IsRequired = false;
break;
case FormFieldTypes.Required:
this.RenderField = true;
this.IsRequired = true;
break;
case FormFieldTypes.Optional:
this.RenderField = true;
this.IsRequired = false;
break;
default:
this.RenderField = false;
this.IsRequired = false;
break;
}
}
public T FieldValue { get; set; }
public bool IsRequired { get; private set; }
public T OriginalValue { get; set; }
public string OriginalValueString
{
get
{
return this.OriginalValue == null ? string.Empty : this.OriginalValue.ToString();
}
}
public bool ValueHasChanged
{
get
{
return !EqualityComparer<T>.Default.Equals(this.FieldValue, this.OriginalValue);
}
}
}
public interface IChangeRequestFormField<out T>
{
bool IsRequired { get; }
string OriginalValueString { get; }
bool ValueHasChanged { get; }
}
public static MvcHtmlString LabelForChangeRequestFormField<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string labelText, IDictionary<string, object> htmlAttributes)
{
if (expression.Body.Type.GetGenericTypeDefinition() != typeof(ChangeRequestFormField<>))
{
return html.LabelFor(expression, htmlAttributes);
}
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var isRequired = ((IChangeRequestFormField<object>)metadata.Model).IsRequired;
var valueChanged = ((IChangeRequestFormField<object>)metadata.Model).ValueHasChanged;
// other code left out
}