I have such interface:
public interface IFoo
{
decimal Amount { get; set; }
}
And I have some view models implement it:
public class Foo1 : IFoo
{
[Display(Name = "Foo1 Amount")]
[Range(6, 11)]
public decimal Amount { get; set; }
}
public class Foo2 : IFoo
{
[Display(Name = "Foo2 Amount")]
[Range(1, 5)]
public decimal Amount { get; set; }
}
I don't want to create a new view for each of Foo1
and Foo2
.
So, I have created a view which has IFoo
type model.
@model IFoo
<div>
@Html.LabelFor(x => x.Amount)
@Html.TextBoxFor(x => x.Amount)
@Html.ValidationMessageFor(x => x.Amount)
</div>
But, it doesn't create client-side unobtrusive attributes like Range
attribute in client-side.
If I create a new view for each of this types, then everyting will be ok.
Update: I have tried to change interface to abstract class as offered in the answer, but it didn't help neither.
I would suggest you instead use an abstract or just use a base class, define the Amount property with some default range and override in the subclass.
Unfortunately you cannot do this using an interface. When you use a html helper to generate html, it first generates the
ModelMetadata
for the property (in the case of the strongly typed html helpers, by callingThis generates the metadata based on the property taking into account its attributes. In the case of
TextBoxFor()
, theGetUnobtrusiveValidationAttributes()
method ofHtmlHelper
is then called to generate thedata-val-*
attributes.The key here is that its the metadata for the property, and the property its getting the metadata for does not have any validation attributes. And further to your comment "@Model.GetType() is Foo1 or Foo2", it does not attempt to get an instance of the concrete type and generate its metadata.
Unless you were to create your own ModelMetadataProvider and override the CreateMetadata() method, you need to create separate views for each concrete class.