Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC editor templates and Html.EditorFor(...) - how to disambiguate the type name?

When using this HTML helper in Razor syntax:

@Html.EditorFor(model => model.Prop1)

... the convention is to render the view under Views/<CrtView|Shared>/EditorTemplates/Prop1TypeName.cshtml.

So far so good. Notice that if the (qualified) type of Prop1 is my.org.ns.TheType, the file TheType.cshtml will be rendered.

But if I have a model with .Prop1 and .Prop2, and :

Prop1.GetType().FullName == "my.org.ns1.TheType";
Prop2.GetType().FullName == "my.org.ns2.TheType";  //same type name but different namespace

and I call this Razor:

@Html.EditorFor(model => model.Prop1)
@Html.EditorFor(model => model.Prop2)

...I can't get it to display different views for the different types.

Is there a way to disambiguate this?

Maybe there's more than I know about the naming convention for the .cshtml file?

like image 737
Cristian Diaconescu Avatar asked Aug 26 '13 13:08

Cristian Diaconescu


People also ask

What is HTML EditorFor in MVC?

Create HTML Controls for Model Class Properties using EditorFor() ASP.NET MVC includes the method that generates HTML input elements based on the datatype. The Html. Editor() or Html. EditorFor() extension methods generate HTML elements based on the data type of the model object's property.

What is the difference between Textboxfor and EditorFor?

it's absolutly wrong answer, becuase the key difference is that Texbox returns input and editorfor returns your template where input is default template for editorfor.

What is MVC editor template?

An EditorTemplate is a Razor file placed in the EditorTemplates folder: For Razor Pages apps, in the Pages/Shared/EditorTemplates folder. For MVC apps, in the Views/Shared/EditorTemplates folder or the Views/ControllerName/EditorTemplates folder.


2 Answers

You can use this overload to specify the name of the editor to use. With this, you would name your EditorTemplates First.cshtml and Second.cshtml, then in your View, do this.

@Html.EditorFor(model => model.Prop1, "First")
@Html.EditorFor(model => model.Prop2, "Second")

However, I would recommend avoiding reusing the same type name in the same project, even if they have different namespaces. This will cause confusion for someone reading the code, maybe even you down the road. That is a bigger issue than the framework not knowing what template to use.

like image 77
cadrell0 Avatar answered Nov 12 '22 14:11

cadrell0


When examining the ASP.NET MVC source code (line 164):

 // TODO: Make better string names for generic types
 yield return fieldType.Name;

It's seems that the development team is aware that this simplified approach (fieldType.Name for complex type) could be potentiality ambiguous. i hope they'll find an elegant way to let us choose templates in a more flexible way.

In the meantime, you can simply use the [UIHint] attribute, as follows:

[UIHint("ns1.TheType")]
public TheType Prop1 { get; set; }

[UIHint("ns2.TheType")]
public TheType Prop2 { get; set; }

Update (as per your comment):

The [UIHint] can only be used on a property or a field, hence you can't use it to decorate your class.

However, you can create your own attribute that derives from UIHintAttribute:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = true)]
public class MyUIHintAttribute : UIHintAttribute
{
    public MyUIHintAttribute(string templateName) : base(templateName)
    {
    }
}

Then decorate your classes:

[MyUIHint("ns1.TheType")]
public class TheType
{
    ....
}

[MyUIHint("ns2.TheType")]
public class TheType
{
    ....
}
like image 22
haim770 Avatar answered Nov 12 '22 14:11

haim770