Reputation: 93
I have basic class:
public abstract class AbstractBaseModel : IModel
{
[Display(Name = "Some Name")]
[DisplayFormat(DataFormatString = "{0:d0}")]
[RegularExpression(@"[0-9]{1,10}", ErrorMessage = "error")]
public virtual string SomeName{ get; set; }
}
The IModel
interface is just simple declaration of properties:
public interface IModel
{
string SomeName{ get; set; }
}
From the base model I have 2 derived models
public class ClientModel : AbstractBaseModel
{
[Required(ErrorMessage = "Some error message for customer only")]
public override string SomeName{ get; set; }
}
public class PowerUserModel : AbstractBaseModel
{
[Required(ErrorMessage = "Different message for the admin")]
public override string SomeName{ get; set; }
}
This model, or rather interface is part of another model that combines multiple models:
public class ComboEndModel
{
public IModel Model { get; set; }
public IDifferentModel DifferentModel { get; set; }
}
Depending on the View
/Controler
that is currently used, I pass new ClientModel
or PowerUserModel
as a Model in ComboEndModel
When the view is rendered, I'm only getting the annotations from the base, abstract model, not the ones added in the derivative type. I suspect that's because I'm using interface as a nested model property instead of type.
Whats the correct way of implementing this relation, or working around the issue with incorrect annotations? Should I try with custom binding?
Upvotes: 2
Views: 299
Reputation: 13949
One thing that might work for you would be to create editor templates for each derived model.
If you define your ComboEndModel like this
var model = new ComboEndModel() { Model = new PowerUserModel() };
return View(model);
and in your view you use EditorFor
@model WebApplication.Models.ComboEndModel
@Html.EditorFor(m => m.Model)
depending on what Type Model
is, it will pick the associated editor template and apply the annotations for that derived type. In this case you'd need a partial view in your EditorTemplates
folder named PowerUserModel.cshtml
with a model type of PowerUserModel
Upvotes: 3
Reputation: 3784
Ok I have some problems with that too, and what I understood so far is (someone correct me if I'm wrong):
Why this problem occurs?
Because the DataAnnotation
that is retrieved are retrived from the type of the model. Let me show you some samples:
If you have in your .cshtml
file:
Sample 1:
@model AbstractBaseModel
// The type that will be retrived is `AbstractBaseModel`.
Sample 2:
@model IModel
// The type that will be retrived is `IModel`.
Or in other case if you have actions:
public ActionResult SomeAction(AbstractBaseModel model) { /* ... */ }
Sample 2:
public ActionResult SomeAction(IModel model) { /* ... */ }
So what matters is what type you specified in @model or in the action parameter. Doesn't matter if is interface, abstract class, base class or other type of class, matter only the type you described in your use.
In your example specifically you wrote:
public class ComboEndModel
{
public IModel Model { get; set; }
// ...
}
So the DataAnnotation will be retrive from IModel, but IModel don't have a RequiredAttribute
defined so you get one step further in the chain of inheritance/implementation and get AbstractBaseModel
. (Try this to confirm what I'm writing: put a required in IModel.SomeName with a different message and see what message will get).
Solution/Suggestion
If I'm right, there is no solution for your problem without change the strategy. So here some suggestions about what you can do:
Upvotes: 2