Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle MVC DisplayTemplates for two classes with the same name (different namespaces)

Tags:

c#

asp.net-mvc

You can only have one View per class name in the DisplayTemplates folder as the class name is used as the name of the view.cshtml file.

However, you can have two classes in a solution with the same name if they appear in different namespaces:

MyNamespace.Class1
MyOtherNamespace.Class1

Both try to use the DisplayTemplate defined by view:

Class1.cshtml

However in the view file you must declare the model - for example:

@model MyNamespace.Class1

This means that if you have a DisplayFor which takes a MyOtherNamespace.Class1 you get a runtime error due to a type mismatch.

If you knew in advance the places where this was going to happen you could use the UIHint to force the DisplayFor to use an alternative template (or you could use a named template directly in the view). But if you don't know in advance (you have all these objects in an enumeration of some kind and therefore can't write specific code to handle edge cases like this without a lot of unwieldy reflection - is there any way to have DisplayTemplates for these classes?

like image 291
Kaine Avatar asked Aug 15 '17 15:08

Kaine


1 Answers

I haven't tried something like this before, but it should work. You can have the view accept a generic model type like object, and then attempt to cast it to the appropriate type:

@model object

@if (Model is MyNamespace.Class1)
{
    var class1 = Model as MyNamespace.Class1;
    // view code for this type
}

@if (Model is MyOtherNamespace.Class1)
{
    var class1 = Model as MyOtherNamespace.Class1;
    // view code for this type
}

UPDATE

Looking again at this, I'm bothered by the branching being done in this template. That's unavoidable, but a slightly better solution might be something like:

@model object

@if (Model is MyNamespace.Class1)
{
    Html.RenderPartial("MyNamespaceClass1", Model);
}

@if (Model is MyOtherNamespace.Class1)
{
    Html.RenderPartial("MyOtherNamespaceClass1", Model);
}

Then, simply create those additional views. That way, your code is still neatly broken into specific views, which can have the appropriate model declaration. This view basically just becomes a proxy that routes to the right one.

like image 130
Chris Pratt Avatar answered Oct 05 '22 23:10

Chris Pratt