I have a case where a complex partial view needs different validation of fields depending on where the partial view is used.
I thought I could get around this by making the partial view take an interface as the model type and implementing two different ViewModels based on the interface. The data annotations in the two ViewModels would be different. I would then supply an instance of the correct ViewModel to the partial view.
But what I'm finding is that the only annotations that are recognized are those on the interface itself. DAs on the interface-implementing ViewModel classes are ignored, even though those are the objects that are being passed as models. So my plan isn't working.
Is there a way around this? A better approach? I'd prefer not to split the partial view into separate views if I can avoid it.
ETA: This is an abbreviated version of the partial view, as requested:
@model IPerson
@Html.ValidationSummary(false)
<fieldset>
<table class="editForm">
<tr>
<td class="editor-label">
@Html.LabelFor(model => model.FirstName)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</td>
<td class="editor-label">
@Html.LabelFor(model => model.LastName)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</td>
</tr>
</table>
<fieldset>
The real partial view is quite long and has a lot of @if statements managing the rendering (or not) of optional sections, but it doesn't do anything tricky.
My idea isn't going to work: this thread reminded me that classes don't inherit attributes from their interfaces. (As the answer points out, what would happen if two interfaces specified the same property with different attributes, and both were implemented by one class?)
It might work with a common base class. I will try that tomorrow.
Thanks, everybody.
Well, actually you have a very reasonable idea! and can be archived is you use the non generic version of the HtmlHelper methods (ex. "@Html.Editor" instead of "@Html.EditorFor"), because the generic versions recreate the ModelMetadata (i don't know why!) based on the generic parameter type and don't use the ModelMetadata of the view. Freaking awful, isn't it?
Hope this help.
Ann, you're right. I've deleted my comment. You can't post an interface back through your view. However, I don't know what exactly your trying to do since I can't see your code. Maybe something like this? I'm passing an interface to the view, but passing it back as the class I'm expecting. Again, I'm not sure the application is here.
Let's say you have classes like this:
Your Controller looks like:
And your View Looks like this: