2012-07-20 01:04:35 +06:00
using System ;
2012-09-29 08:49:21 +07:00
using System.IO ;
2012-08-07 21:40:34 +06:00
using System.Threading ;
2012-09-29 08:49:21 +07:00
using System.Web.Mvc ;
2012-07-20 01:04:35 +06:00
namespace Umbraco.Web.Mvc
{
2012-09-29 08:49:21 +07:00
internal static class ControllerExtensions
2012-07-20 01:04:35 +06:00
{
2014-03-13 14:10:05 +11:00
internal static object GetDataTokenInViewContextHierarchy ( this ControllerContext controllerContext , string dataTokenName )
{
if ( controllerContext . RouteData . DataTokens . ContainsKey ( dataTokenName ) )
{
return controllerContext . RouteData . DataTokens [ dataTokenName ] ;
}
if ( controllerContext . ParentActionViewContext ! = null )
{
//recurse!
return controllerContext . ParentActionViewContext . GetDataTokenInViewContextHierarchy ( dataTokenName ) ;
}
return null ;
}
2012-07-20 01:04:35 +06:00
/// <summary>
/// Return the controller name from the controller type
/// </summary>
/// <param name="controllerType"></param>
/// <returns></returns>
2012-09-29 08:49:21 +07:00
internal static string GetControllerName ( Type controllerType )
2012-07-20 01:04:35 +06:00
{
2013-03-28 09:07:36 +06:00
if ( ! controllerType . Name . EndsWith ( "Controller" ) )
{
throw new InvalidOperationException ( "The controller type " + controllerType + " does not follow conventions, MVC Controller class names must be suffixed with the term 'Controller'" ) ;
}
2012-07-20 01:04:35 +06:00
return controllerType . Name . Substring ( 0 , controllerType . Name . LastIndexOf ( "Controller" ) ) ;
}
/// <summary>
2013-05-12 19:05:49 -10:00
/// Return the controller name from the controller instance
/// </summary>
/// <param name="controllerInstance"></param>
/// <returns></returns>
internal static string GetControllerName ( this IController controllerInstance )
{
return GetControllerName ( controllerInstance . GetType ( ) ) ;
}
/// <summary>
2012-07-20 01:04:35 +06:00
/// Return the controller name from the controller type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <remarks></remarks>
2012-09-29 08:49:21 +07:00
internal static string GetControllerName < T > ( )
2012-07-20 01:04:35 +06:00
{
return GetControllerName ( typeof ( T ) ) ;
}
2012-09-29 08:49:21 +07:00
/// <summary>
/// This is generally used for proxying to a ChildAction which requires a ViewContext to be setup
/// but since the View isn't actually rendered the IView object is null, however the rest of the
/// properties are filled in.
/// </summary>
/// <param name="controller"></param>
/// <returns></returns>
internal static ViewContext CreateEmptyViewContext ( this ControllerBase controller )
{
return new ViewContext
{
Controller = controller ,
HttpContext = controller . ControllerContext . HttpContext ,
RequestContext = controller . ControllerContext . RequestContext ,
RouteData = controller . ControllerContext . RouteData ,
TempData = controller . TempData ,
ViewData = controller . ViewData
} ;
}
/// <summary>
/// Returns the string output from a ViewResultBase object
/// </summary>
/// <param name="controller"></param>
/// <param name="viewResult"></param>
/// <returns></returns>
internal static string RenderViewResultAsString ( this ControllerBase controller , ViewResultBase viewResult )
{
using ( var sw = new StringWriter ( ) )
{
controller . EnsureViewObjectDataOnResult ( viewResult ) ;
var viewContext = new ViewContext ( controller . ControllerContext , viewResult . View , viewResult . ViewData , viewResult . TempData , sw ) ;
viewResult . View . Render ( viewContext , sw ) ;
foreach ( var v in viewResult . ViewEngineCollection )
{
v . ReleaseView ( controller . ControllerContext , viewResult . View ) ;
}
return sw . ToString ( ) . Trim ( ) ;
}
}
2012-11-14 10:47:40 +05:00
2012-09-29 08:49:21 +07:00
/// <summary>
/// Renders the partial view to string.
/// </summary>
/// <param name="controller">The controller context.</param>
/// <param name="viewName">Name of the view.</param>
/// <param name="model">The model.</param>
2012-11-14 10:47:40 +05:00
/// <param name="isPartial">true if it is a Partial view, otherwise false for a normal view </param>
2012-09-29 08:49:21 +07:00
/// <returns></returns>
2012-11-14 10:47:40 +05:00
internal static string RenderViewToString ( this ControllerBase controller , string viewName , object model , bool isPartial = false )
2012-09-29 08:49:21 +07:00
{
2012-11-14 10:47:40 +05:00
if ( controller . ControllerContext = = null )
throw new ArgumentException ( "The controller must have an assigned ControllerContext to execute this method." ) ;
2012-09-29 08:49:21 +07:00
controller . ViewData . Model = model ;
2012-11-14 10:47:40 +05:00
using ( var sw = new StringWriter ( ) )
2012-09-29 08:49:21 +07:00
{
2012-11-14 10:47:40 +05:00
var viewResult = ! isPartial
? ViewEngines . Engines . FindView ( controller . ControllerContext , viewName , null )
: ViewEngines . Engines . FindPartialView ( controller . ControllerContext , viewName ) ;
var viewContext = new ViewContext ( controller . ControllerContext , viewResult . View , controller . ViewData , controller . TempData , sw ) ;
2012-09-29 08:49:21 +07:00
viewResult . View . Render ( viewContext , sw ) ;
2012-12-04 03:26:04 +05:00
viewResult . ViewEngine . ReleaseView ( controller . ControllerContext , viewResult . View ) ;
2012-09-29 08:49:21 +07:00
return sw . GetStringBuilder ( ) . ToString ( ) ;
}
}
2013-03-11 20:11:11 +06:00
/// <summary>
/// Normally in MVC the way that the View object gets assigned to the result is to Execute the ViewResult, this however
/// will write to the Response output stream which isn't what we want. Instead, this method will use the same logic inside
2015-07-22 18:25:08 +02:00
/// of MVC to assign the View object to the result but without executing it.
2013-03-11 20:11:11 +06:00
/// This is only relavent for view results of PartialViewResult or ViewResult.
/// </summary>
/// <param name="result"></param>
/// <param name="controller"></param>
2015-07-22 18:25:08 +02:00
private static void EnsureViewObjectDataOnResult ( this ControllerBase controller , ViewResultBase result )
{
2013-03-11 20:11:11 +06:00
if ( result . View ! = null ) return ;
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
if ( string . IsNullOrEmpty ( result . ViewName ) )
result . ViewName = controller . ControllerContext . RouteData . GetRequiredString ( "action" ) ;
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
if ( result . View ! = null ) return ;
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
if ( result is PartialViewResult )
{
var viewEngineResult = ViewEngines . Engines . FindPartialView ( controller . ControllerContext , result . ViewName ) ;
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
if ( viewEngineResult . View = = null )
{
throw new InvalidOperationException ( "Could not find the view " + result . ViewName + ", the following locations were searched: " + Environment . NewLine + string . Join ( Environment . NewLine , viewEngineResult . SearchedLocations ) ) ;
}
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
result . View = viewEngineResult . View ;
}
else if ( result is ViewResult )
{
var vr = ( ViewResult ) result ;
var viewEngineResult = ViewEngines . Engines . FindView ( controller . ControllerContext , vr . ViewName , vr . MasterName ) ;
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
if ( viewEngineResult . View = = null )
{
throw new InvalidOperationException ( "Could not find the view " + vr . ViewName + ", the following locations were searched: " + Environment . NewLine + string . Join ( Environment . NewLine , viewEngineResult . SearchedLocations ) ) ;
}
2012-09-29 08:49:21 +07:00
2013-03-11 20:11:11 +06:00
result . View = viewEngineResult . View ;
}
}
2012-07-20 01:04:35 +06:00
}
}