Could someone please clarify something for me. In my ASP.NET MVC 2 app, I've got a BaseViewModel
class which includes the following method:
public virtual IDictionary<string, object> GetHtmlAttributes<TModel, TProperty>
(Expression<Func<TModel, TProperty>> propertyExpression)
{
return new Dictionary<string, object>();
}
The idea being that each child viewmodel can override this method and provide a suitable set of html attributes, based on some logic, to be rendered in the view:
<%: Html.TextBoxFor(model => model.MyProperty, Model.GetHtmlAttributes
(model => model.MyProperty)) %>
However when used as in the line above, I get a compilation error when I hit the view:
The type arguments for method '
...BaseViewModel.GetHtmlAttributes<TModel,TProperty> Expression<System.Func<TModel,TProperty>)
' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I have to do the following:
<%: Html.TextBoxFor(model => model.MyProperty, Model.GetHtmlAttributes
<ChildModel, string>(model => model.MyProperty)) %>
I'm just looking for some clarity as to how it tries to infer the type, it has no problem doing so in the HtmlHelper/TextBoxFor
extension method?
Is it because HtmlHelper
in the view will automatically be for the same type as is specified in the ViewUserControl
at the top of the page, whereas my code can be for any type inheriting from BaseViewModel
? Is is possible to write this in such a way that it can infer my model/property types?
I know this question already has an accepted answer, but for me, a .NET beginner, there was a simple solution to what I was doing wrong and I thought I'd share.
I had been doing this:
@Html.HiddenFor(Model.Foo.Bar.ID)
What worked for me was changing to this:
@Html.HiddenFor(m => m.Foo.Bar.ID)
(where "m" is an arbitrary string to represent the model object)
In your example, the compiler has no way of knowing what type should TModel
be. You could do something close to what you are probably trying to do with an extension method.
static class ModelExtensions
{
public static IDictionary<string, object> GetHtmlAttributes<TModel, TProperty>
(this TModel model, Expression<Func<TModel, TProperty>> propertyExpression)
{
return new Dictionary<string, object>();
}
}
But you wouldn't be able to have anything similar to virtual
, I think.
EDIT:
Actually, you can do virtual
, using self-referential generics:
class ModelBase<TModel>
{
public virtual IDictionary<string, object> GetHtmlAttributes<TProperty>
(Expression<Func<TModel, TProperty>> propertyExpression)
{
return new Dictionary<string, object>();
}
}
class FooModel : ModelBase<FooModel>
{
public override IDictionary<string, object> GetHtmlAttributes<TProperty>
(Expression<Func<FooModel, TProperty>> propertyExpression)
{
return new Dictionary<string, object> { { "foo", "bar" } };
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With