Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Nansen {
- public static class DisplayExtensions {
- public const string DEFAULT_PREFIX_VIEW_FORMAT = "{0}.{1}";
- public const string DIRECTORY_PREFIX_VIEW_FORMAT = "{0}/{1}";
- /// <summary>
- /// <see cref="System.Web.Mvc.Html.DisplayExtensions.DisplayFor{TModel,TValue}(System.Web.Mvc.HtmlHelper{TModel},System.Linq.Expressions.Expression{System.Func{TModel,TValue}})"/>
- /// 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.
- /// </summary>
- /// <remarks>
- /// 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}})"/>
- /// 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
- /// using no template at all.
- /// </remarks>
- /// <typeparam name="TModel">The model type</typeparam>
- /// <typeparam name="TValue">The value type</typeparam>
- /// <param name="html">The html helper</param>
- /// <param name="expression">The value expression</param>
- /// <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>
- /// <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>
- /// <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>
- /// <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>
- /// <returns>The rendered html</returns>
- public static MvcHtmlString DisplayForWithPrefix<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templatePrefix,
- string viewFormat = DEFAULT_PREFIX_VIEW_FORMAT, string fallbackTemplate = null, bool preferInterfaceBeforeBaseClass = false)
- {
- var metaData = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
- var modelType = metaData.Model.GetType(); // this is the most derived type of the model
- Func<string, MvcHtmlString> renderer = templateName => System.Web.Mvc.Html.DisplayExtensions.DisplayFor(html, expression, templateName);
- // first, check all concrete implementations
- while(modelType != null) {
- var viewName = string.Format(viewFormat, templatePrefix, modelType.Name);
- if(DisplayTemplateExist(html.ViewContext, viewName)) {
- return renderer(viewName);
- }
- if(preferInterfaceBeforeBaseClass) {
- // check interfaces defined on the model type directly
- var exceptions = modelType.BaseType != null ? modelType.BaseType.GetInterfaces() : Enumerable.Empty<Type>();
- foreach(var @interface in metaData.Model.GetType().GetInterfaces().Except(exceptions)) {
- viewName = string.Format(viewFormat, templatePrefix, @interface.Name);
- if(DisplayTemplateExist(html.ViewContext, viewName)) {
- return renderer(viewName);
- }
- }
- }
- modelType = modelType.BaseType;
- }
- // check all interfaces, if not already checked per implementation
- if(!preferInterfaceBeforeBaseClass) {
- foreach(var @interface in metaData.Model.GetType().GetInterfaces()) {
- var viewName = string.Format(viewFormat, templatePrefix, @interface.Name);
- if(DisplayTemplateExist(html.ViewContext, viewName)) {
- return renderer(viewName);
- }
- }
- }
- // fallback
- return renderer(fallbackTemplate);
- }
- private static bool DisplayTemplateExist(ViewContext context, params string[] templateNames)
- {
- foreach(var templateName in templateNames) {
- // the FindPartialView will not automatically search the displaytemplates folder, but the DisplayFor method will
- var viewResult = ViewEngines.Engines.FindPartialView(context, "DisplayTemplates/" + templateName);
- return viewResult.View != null;
- }
- return false;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement