Creates ReflectedFixedRazorViewEngine and version checkers to dynamically update code depending on the major versions of MVC and WebApi

This commit is contained in:
Shannon
2015-01-06 17:39:07 +11:00
parent 106873732c
commit 4a72e8c3df
9 changed files with 156 additions and 14 deletions

View File

@@ -15,11 +15,11 @@
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.30506.0,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi" version="[4.0.30506,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.WebHost" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Core" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Client" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.30506.0,6.0.0)" />
<dependency id="Microsoft.AspNet.WebApi" version="[4.0.30506,6.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.WebHost" version="[4.0.30506, 6.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Core" version="[4.0.30506, 6.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Client" version="[4.0.30506, 6.0.0)" />
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" />
<dependency id="Microsoft.Net.Http" version="[2.0.20710.0, 3.0.0)" />
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />

View File

@@ -1,2 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.2.1
7.3.0

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Web.Mvc
{
internal class MvcVersionCheck
{
public static System.Version MvcVersion
{
get { return typeof (System.Web.Mvc.Controller).Assembly.GetName().Version; }
}
}
}

View File

@@ -1,15 +1,16 @@
using System.IO;
using System.Linq;
using System.Web.Mvc;
using Lucene.Net.Util;
using Microsoft.Web.Mvc;
using Umbraco.Core.IO;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// <summary>
/// A view engine to look into the App_Plugins folder for views for packaged controllers
/// </summary>
public class PluginViewEngine : FixedRazorViewEngine
public class PluginViewEngine : ReflectedFixedRazorViewEngine
{
/// <summary>
@@ -47,9 +48,9 @@ namespace Umbraco.Web.Mvc
})
.ToArray();
AreaMasterLocationFormats = viewLocationsArray;
AreaMasterLocationFormats = viewLocationsArray;
AreaPartialViewLocationFormats = new[]
AreaPartialViewLocationFormats = new[]
{
//will be used when we have partial view and child action macros
string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"),

View File

@@ -0,0 +1,98 @@
using System;
using System.Reflection;
using System.Web.Mvc;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// This is here to support compatibility with both MVC4 and MVC5
/// </summary>
public abstract class ReflectedFixedRazorViewEngine : IViewEngine
{
protected ReflectedFixedRazorViewEngine()
{
if (MvcVersionCheck.MvcVersion >= System.Version.Parse("5.0.0"))
{
_wrappedEngine = new RazorViewEngine();
}
else
{
var assembly = Assembly.Load("Microsoft.Web.Mvc.FixedDisplayModes");
var engineType = assembly.GetType("Microsoft.Web.Mvc.FixedRazorViewEngine");
_wrappedEngine = (IViewEngine)Activator.CreateInstance(engineType);
}
}
public string[] ViewLocationFormats
{
get { return _viewLocationFormats; }
set
{
_wrappedEngine.GetType().GetProperty("ViewLocationFormats").SetValue(_wrappedEngine, value);
_viewLocationFormats = value;
}
}
public string[] PartialViewLocationFormats
{
get { return _partialViewLocationFormats; }
set
{
_wrappedEngine.GetType().GetProperty("PartialViewLocationFormats").SetValue(_wrappedEngine, value);
_partialViewLocationFormats = value;
}
}
public string[] AreaViewLocationFormats
{
get { return _areaViewLocationFormats; }
set
{
_wrappedEngine.GetType().GetProperty("AreaViewLocationFormats").SetValue(_wrappedEngine, value);
_areaViewLocationFormats = value;
}
}
public string[] AreaMasterLocationFormats
{
get { return _areaMasterLocationFormats; }
set
{
_wrappedEngine.GetType().GetProperty("AreaMasterLocationFormats").SetValue(_wrappedEngine, value);
_areaMasterLocationFormats = value;
}
}
public string[] AreaPartialViewLocationFormats
{
get { return _areaPartialViewLocationFormats; }
set
{
_wrappedEngine.GetType().GetProperty("AreaPartialViewLocationFormats").SetValue(_wrappedEngine, value);
_areaPartialViewLocationFormats = value;
}
}
private readonly IViewEngine _wrappedEngine;
private string[] _areaViewLocationFormats;
private string[] _areaMasterLocationFormats;
private string[] _areaPartialViewLocationFormats;
private string[] _viewLocationFormats;
private string[] _partialViewLocationFormats;
public virtual ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
return _wrappedEngine.FindPartialView(controllerContext, partialViewName, useCache);
}
public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
return _wrappedEngine.FindView(controllerContext, viewName, masterName, useCache);
}
public void ReleaseView(ControllerContext controllerContext, IView view)
{
_wrappedEngine.ReleaseView(controllerContext, view);
}
}
}

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Web.Mvc
/// A view engine to look into the template location specified in the config for the front-end/Rendering part of the cms,
/// this includes paths to render partial macros and media item templates.
/// </summary>
public class RenderViewEngine : FixedRazorViewEngine
public class RenderViewEngine : ReflectedFixedRazorViewEngine
{
private readonly IEnumerable<string> _supplementedViewLocations = new[] { "/{0}.cshtml" };
@@ -33,7 +33,7 @@ namespace Umbraco.Web.Mvc
var replacePartialWithUmbracoFolder = _supplementedPartialViewLocations.ForEach(location => templateFolder + location);
//The Render view engine doesn't support Area's so make those blank
ViewLocationFormats = replaceWithUmbracoFolder.ToArray();
ViewLocationFormats = replaceWithUmbracoFolder.ToArray();
PartialViewLocationFormats = replacePartialWithUmbracoFolder.ToArray();
AreaPartialViewLocationFormats = new string[] { };

View File

@@ -78,6 +78,7 @@ namespace Umbraco.Web.Trees
var proxiedRouteData = new HttpRouteData(
controllerContext.RouteData.Route,
new HttpRouteValueDictionary(new {action = "GetRootNode", controller = ControllerExtensions.GetControllerName(instance.GetType())}));
//create a proxied controller context
var proxiedControllerContext = new HttpControllerContext(
controllerContext.Configuration,
@@ -86,10 +87,29 @@ namespace Umbraco.Web.Trees
{
ControllerDescriptor = new HttpControllerDescriptor(controllerContext.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(instance.GetType()), instance.GetType())
};
if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0"))
{
//In WebApi2, this is required to be set:
// proxiedControllerContext.RequestContext = controllerContext.RequestContext
// but we need to do this with reflection because of codebase changes between version 4/5
var controllerContextRequestContext = controllerContext.GetType().GetProperty("RequestContext").GetValue(controllerContext);
proxiedControllerContext.GetType().GetProperty("RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext);
}
instance.ControllerContext = proxiedControllerContext;
instance.Request = controllerContext.Request;
if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0"))
{
//now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above
// because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set
// this with reflection due to codebase changes between version 4/5
// instance.RequestContext.RouteData = proxiedRouteData;
var instanceRequestContext = instance.GetType().GetProperty("RequestContext").GetValue(instance);
instanceRequestContext.GetType().GetProperty("RouteData").SetValue(instanceRequestContext, proxiedRouteData);
}
//invoke auth filters for this sub request
var result = await instance.ControllerContext.InvokeAuthorizationFiltersForRequest();
//if a result is returned it means they are unauthorized, just throw the response.

View File

@@ -270,6 +270,8 @@
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="Models\LegacyConvertedNode.cs" />
<Compile Include="Models\LegacyConvertedNodeProperty.cs" />
<Compile Include="Mvc\MvcVersionCheck.cs" />
<Compile Include="Mvc\ReflectedFixedRazorViewEngine.cs" />
<Compile Include="Scheduling\BackgroundTaskRunner.cs" />
<Compile Include="BatchedServerMessenger.cs" />
<Compile Include="CacheHelperExtensions.cs" />
@@ -810,6 +812,7 @@
<Compile Include="WebApi\HttpRequestMessageExtensions.cs" />
<Compile Include="WebApi\JsonCamelCaseFormatter.cs" />
<Compile Include="WebApi\MemberAuthorizeAttribute.cs" />
<Compile Include="WebApi\MvcVersionCheck.cs" />
<Compile Include="WebApi\NamespaceHttpControllerSelector.cs" />
<Compile Include="WebApi\UmbracoApiController.cs" />
<Compile Include="WebApi\UmbracoApiControllerResolver.cs" />

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Web.WebApi
{
internal class WebApiVersionCheck
{
public static System.Version WebApiVersion
{
get { return typeof(System.Web.Http.ApiController).Assembly.GetName().Version; }
}
}
}