2012-09-05 09:35:24 +07:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2012-09-26 13:42:03 +07:00
using System.Linq ;
2012-09-05 09:35:24 +07:00
using System.Text ;
2012-10-31 11:36:22 +06:00
using System.Web ;
2012-09-05 09:35:24 +07:00
using System.Web.Mvc ;
using System.Web.Mvc.Html ;
using Umbraco.Core ;
2012-09-27 08:30:35 +07:00
using Umbraco.Core.Dynamics ;
2012-09-26 13:42:03 +07:00
using Umbraco.Web.Mvc ;
2012-09-05 09:35:24 +07:00
using umbraco ;
2012-10-31 11:36:22 +06:00
using umbraco.cms.businesslogic.member ;
2012-09-05 09:35:24 +07:00
namespace Umbraco.Web
{
/// <summary>
/// HtmlHelper extensions for use in templates
/// </summary>
public static class HtmlHelperRenderExtensions
{
2012-10-31 11:36:22 +06:00
public static IHtmlString CachedPartial (
this HtmlHelper htmlHelper ,
string partialViewName ,
object model ,
2012-10-31 11:46:02 +06:00
int cachedSeconds ,
2012-10-31 11:36:22 +06:00
bool cacheByPage = false ,
bool cacheByMember = false ,
ViewDataDictionary viewData = null )
{
var cacheKey = new StringBuilder ( partialViewName ) ;
if ( cacheByPage )
{
if ( UmbracoContext . Current = = null )
{
throw new InvalidOperationException ( "Cannot cache by page if the UmbracoContext has not been initialized, this parameter can only be used in the context of an Umbraco request" ) ;
}
cacheKey . AppendFormat ( "{0}-" , UmbracoContext . Current . PageId ) ;
}
if ( cacheByMember )
{
var currentMember = Member . GetCurrentMember ( ) ;
cacheKey . AppendFormat ( "m{0}-" , currentMember = = null ? 0 : currentMember . Id ) ;
}
2012-10-31 11:46:02 +06:00
return ApplicationContext . Current . ApplicationCache . CachedPartialView ( htmlHelper , partialViewName , model , cachedSeconds , cacheKey . ToString ( ) , viewData ) ;
2012-10-31 11:36:22 +06:00
}
2012-09-27 08:30:35 +07:00
public static MvcHtmlString EditorFor < T > ( this HtmlHelper htmlHelper , string templateName = "" , string htmlFieldName = "" , object additionalViewData = null )
where T : new ( )
{
var model = new T ( ) ;
var typedHelper = new HtmlHelper < T > (
htmlHelper . ViewContext . CopyWithModel ( model ) ,
htmlHelper . ViewDataContainer . CopyWithModel ( model ) ) ;
return typedHelper . EditorFor ( x = > model , templateName , htmlFieldName , additionalViewData ) ;
}
/// <summary>
/// A validation summary that lets you pass in a prefix so that the summary only displays for elements
/// containing the prefix. This allows you to have more than on validation summary on a page.
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="prefix"></param>
/// <param name="excludePropertyErrors"></param>
/// <param name="message"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcHtmlString ValidationSummary ( this HtmlHelper htmlHelper ,
string prefix = "" ,
bool excludePropertyErrors = false ,
string message = "" ,
IDictionary < string , object > htmlAttributes = null )
{
if ( prefix . IsNullOrWhiteSpace ( ) )
{
return htmlHelper . ValidationSummary ( excludePropertyErrors , message , htmlAttributes ) ;
}
//if there's a prefix applied, we need to create a new html helper with a filtered ModelState collection so that it only looks for
//specific model state with the prefix.
var filteredHtmlHelper = new HtmlHelper ( htmlHelper . ViewContext , htmlHelper . ViewDataContainer . FilterContainer ( prefix ) ) ;
return filteredHtmlHelper . ValidationSummary ( excludePropertyErrors , message , htmlAttributes ) ;
}
#region BeginUmbracoForm
2012-09-05 09:35:24 +07:00
/// <summary>
/// Used for rendering out the Form for BeginUmbracoForm
/// </summary>
internal class UmbracoForm : MvcForm
{
2012-09-26 13:42:03 +07:00
/// <summary>
/// Creates an UmbracoForm
/// </summary>
/// <param name="viewContext"></param>
/// <param name="surfaceController"></param>
/// <param name="surfaceAction"></param>
/// <param name="area"></param>
/// <param name="additionalRouteVals"></param>
2012-09-05 09:35:24 +07:00
public UmbracoForm (
ViewContext viewContext ,
string surfaceController ,
string surfaceAction ,
2012-09-27 08:30:35 +07:00
string area ,
2012-09-05 09:35:24 +07:00
object additionalRouteVals = null )
: base ( viewContext )
{
//need to create a params string as Base64 to put into our hidden field to use during the routes
2012-09-26 13:42:03 +07:00
var surfaceRouteParams = string . Format ( "c={0}&a={1}&ar={2}" ,
2012-09-27 08:30:35 +07:00
viewContext . HttpContext . Server . UrlEncode ( surfaceController ) ,
viewContext . HttpContext . Server . UrlEncode ( surfaceAction ) ,
area ) ;
2012-09-05 09:35:24 +07:00
var additionalRouteValsAsQuery = additionalRouteVals . ToDictionary < object > ( ) . ToQueryString ( ) ;
if ( ! additionalRouteValsAsQuery . IsNullOrWhiteSpace ( ) )
surfaceRouteParams = "&" + additionalRouteValsAsQuery ;
_base64String = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( surfaceRouteParams ) ) ;
_textWriter = viewContext . Writer ;
}
private bool _disposed ;
private readonly string _base64String ;
private readonly TextWriter _textWriter ;
protected override void Dispose ( bool disposing )
{
if ( this . _disposed )
return ;
this . _disposed = true ;
//write out the hidden surface form routes
_textWriter . Write ( "<input name='uformpostroutevals' type='hidden' value='" + _base64String + "' />" ) ;
base . Dispose ( disposing ) ;
}
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName )
{
return html . BeginUmbracoForm ( action , controllerName , null , new Dictionary < string , object > ( ) ) ;
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
2012-09-26 13:42:03 +07:00
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName , object additionalRouteVals )
2012-09-05 09:35:24 +07:00
{
return html . BeginUmbracoForm ( action , controllerName , additionalRouteVals , new Dictionary < string , object > ( ) ) ;
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName ,
2012-09-27 08:30:35 +07:00
object additionalRouteVals ,
object htmlAttributes )
2012-09-05 09:35:24 +07:00
{
return html . BeginUmbracoForm ( action , controllerName , additionalRouteVals , htmlAttributes . ToDictionary < object > ( ) ) ;
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName ,
2012-09-27 08:30:35 +07:00
object additionalRouteVals ,
IDictionary < string , object > htmlAttributes )
2012-09-05 09:35:24 +07:00
{
2012-09-26 13:42:03 +07:00
Mandate . ParameterNotNullOrEmpty ( action , "action" ) ;
2012-09-27 08:30:35 +07:00
Mandate . ParameterNotNullOrEmpty ( controllerName , "controllerName" ) ;
2012-09-26 13:42:03 +07:00
2012-09-25 13:09:59 +07:00
var area = Umbraco . Core . Configuration . GlobalSettings . UmbracoMvcArea ;
2012-09-26 13:42:03 +07:00
return html . BeginUmbracoForm ( action , controllerName , area , additionalRouteVals , htmlAttributes ) ;
}
2012-09-05 09:35:24 +07:00
2012-09-26 13:42:03 +07:00
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="surfaceType">The surface controller to route to</param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , Type surfaceType )
{
return html . BeginUmbracoForm ( action , surfaceType , null , new Dictionary < string , object > ( ) ) ;
2012-09-05 09:35:24 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
2012-09-26 13:42:03 +07:00
/// <typeparam name="T"></typeparam>
2012-09-05 09:35:24 +07:00
/// <param name="html"></param>
/// <param name="action"></param>
/// <returns></returns>
2012-09-26 13:42:03 +07:00
public static MvcForm BeginUmbracoForm < T > ( this HtmlHelper html , string action )
2012-09-27 08:30:35 +07:00
where T : SurfaceController
2012-09-05 09:35:24 +07:00
{
2012-09-27 08:30:35 +07:00
return html . BeginUmbracoForm ( action , typeof ( T ) ) ;
2012-09-05 09:35:24 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
2012-09-26 13:42:03 +07:00
/// <param name="surfaceType">The surface controller to route to</param>
2012-09-05 09:35:24 +07:00
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
2012-09-26 13:42:03 +07:00
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , Type surfaceType ,
2012-09-27 08:30:35 +07:00
object additionalRouteVals )
2012-09-05 09:35:24 +07:00
{
2012-09-26 13:42:03 +07:00
return html . BeginUmbracoForm ( action , surfaceType , additionalRouteVals , new Dictionary < string , object > ( ) ) ;
2012-09-05 09:35:24 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
2012-09-26 13:42:03 +07:00
/// <typeparam name="T"></typeparam>
2012-09-05 09:35:24 +07:00
/// <param name="html"></param>
/// <param name="action"></param>
2012-09-26 13:42:03 +07:00
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm < T > ( this HtmlHelper html , string action , object additionalRouteVals )
where T : SurfaceController
{
2012-09-27 08:30:35 +07:00
return html . BeginUmbracoForm ( action , typeof ( T ) , additionalRouteVals ) ;
2012-09-26 13:42:03 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="surfaceType">The surface controller to route to</param>
2012-09-05 09:35:24 +07:00
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
2012-09-26 13:42:03 +07:00
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , Type surfaceType ,
2012-09-27 08:30:35 +07:00
object additionalRouteVals ,
object htmlAttributes )
2012-09-05 09:35:24 +07:00
{
2012-09-26 13:42:03 +07:00
return html . BeginUmbracoForm ( action , surfaceType , additionalRouteVals , htmlAttributes . ToDictionary < object > ( ) ) ;
2012-09-05 09:35:24 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
2012-09-26 13:42:03 +07:00
/// <typeparam name="T"></typeparam>
2012-09-05 09:35:24 +07:00
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
2012-09-27 08:30:35 +07:00
public static MvcForm BeginUmbracoForm < T > ( this HtmlHelper html , string action ,
object additionalRouteVals ,
object htmlAttributes )
where T : SurfaceController
2012-09-26 13:42:03 +07:00
{
2012-09-27 08:30:35 +07:00
return html . BeginUmbracoForm ( action , typeof ( T ) , additionalRouteVals , htmlAttributes ) ;
2012-09-26 13:42:03 +07:00
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="surfaceType">The surface controller to route to</param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , Type surfaceType ,
2012-09-27 08:30:35 +07:00
object additionalRouteVals ,
IDictionary < string , object > htmlAttributes )
{
2012-09-26 13:42:03 +07:00
Mandate . ParameterNotNullOrEmpty ( action , "action" ) ;
Mandate . ParameterNotNull ( surfaceType , "surfaceType" ) ;
var area = Umbraco . Core . Configuration . GlobalSettings . UmbracoMvcArea ;
var surfaceController = SurfaceControllerResolver . Current . SurfaceControllers
. SingleOrDefault ( x = > x . Metadata . ControllerType = = surfaceType ) ;
if ( surfaceController = = null )
throw new InvalidOperationException ( "Could not find the surface controller of type " + surfaceType . FullName ) ;
if ( ! surfaceController . Metadata . AreaName . IsNullOrWhiteSpace ( ) )
{
//set the area to the plugin area
2012-09-27 08:30:35 +07:00
area = surfaceController . Metadata . AreaName ;
2012-09-26 13:42:03 +07:00
}
return html . BeginUmbracoForm ( action , surfaceController . Metadata . ControllerName , area , additionalRouteVals , htmlAttributes ) ;
}
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
2012-09-27 08:30:35 +07:00
public static MvcForm BeginUmbracoForm < T > ( this HtmlHelper html , string action ,
object additionalRouteVals ,
IDictionary < string , object > htmlAttributes )
where T : SurfaceController
2012-09-26 13:42:03 +07:00
{
2012-09-27 08:30:35 +07:00
return html . BeginUmbracoForm ( action , typeof ( T ) , additionalRouteVals , htmlAttributes ) ;
2012-09-26 13:42:03 +07:00
}
2012-09-28 08:08:36 +07:00
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="area"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName , string area )
{
return html . BeginUmbracoForm ( action , controllerName , area , null , new Dictionary < string , object > ( ) ) ;
}
2012-09-26 13:42:03 +07:00
/// <summary>
/// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="area"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcForm BeginUmbracoForm ( this HtmlHelper html , string action , string controllerName , string area ,
object additionalRouteVals ,
IDictionary < string , object > htmlAttributes )
2012-09-05 09:35:24 +07:00
{
2012-09-26 13:42:03 +07:00
Mandate . ParameterNotNullOrEmpty ( area , "area" ) ;
Mandate . ParameterNotNullOrEmpty ( action , "action" ) ;
Mandate . ParameterNotNullOrEmpty ( controllerName , "controllerName" ) ;
2012-10-26 02:55:57 +05:00
var formAction = UmbracoContext . Current . OriginalRequestUrl . ToString ( ) ;
2012-09-26 13:42:03 +07:00
return html . RenderForm ( formAction , FormMethod . Post , htmlAttributes , controllerName , action , area , additionalRouteVals ) ;
2012-09-05 09:35:24 +07:00
}
/// <summary>
/// This renders out the form for us
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="formAction"></param>
/// <param name="method"></param>
/// <param name="htmlAttributes"></param>
/// <param name="surfaceController"></param>
/// <param name="surfaceAction"></param>
2012-09-26 13:42:03 +07:00
/// <param name="area"></param>
2012-09-05 09:35:24 +07:00
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
/// <remarks>
/// This code is pretty much the same as the underlying MVC code that writes out the form
/// </remarks>
private static MvcForm RenderForm ( this HtmlHelper htmlHelper ,
2012-09-27 08:30:35 +07:00
string formAction ,
FormMethod method ,
IDictionary < string , object > htmlAttributes ,
string surfaceController ,
string surfaceAction ,
string area ,
object additionalRouteVals = null )
2012-09-05 09:35:24 +07:00
{
2012-10-02 21:19:21 +05:00
//ensure that the multipart/form-data is added to the html attributes
if ( ! htmlAttributes . ContainsKey ( "enctype" ) )
{
htmlAttributes . Add ( "enctype" , "multipart/form-data" ) ;
}
2012-09-05 09:35:24 +07:00
var tagBuilder = new TagBuilder ( "form" ) ;
tagBuilder . MergeAttributes ( htmlAttributes ) ;
// action is implicitly generated, so htmlAttributes take precedence.
tagBuilder . MergeAttribute ( "action" , formAction ) ;
// method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder . MergeAttribute ( "method" , HtmlHelper . GetFormMethodString ( method ) , true ) ;
var traditionalJavascriptEnabled = htmlHelper . ViewContext . ClientValidationEnabled & & ! htmlHelper . ViewContext . UnobtrusiveJavaScriptEnabled ;
if ( traditionalJavascriptEnabled )
{
// forms must have an ID for client validation
tagBuilder . GenerateId ( "form" + Guid . NewGuid ( ) . ToString ( "N" ) ) ;
}
htmlHelper . ViewContext . Writer . Write ( tagBuilder . ToString ( TagRenderMode . StartTag ) ) ;
//new UmbracoForm:
2012-09-26 13:42:03 +07:00
var theForm = new UmbracoForm ( htmlHelper . ViewContext , surfaceController , surfaceAction , area , additionalRouteVals ) ;
2012-09-05 09:35:24 +07:00
if ( traditionalJavascriptEnabled )
{
htmlHelper . ViewContext . FormContext . FormId = tagBuilder . Attributes [ "id" ] ;
}
return theForm ;
}
2012-09-27 08:30:35 +07:00
#endregion
#region Wrap
public static HtmlTagWrapper Wrap ( this HtmlHelper html , string tag , string innerText , params IHtmlTagWrapper [ ] children )
{
var item = html . Wrap ( tag , innerText , ( object ) null ) ;
foreach ( var child in children )
{
item . AddChild ( child ) ;
}
return item ;
}
public static HtmlTagWrapper Wrap ( this HtmlHelper html , string tag , object inner , object anonymousAttributes , params IHtmlTagWrapper [ ] children )
{
string innerText = null ;
if ( inner ! = null & & inner . GetType ( ) ! = typeof ( DynamicNull ) )
{
innerText = string . Format ( "{0}" , inner ) ;
}
var item = html . Wrap ( tag , innerText , anonymousAttributes ) ;
foreach ( var child in children )
{
item . AddChild ( child ) ;
}
return item ;
}
public static HtmlTagWrapper Wrap ( this HtmlHelper html , string tag , object inner )
{
string innerText = null ;
if ( inner ! = null & & inner . GetType ( ) ! = typeof ( DynamicNull ) )
{
innerText = string . Format ( "{0}" , inner ) ;
}
return html . Wrap ( tag , innerText , ( object ) null ) ;
}
public static HtmlTagWrapper Wrap ( this HtmlHelper html , string tag , string innerText , object anonymousAttributes , params IHtmlTagWrapper [ ] children )
{
var wrap = new HtmlTagWrapper ( tag ) ;
if ( anonymousAttributes ! = null )
{
wrap . ReflectAttributesFromAnonymousType ( anonymousAttributes ) ;
}
if ( ! string . IsNullOrWhiteSpace ( innerText ) )
{
wrap . AddChild ( new HtmlTagWrapperTextNode ( innerText ) ) ;
}
foreach ( var child in children )
{
wrap . AddChild ( child ) ;
}
return wrap ;
}
public static HtmlTagWrapper Wrap ( this HtmlHelper html , bool visible , string tag , string innerText , object anonymousAttributes , params IHtmlTagWrapper [ ] children )
{
var item = html . Wrap ( tag , innerText , anonymousAttributes , children ) ;
item . Visible = visible ;
foreach ( var child in children )
{
item . AddChild ( child ) ;
}
return item ;
}
#endregion
2012-09-05 09:35:24 +07:00
}
}