View difference between Paste ID: Y1ES6gg7 and EL1vcV58
SHOW: | | - or go back to the newest paste.
1
namespace Nansen { 
2
  public static class DisplayExtensions {
3
    public const string DEFAULT_PREFIX_VIEW_FORMAT = "{0}.{1}";
4
    public const string DIRECTORY_PREFIX_VIEW_FORMAT = "{0}/{1}";
5
6-
    /// <summary>
6+
    /// <summary>
7-
    /// &lt;see cref="System.Web.Mvc.Html.DisplayExtensions.DisplayFor{TModel,TValue}(System.Web.Mvc.HtmlHelper{TModel},System.Linq.Expressions.Expression{System.Func{TModel,TValue}})"/&gt;
7+
    /// <see cref="System.Web.Mvc.Html.DisplayExtensions.DisplayFor{TModel,TValue}(System.Web.Mvc.HtmlHelper{TModel},System.Linq.Expressions.Expression{System.Func{TModel,TValue}})"/>
8
    /// overload using a template prefix. Used to display for the value type using a custom prefix so one object type can have different templates. Will fall back to base types.
9-
    /// &lt;/summary&gt;
9+
    /// </summary>
10-
    /// &lt;remarks&gt;
10+
    /// <remarks>
11-
    /// Works similar to regular &lt;see cref="System.Web.Mvc.Html.DisplayExtensions.DisplayFor{TModel,TValue}(System.Web.Mvc.HtmlHelper{TModel},System.Linq.Expressions.Expression{System.Func{TModel,TValue}})"/&gt; 
11+
    /// Works similar to regular <see cref="System.Web.Mvc.Html.DisplayExtensions.DisplayFor{TModel,TValue}(System.Web.Mvc.HtmlHelper{TModel},System.Linq.Expressions.Expression{System.Func{TModel,TValue}})"/> 
12-
    /// where the template type is searched recursively using &lt;see cref="Type.BaseType"/&gt;. If no template can be found, it will fallback to the default System.Web.Mvc.Html.DisplayExtensions.DisplayFor method 
12+
    /// where the template type is searched recursively using <see cref="Type.BaseType"/>. If no template can be found, it will fallback to the default System.Web.Mvc.Html.DisplayExtensions.DisplayFor method 
13
    /// using no template at all.
14-
    /// &lt;/remarks&gt;
14+
    /// </remarks>
15-
    /// &lt;typeparam name="TModel"&gt;The model type&lt;/typeparam&gt;
15+
    /// <typeparam name="TModel">The model type</typeparam>
16-
    /// &lt;typeparam name="TValue"&gt;The value type&lt;/typeparam&gt;
16+
    /// <typeparam name="TValue">The value type</typeparam>
17-
    /// &lt;param name="html"&gt;The html helper&lt;/param&gt;
17+
    /// <param name="html">The html helper</param>
18-
    /// &lt;param name="expression"&gt;The value expression&lt;/param&gt;
18+
    /// <param name="expression">The value expression</param>
19-
    /// &lt;param name="templatePrefix"&gt;The template prefix, ex using "MyStringList" for &lt;typeparamref name="TValue"/&gt; string would, using default &lt;paramref name="viewFormat" /&gt;, look for the display template named MyStringList.string.cshtml&lt;/param&gt;
19+
    /// <param name="templatePrefix">The template prefix, ex using "MyStringList" for <typeparamref name="TValue"/> string would, using default <paramref name="viewFormat" />, look for the display template named MyStringList.string.cshtml</param>
20-
    /// &lt;param name="viewFormat"&gt;How to format the view template name, format arguments: {0} - &lt;paramref name="templatePrefix"/&gt;, {1} - model type name. / can also be used to make the prefix be a directory&lt;/param&gt;
20+
    /// <param name="viewFormat">How to format the view template name, format arguments: {0} - <paramref name="templatePrefix"/>, {1} - model type name. / can also be used to make the prefix be a directory</param>
21-
    /// &lt;param name="fallbackTemplate"&gt;If set, will be used if no display template can be found, otherwise DisplayFor without template will be called as fallback&lt;/param&gt;
21+
    /// <param name="fallbackTemplate">If set, will be used if no display template can be found, otherwise DisplayFor without template will be called as fallback</param>
22-
    /// &lt;param name="preferInterfaceBeforeBaseClass"&gt;If true, the display template search prefers interfaces before base classes, otherwise all base classes will be checked before any interface. Also, only interfaces defined directly on the current type being searched is considered each &lt;see cref="Type.BaseType"/&gt; iteration&lt;/param&gt;
22+
    /// <param name="preferInterfaceBeforeBaseClass">If true, the display template search prefers interfaces before base classes, otherwise all base classes will be checked before any interface. Also, only interfaces defined directly on the current type being searched is considered each <see cref="Type.BaseType"/> iteration</param>
23-
    /// &lt;returns&gt;The rendered html&lt;/returns&gt;
23+
    /// <returns>The rendered html</returns>
24-
    public static MvcHtmlString DisplayForWithPrefix&lt;TModel, TValue&gt;(this HtmlHelper&lt;TModel&gt; html, Expression&lt;Func&lt;TModel, TValue&gt;&gt; expression, string templatePrefix,
24+
    public static MvcHtmlString DisplayForWithPrefix<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templatePrefix,
25
      string viewFormat = DEFAULT_PREFIX_VIEW_FORMAT, string fallbackTemplate = null, bool preferInterfaceBeforeBaseClass = false)
26
    {
27
      var metaData = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
28
      var modelType = metaData.Model.GetType(); // this is the most derived type of the model
29
30-
      Func&lt;string, MvcHtmlString&gt; renderer = templateName =&gt; System.Web.Mvc.Html.DisplayExtensions.DisplayFor(html, expression, templateName);
30+
      Func<string, MvcHtmlString> renderer = templateName => System.Web.Mvc.Html.DisplayExtensions.DisplayFor(html, expression, templateName);
31
32
      // first, check all concrete implementations
33
      while(modelType != null) {
34
        var viewName = string.Format(viewFormat, templatePrefix, modelType.Name);
35
36
        if(DisplayTemplateExist(html.ViewContext, viewName)) {
37
          return renderer(viewName);
38
        }
39
40
        if(preferInterfaceBeforeBaseClass) {
41
          // check interfaces defined on the model type directly
42-
          var exceptions = modelType.BaseType != null ? modelType.BaseType.GetInterfaces() : Enumerable.Empty&lt;Type&gt;();
42+
          var exceptions = modelType.BaseType != null ? modelType.BaseType.GetInterfaces() : Enumerable.Empty<Type>();
43
          foreach(var @interface in metaData.Model.GetType().GetInterfaces().Except(exceptions)) {
44
            viewName = string.Format(viewFormat, templatePrefix, @interface.Name);
45
            if(DisplayTemplateExist(html.ViewContext, viewName)) {
46
              return renderer(viewName);
47
            }
48
          }
49
        }
50
51
        modelType = modelType.BaseType;
52
      }
53
54
      // check all interfaces, if not already checked per implementation
55
      if(!preferInterfaceBeforeBaseClass) {
56
        foreach(var @interface in metaData.Model.GetType().GetInterfaces()) {
57
          var viewName = string.Format(viewFormat, templatePrefix, @interface.Name);
58
          if(DisplayTemplateExist(html.ViewContext, viewName)) {
59
            return renderer(viewName);
60
          }
61
        }
62
      }
63
64
      // fallback
65
      return renderer(fallbackTemplate);
66
    }
67
68
    private static bool DisplayTemplateExist(ViewContext context, params string[] templateNames)
69
    {
70
      foreach(var templateName in templateNames) {
71
        // the FindPartialView will not automatically search the displaytemplates folder, but the DisplayFor method will
72
        var viewResult = ViewEngines.Engines.FindPartialView(context, "DisplayTemplates/" + templateName);
73
        return viewResult.View != null;
74
      }
75
      return false;
76
    }
77
  }
78
}