Search code examples
asp.net-mvcrazordisplay-templates

What is use of UIHint attribute in ASP.Net MVC


just reading about UIHint from this url What is use of UIHint attribute in MVC

If you annotate a property with UIHint attribute and use EditorFor or DisplayFor inside your views, ASP.NET MVC framework will look for the specified template which you specified through UIHintAttribute. The directories it looks for is:

For EditorFor:

~/Views/Shared/EditorTemplates

~/Views/Controller_Name/EditorTemplates

For DisplayFor:

~/Views/Shared/DisplayTemplates

~/Views/Controller_Name/DisplayTemplates

the above write up means MVC engine first search view in shared if not found then it will search view in ~/Views/Controller_Name/DisplayTemplates ?

i just got a code but it is not complete so not being able to understand it properly

public class Person { 

    [UIHint("Poo")]
    public string Name { get; set; }
}

@model MyApp.Models.Person

<h2>My Person</h2>

@Html.DisplayFor(m => m.Name)

if i think Poo is a shared view then where is poo related view code?

when this line will execute @Html.DisplayFor(m => m.Name) then what will happen.

see this code

@Html.EditorFor(model => model.ProductViewModel, "yourTemplateName")

where MVC will find the file yourTemplateName.cshtml?

thanks


Solution

  • the above write up means MVC engine first search view in shared if not found then it will search view in ~/Views/Controller_Name/DisplayTemplates ?

    That is backwards, the search pattern is (exactly):

    (if in an area)

    "~/Areas/{2}/Views/{1}/DisplayTemplates/{0}.cshtml",
    "~/Areas/{2}/Views/{1}/DisplayTemplates/{0}.vbhtml",
    "~/Areas/{2}/Views/Shared/DisplayTemplates/{0}.cshtml",
    "~/Areas/{2}/Views/Shared/DisplayTemplates/{0}.vbhtml"
    

    then

    "~/Views/{1}/DisplayTemplates/{0}.cshtml",
    "~/Views/{1}/DisplayTemplates/{0}.vbhtml",
    "~/Views/Shared/DisplayTemplates/{0}.cshtml",
    "~/Views/Shared/DisplayTemplates/{0}.vbhtml"
    

    Where

    0 = Template/Type name
    1 = ControllerName
    2 = AreaName
    

    (In the event you do not provide a Template name hint, the razor engine default to the type (int, boolean, string and even custom class types you've defined)

    if i think Poo is a shared view then where is poo related view code?

    In one more more of the locations above. This allows you to create poo specific views per controller and/or a shared poo view. It's however you want to do it.

    when this line will execute @Html.DisplayFor(m => m.Name) then what will happen.

    The engine will search the above folders for a template. In the event one is not found it then looks for object.cshtml/vbhtml in the same folders. If that file is found it executes it, if not it executes the default internal object display for code.

    where MVC will find the file yourTemplateName.cshtml?

    In the same directories above. You have to understand this it does the same thing over and over, it is a convention of .

    What is use of UIHint attribute in ASP.Net MVC

    This allows you to override the template used for a given property.

    public class Person
    {
      [UIHint("Age")]
      public DateTime Birthday { get; set; }
    }
    

    Will attempt to look for 'age.cshtml' in the above locations. Since the UIHintAttribute is not sealed you can also derive your own attribute and create some pretty nifty templates:

    public UIDateTimeAttribute : UIHintAttribute
    {
      public UIDateTimeAttribute(bool canShowSeconds)
        : base("UIDateTime", "MVC")
      {
        CanShowSeconds = canShowSeconds;
      }
    
      public bool CanShowSeconds { get; private set; }
    }
    

    Then your model might looks like:

    public class Person
    {
      [UIDateTime(false)]
      public DateTime Birthday { get; set; }
    }
    

    UIDateTime.cshtml

    @model DateTime
    
    @{
      var format = "dd-MM-yy hh:mm:ss";
    
      // Get the container model (Person for example)
      var attribute = ViewData.ModelMetadata.ContainerType
        // Get the property we are displaying for (Birthday)
        .GetProperty(ViewData.ModelMetadata.PropertyName)
        // Get all attributes of type UIDateTimeAttribute
        .GetCustomAttributes(typeof(UIDateTimeAttribute))
        // Cast the result as UIDateTimeAttribute
        .Select(a => a as UIDateTimeAttribute)
        // Get the first one or null
        .FirstOrDefault(a => a != null);
    
      if (attribute != null && !attribute.CanShowTime)
      {
        format = "dd-MM-yy hh:mm";
      }
    }
    
    @Model.ToString(format)