Permalink
Browse files

Web.Routing - cleanup template / rendering engine lookup

  • Loading branch information...
zpqrtbnk committed Jan 23, 2013
1 parent 58b91fe commit b77521cbc54e45554c0a51a99ebf3baae7555613
@@ -1,8 +1,9 @@
namespace Umbraco.Core
{
public enum RenderingEngine
{
Mvc,
WebForms
}
public enum RenderingEngine
{
Unknown,
Mvc,
WebForms
}
}
@@ -24,7 +24,7 @@ namespace Umbraco.Web.Routing
{
/// <summary>
/// Represents a request for one specified Umbraco IPublishedContent to be rendered
/// by one specified Template, using one specified Culture and RenderingEngine.
/// by one specified template, using one specified Culture and RenderingEngine.
/// </summary>
internal class PublishedContentRequest
{
@@ -117,7 +117,7 @@ internal void OnPrepared()
/// <summary>
/// Gets or sets the requested content.
/// </summary>
/// <remarks>Setting the requested content clears both <c>Template</c> and <c>AlternateTemplateAlias</c>.</remarks>
/// <remarks>Setting the requested content clears <c>Template</c>.</remarks>
public IPublishedContent PublishedContent
{
get { return _publishedContent; }
@@ -181,7 +181,7 @@ public bool HasPublishedContent
/// </summary>
public bool HasTemplate
{
get { return this.Template != null ; }
get { return this.Template != null; }
}

#endregion
@@ -237,63 +237,73 @@ private void HandleWildcardDomains()

#region Rendering engine

/// <summary>
/// Finds the rendering engine to use to render a template specified by its alias.
/// </summary>
/// <param name="alias">The alias of the template.</param>
/// <returns>The rendering engine, or Unknown if the template was not found.</returns>
internal RenderingEngine FindTemplateRenderingEngine(string alias)
{
if (string.IsNullOrWhiteSpace(alias))
return RenderingEngine.Unknown;

alias = alias.Replace('\\', '/'); // forward slashes only

// NOTE: we could start with what's the current default?

if (FindTemplateRenderingEngineInDirectory(new DirectoryInfo(IOHelper.MapPath(SystemDirectories.MvcViews)),
alias, new[] { ".cshtml", ".vbhtml" }))
return RenderingEngine.Mvc;

if (FindTemplateRenderingEngineInDirectory(new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Masterpages)),
alias, new[] { ".master" }))
return RenderingEngine.WebForms;

return RenderingEngine.Unknown;
}

internal bool FindTemplateRenderingEngineInDirectory(DirectoryInfo directory, string alias, string[] extensions)
{
if (directory == null || !directory.Exists)
return false;

var pos = alias.IndexOf('/');
if (pos > 0)
{
// recurse
var subdir = directory.GetDirectories(alias.Substring(0, pos)).FirstOrDefault();
alias = alias.Substring(pos + 1);
return subdir == null ? false : FindTemplateRenderingEngineInDirectory(subdir, alias, extensions);
}
else
{
// look here
return directory.GetFiles().Any(f => extensions.Any(e => f.Name.InvariantEquals(alias + e)));
}
}

/// <summary>
/// Finds the rendering engine to use, and updates the PublishedContentRequest accordingly.
/// </summary>
internal void FindRenderingEngine()
{
//First, if there is no template, we will default to use MVC because MVC supports Hijacking routes which
//sometimes don't require a template since the developer may want full control over the rendering.
//Webforms doesn't support this so MVC it is. MVC will also handle what to do if no template or hijacked route
//is there (i.e. blank page)
if (!_pcr.HasTemplate)
{
_pcr.RenderingEngine = RenderingEngine.Mvc;
return;
}

//NOTE: Not sure how the alias is actually saved with a space as this shouldn't ever be the case?
// but apparently this happens. I think what should actually be done always is the template alias
// should be saved using the ToUmbracoAlias method and then we can use this here too, that way it
// it 100% consistent. I'll leave this here for now until further invenstigation.
var templateAlias = _pcr.Template.Alias.Replace(" ", string.Empty);
//var templateAlias = _pcr.Template.Alias.ToUmbracoAlias(StringAliasCaseType.PascalCase);

Func<DirectoryInfo, string, string[], RenderingEngine, bool> determineEngine =
(directory, alias, extensions, renderingEngine) =>
{
//so we have a template, now we need to figure out where the template is, this is done just by the Alias field
//ensure it exists
if (!directory.Exists) Directory.CreateDirectory(directory.FullName);
var file = directory.GetFiles()
.FirstOrDefault(x => extensions.Any(e => x.Name.InvariantEquals(alias + e)));

if (file != null)
{
//it is mvc since we have a template there that exists with this alias
_pcr.RenderingEngine = renderingEngine;
return true;
}
return false;
};

//first determine if it is MVC, we will favor mvc if there is a template with the same name in both
// folders, if it is then MVC will be selected
if (!determineEngine(
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.MvcViews)),
templateAlias,
new[] { ".cshtml", ".vbhtml" },
RenderingEngine.Mvc))
{
//if not, then determine if it is webforms (this should def match if a template is assigned and its not in the MVC folder)
// if it doesn't match, then MVC will be used by default anyways.
determineEngine(
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Masterpages)),
templateAlias,
new[] { ".master" },
RenderingEngine.WebForms);
}

RenderingEngine renderingEngine = RenderingEngine.Unknown;

// NOTE: Not sure how the alias is actually saved with a space as this shouldn't ever be the case?
// but apparently this happens. I think what should actually be done always is the template alias
// should be saved using the ToUmbracoAlias method and then we can use this here too, that way it
// it 100% consistent. I'll leave this here for now until further invenstigation.
if (_pcr.HasTemplate)
renderingEngine = FindTemplateRenderingEngine(_pcr.Template.Alias.Replace(" ", ""));

// Unkwnown means that no template was found. Default to Mvc because Mvc supports hijacking
// routes which sometimes doesn't require a template since the developer may want full control
// over the rendering. Can't do it in WebForms, so Mvc it is. And Mvc will also handle what to
// do if no template or hijacked route is exist.
if (renderingEngine == RenderingEngine.Unknown)
renderingEngine = RenderingEngine.Mvc;

_pcr.RenderingEngine = renderingEngine;
}

#endregion

0 comments on commit b77521c

Please sign in to comment.