using System; using System.ComponentModel; using System.Web; using System.Web.Security; using System.Xml.XPath; using Umbraco.Core; using Umbraco.Core.Dictionary; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Xml; using Umbraco.Web.Routing; using Umbraco.Web.Security; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Mvc; using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; namespace Umbraco.Web { /// /// A helper class that provides many useful methods and functionality for using Umbraco in templates /// public class UmbracoHelper : IUmbracoComponentRenderer { private static readonly HtmlStringUtilities StringUtilities = new HtmlStringUtilities(); private readonly UmbracoContext _umbracoContext; private readonly IPublishedContent _currentPage; private readonly IPublishedContentQuery _iQuery; private readonly ServiceContext _services; private readonly CacheHelper _appCache; private IUmbracoComponentRenderer _componentRenderer; private PublishedContentQuery _query; private MembershipHelper _membershipHelper; private ITagQuery _tag; private IDataTypeService _dataTypeService; private ICultureDictionary _cultureDictionary; #region Constructors /// /// Initializes a new instance of the class. /// /// For tests. internal UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, IPublishedContentQuery query, ITagQuery tagQuery, IDataTypeService dataTypeService, ICultureDictionary cultureDictionary, IUmbracoComponentRenderer componentRenderer, MembershipHelper membershipHelper, ServiceContext services, CacheHelper appCache) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (content == null) throw new ArgumentNullException(nameof(content)); if (query == null) throw new ArgumentNullException(nameof(query)); if (tagQuery == null) throw new ArgumentNullException(nameof(tagQuery)); if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService)); if (cultureDictionary == null) throw new ArgumentNullException(nameof(cultureDictionary)); if (componentRenderer == null) throw new ArgumentNullException(nameof(componentRenderer)); if (membershipHelper == null) throw new ArgumentNullException(nameof(membershipHelper)); if (services == null) throw new ArgumentNullException(nameof(services)); if (appCache == null) throw new ArgumentNullException(nameof(appCache)); _umbracoContext = umbracoContext; _tag = new TagQuery(tagQuery); _dataTypeService = dataTypeService; _cultureDictionary = cultureDictionary; _componentRenderer = componentRenderer; _membershipHelper = membershipHelper; _currentPage = content; _iQuery = query; _services = services; _appCache = appCache; } /// /// Initializes a new instance of the class. /// /// For tests - nothing is initialized. internal UmbracoHelper() { } /// /// Initializes a new instance of the class with an Umbraco context /// and a specific content item. /// /// An Umbraco context. /// A content item. /// A services context. /// An application cache helper. /// Sets the current page to the supplied content item. public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache, IPublishedContent content) : this(umbracoContext, services, appCache) { if (content == null) throw new ArgumentNullException(nameof(content)); _currentPage = content; } /// /// Initializes a new instance of the class with an Umbraco context. /// /// An Umbraco context. /// A services context. /// An application cache helper. /// Sets the current page to the context's published content request's content item. public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (services == null) throw new ArgumentNullException(nameof(services)); if (appCache == null) throw new ArgumentNullException(nameof(appCache)); _umbracoContext = umbracoContext; if (_umbracoContext.IsFrontEndUmbracoRequest) _currentPage = _umbracoContext.PublishedContentRequest.PublishedContent; _services = services; _appCache = appCache; } #endregion /// /// Gets the tag context. /// public ITagQuery TagQuery => _tag ?? (_tag = new TagQuery(_services.TagService, _iQuery ?? ContentQuery)); /// /// Gets the query context. /// public PublishedContentQuery ContentQuery => _query ?? (_query = _iQuery != null ? new PublishedContentQuery(_iQuery) : new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache)); /// /// Gets the Umbraco context. /// public UmbracoContext UmbracoContext { get { if (_umbracoContext == null) throw new NullReferenceException("UmbracoContext has not been set."); return _umbracoContext; } } /// /// Gets the membership helper. /// public MembershipHelper MembershipHelper => _membershipHelper ?? (_membershipHelper = new MembershipHelper(UmbracoContext)); /// /// Gets the url provider. /// public UrlProvider UrlProvider => UmbracoContext.UrlProvider; /// /// Gets the datatype service. /// private IDataTypeService DataTypeService => _dataTypeService ?? (_dataTypeService = _services.DataTypeService); /// /// Gets the component renderer. /// public IUmbracoComponentRenderer UmbracoComponentRenderer => _componentRenderer ?? (_componentRenderer = new UmbracoComponentRenderer(UmbracoContext)); /// /// Returns the current IPublishedContent item assigned to the UmbracoHelper /// /// /// Note that this is the assigned IPublishedContent item to the UmbracoHelper, this is not necessarily the Current IPublishedContent item /// being rendered. This IPublishedContent object is contextual to the current UmbracoHelper instance. /// /// In some cases accessing this property will throw an exception if there is not IPublishedContent assigned to the Helper /// this will only ever happen if the Helper is constructed with an UmbracoContext and it is not a front-end request /// /// Thrown if the UmbracoHelper is constructed with an UmbracoContext and it is not a front-end request public IPublishedContent AssignedContentItem { get { if (_currentPage == null) throw new InvalidOperationException("Cannot return the " + typeof(IPublishedContent).Name + " because the " + typeof(UmbracoHelper).Name + " was constructed with an " + typeof(UmbracoContext).Name + " and the current request is not a front-end request."); return _currentPage; } } /// /// Renders the template for the specified pageId and an optional altTemplateId. /// /// /// If not specified, will use the template assigned to the node /// public IHtmlString RenderTemplate(int pageId, int? altTemplateId = null) { return UmbracoComponentRenderer.RenderTemplate(pageId, altTemplateId); } #region RenderMacro /// /// Renders the macro with the specified alias. /// /// The alias. /// public IHtmlString RenderMacro(string alias) { return UmbracoComponentRenderer.RenderMacro(alias, new { }); } /// /// Renders the macro with the specified alias, passing in the specified parameters. /// /// The alias. /// The parameters. /// public IHtmlString RenderMacro(string alias, object parameters) { return UmbracoComponentRenderer.RenderMacro(alias, parameters.ToDictionary()); } /// /// Renders the macro with the specified alias, passing in the specified parameters. /// /// The alias. /// The parameters. /// public IHtmlString RenderMacro(string alias, IDictionary parameters) { return UmbracoComponentRenderer.RenderMacro(alias, parameters); } #endregion #region Dictionary /// /// Returns the dictionary value for the key specified /// /// /// public string GetDictionaryValue(string key) { return CultureDictionary[key]; } /// /// Returns the dictionary value for the key specified, and if empty returns the specified default fall back value /// /// key of dictionary item /// fall back text if dictionary item is empty - Name altText to match Umbraco.Field /// public string GetDictionaryValue(string key, string altText) { var dictionaryValue = GetDictionaryValue(key); if (String.IsNullOrWhiteSpace(dictionaryValue)) { dictionaryValue = altText; } return dictionaryValue; } /// /// Returns the ICultureDictionary for access to dictionary items /// public ICultureDictionary CultureDictionary => _cultureDictionary ?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary()); #endregion #region Membership [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Use the IsProtected method that only specifies path")] public bool IsProtected(int documentId, string path) { return IsProtected(path.EnsureEndsWith("," + documentId)); } /// /// Check if a document object is protected by the "Protect Pages" functionality in umbraco /// /// The full path of the document object to check /// True if the document object is protected public bool IsProtected(string path) { return _services.PublicAccessService.IsProtected(path); } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Use the MemberHasAccess method that only specifies path")] public bool MemberHasAccess(int nodeId, string path) { return MemberHasAccess(path.EnsureEndsWith("," + nodeId)); } /// /// Check if the current user has access to a document /// /// The full path of the document object to check /// True if the current user has access or if the current document isn't protected public bool MemberHasAccess(string path) { if (IsProtected(path)) { return MembershipHelper.IsLoggedIn() && _services.PublicAccessService.HasAccess(path, GetCurrentMember(), Roles.Provider); } return true; } /// /// Gets (or adds) the current member from the current request cache /// private MembershipUser GetCurrentMember() { return _appCache.RequestCache.GetCacheItem("UmbracoHelper.GetCurrentMember", () => { var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); return provider.GetCurrentUser(); }); } /// /// Whether or not the current member is logged in (based on the membership provider) /// /// True is the current user is logged in public bool MemberIsLoggedOn() { return MembershipHelper.IsLoggedIn(); } #endregion #region NiceUrls /// /// Returns a string with a friendly url from a node. /// IE.: Instead of having /482 (id) as an url, you can have /// /screenshots/developer/macros (spoken url) /// /// Identifier for the node that should be returned /// String with a friendly url from a node public string NiceUrl(int nodeId) { return Url(nodeId); } /// /// Gets the url of a content identified by its identifier. /// /// The content identifier. /// The url for the content. public string Url(int contentId) { return UrlProvider.GetUrl(contentId); } /// /// Gets the url of a content identified by its identifier, in a specified mode. /// /// The content identifier. /// The mode. /// The url for the content. public string Url(int contentId, UrlProviderMode mode) { return UrlProvider.GetUrl(contentId, mode); } /// /// This method will always add the domain to the path if the hostnames are set up correctly. /// /// Identifier for the node that should be returned /// String with a friendly url with full domain from a node public string NiceUrlWithDomain(int nodeId) { return UrlAbsolute(nodeId); } /// /// Gets the absolute url of a content identified by its identifier. /// /// The content identifier. /// The absolute url for the content. public string UrlAbsolute(int contentId) { return UrlProvider.GetUrl(contentId, true); } #endregion #region Member/Content/Media from Udi public IPublishedContent PublishedContent(Udi udi) { var guidUdi = udi as GuidUdi; if (guidUdi == null) return null; var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(udi.EntityType); var entityService = Current.Services.EntityService; switch (umbracoType) { case UmbracoObjectTypes.Document: return Content(guidUdi.Guid); case UmbracoObjectTypes.Media: // fixme - need to implement Media(guid)! var mediaAttempt = entityService.GetIdForKey(guidUdi.Guid, umbracoType); if (mediaAttempt.Success) return Media(mediaAttempt.Result); break; case UmbracoObjectTypes.Member: // fixme - need to implement Member(guid)! var memberAttempt = entityService.GetIdForKey(guidUdi.Guid, umbracoType); if (memberAttempt.Success) return Member(memberAttempt.Result); break; } return null; } #endregion #region Members public IPublishedContent Member(object id) { var asInt = id.TryConvertTo(); return asInt ? MembershipHelper.GetById(asInt.Result) : MembershipHelper.GetByProviderKey(id); } public IPublishedContent Member(int id) { return MembershipHelper.GetById(id); } public IPublishedContent Member(string id) { var asInt = id.TryConvertTo(); return asInt ? MembershipHelper.GetById(asInt.Result) : MembershipHelper.GetByProviderKey(id); } #endregion #region Content /// /// Gets a content item from the cache. /// /// The unique identifier, or the key, of the content item. /// The content, or null of the content item is not in the cache. public IPublishedContent Content(object id) { return ContentForObject(id); } private IPublishedContent ContentForObject(object id) { int intId; if (ConvertIdObjectToInt(id, out intId)) return ContentQuery.Content(intId); Guid guidId; if (ConvertIdObjectToGuid(id, out guidId)) return ContentQuery.Content(guidId); return null; } /// /// Gets a content item from the cache. /// /// The unique identifier of the content item. /// The content, or null of the content item is not in the cache. public IPublishedContent Content(int id) { return ContentQuery.Content(id); } /// /// Gets a content item from the cache. /// /// The key of the content item. /// The content, or null of the content item is not in the cache. public IPublishedContent Content(Guid id) { return ContentQuery.Content(id); } /// /// Gets a content item from the cache. /// /// The unique identifier, or the key, of the content item. /// The content, or null of the content item is not in the cache. public IPublishedContent Content(string id) { return ContentForObject(id); } public IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars) { return ContentQuery.ContentSingleAtXPath(xpath, vars); } /// /// Gets content items from the cache. /// /// The unique identifiers, or the keys, of the content items. /// The content items that were found in the cache. /// Does not support mixing identifiers and keys. public IEnumerable Content(params object[] ids) { return ContentForObjects(ids); } private IEnumerable ContentForObjects(IEnumerable ids) { var idsA = ids.ToArray(); IEnumerable intIds; if (ConvertIdsObjectToInts(idsA, out intIds)) return ContentQuery.Content(intIds); IEnumerable guidIds; if (ConvertIdsObjectToGuids(idsA, out guidIds)) return ContentQuery.Content(guidIds); return Enumerable.Empty(); } /// /// Gets content items from the cache. /// /// The unique identifiers of the content items. /// The content items that were found in the cache. public IEnumerable Content(params int[] ids) { return ContentQuery.Content(ids); } /// /// Gets content items from the cache. /// /// The keys of the content items. /// The content items that were found in the cache. public IEnumerable Content(params Guid[] ids) { return ContentQuery.Content(ids); } /// /// Gets content items from the cache. /// /// The unique identifiers, or the keys, of the content items. /// The content items that were found in the cache. /// Does not support mixing identifiers and keys. public IEnumerable Content(params string[] ids) { return ContentForObjects(ids); } /// /// Gets the contents corresponding to the identifiers. /// /// The content identifiers. /// The existing contents corresponding to the identifiers. /// If an identifier does not match an existing content, it will be missing in the returned value. public IEnumerable Content(IEnumerable ids) { return ContentForObjects(ids); } /// /// Gets the contents corresponding to the identifiers. /// /// The content identifiers. /// The existing contents corresponding to the identifiers. /// If an identifier does not match an existing content, it will be missing in the returned value. public IEnumerable Content(IEnumerable ids) { return ContentForObjects(ids); } /// /// Gets the contents corresponding to the identifiers. /// /// The content identifiers. /// The existing contents corresponding to the identifiers. /// If an identifier does not match an existing content, it will be missing in the returned value. public IEnumerable Content(IEnumerable ids) { return ContentQuery.Content(ids); } public IEnumerable ContentAtXPath(string xpath, params XPathVariable[] vars) { return ContentQuery.ContentAtXPath(xpath, vars); } public IEnumerable ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) { return ContentQuery.ContentAtXPath(xpath, vars); } public IEnumerable ContentAtRoot() { return ContentQuery.ContentAtRoot(); } private static bool ConvertIdObjectToInt(object id, out int intId) { var s = id as string; if (s != null) { return int.TryParse(s, out intId); } if (id is int) { intId = (int) id; return true; } intId = default(int); return false; } private static bool ConvertIdObjectToGuid(object id, out Guid guidId) { var s = id as string; if (s != null) { return Guid.TryParse(s, out guidId); } if (id is Guid) { guidId = (Guid) id; return true; } guidId = default(Guid); return false; } private static bool ConvertIdsObjectToInts(IEnumerable ids, out IEnumerable intIds) { var list = new List(); intIds = null; foreach (var id in ids) { int intId; if (ConvertIdObjectToInt(id, out intId)) list.Add(intId); else return false; // if one of them is not an int, fail } intIds = list; return true; } private static bool ConvertIdsObjectToGuids(IEnumerable ids, out IEnumerable guidIds) { var list = new List(); guidIds = null; foreach (var id in ids) { Guid guidId; if (ConvertIdObjectToGuid(id, out guidId)) list.Add(guidId); else return false; // if one of them is not a guid, fail } guidIds = list; return true; } #endregion #region Media /// /// Overloaded method accepting an 'object' type /// /// /// /// /// We accept an object type because GetPropertyValue now returns an 'object', we still want to allow people to pass /// this result in to this method. /// This method will throw an exception if the value is not of type int or string. /// public IPublishedContent Media(object id) { return MediaForObject(id); } private IPublishedContent MediaForObject(object id) { int intId; if (ConvertIdObjectToInt(id, out intId)) return ContentQuery.Media(intId); //Guid guidId; //if (ConvertIdObjectToGuid(id, out guidId)) // return ContentQuery.Media(guidId); return null; } public IPublishedContent Media(int id) { return ContentQuery.Media(id); } public IPublishedContent Media(string id) { return MediaForObject(id); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(params object[] ids) { return MediaForObjects(ids); } private IEnumerable MediaForObjects(IEnumerable ids) { var idsA = ids.ToArray(); IEnumerable intIds; if (ConvertIdsObjectToInts(idsA, out intIds)) return ContentQuery.Media(intIds); //IEnumerable guidIds; //if (ConvertIdsObjectToGuids(idsA, out guidIds)) // return ContentQuery.Media(guidIds); return Enumerable.Empty(); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(params int[] ids) { return ContentQuery.Media(ids); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(params string[] ids) { return MediaForObjects(ids); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(IEnumerable ids) { return MediaForObjects(ids); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(IEnumerable ids) { return ContentQuery.Media(ids); } /// /// Gets the medias corresponding to the identifiers. /// /// The media identifiers. /// The existing medias corresponding to the identifiers. /// If an identifier does not match an existing media, it will be missing in the returned value. public IEnumerable Media(IEnumerable ids) { return MediaForObjects(ids); } public IEnumerable MediaAtRoot() { return ContentQuery.MediaAtRoot(); } #endregion #region Search /// /// Searches content /// /// /// /// /// public IEnumerable Search(string term, bool useWildCards = true, string searchProvider = null) { return ContentQuery.Search(term, useWildCards, searchProvider); } /// /// Searhes content /// /// /// /// public IEnumerable Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) { return ContentQuery.Search(criteria, searchProvider); } #endregion #region Strings /// /// Replaces text line breaks with html line breaks /// /// The text. /// The text with text line breaks replaced with html linebreaks (
)
public string ReplaceLineBreaksForHtml(string text) { return StringUtilities.ReplaceLineBreaksForHtml(text); } /// /// Returns an MD5 hash of the string specified /// /// The text to create a hash from /// Md5 has of the string public string CreateMd5Hash(string text) { return text.ToMd5(); } /// /// Strips all html tags from a given string, all contents of the tags will remain. /// public HtmlString StripHtml(IHtmlString html, params string[] tags) { return StripHtml(html.ToHtmlString(), tags); } /// /// Strips all html tags from a given string, all contents of the tags will remain. /// public HtmlString StripHtml(string html, params string[] tags) { return StringUtilities.StripHtmlTags(html, tags); } /// /// Will take the first non-null value in the collection and return the value of it. /// public string Coalesce(params object[] args) { return StringUtilities.Coalesce(args); } /// /// Will take the first non-null value in the collection and return the value of it. /// public string Concatenate(params object[] args) { return StringUtilities.Concatenate(args); } /// /// Joins any number of int/string/objects into one string and seperates them with the string seperator parameter. /// public string Join(string separator, params object[] args) { return StringUtilities.Join(separator, args); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(IHtmlString html, int length) { return Truncate(html.ToHtmlString(), length, true, false); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis) { return Truncate(html.ToHtmlString(), length, addElipsis, false); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent) { return Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(string html, int length) { return Truncate(html, length, true, false); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(string html, int length, bool addElipsis) { return Truncate(html, length, addElipsis, false); } /// /// Truncates a string to a given length, can add a elipsis at the end (...). Method checks for open html tags, and makes sure to close them /// public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent) { return StringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent); } #endregion #region If /// /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. /// public HtmlString If(bool test, string valueIfTrue, string valueIfFalse) { return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse); } /// /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. /// public HtmlString If(bool test, string valueIfTrue) { return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty); } #endregion #region Prevalues public string GetPreValueAsString(int id) { return DataTypeService.GetPreValueAsString(id); } #endregion #region canvasdesigner [Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")] public IHtmlString EnableCanvasDesigner() { return EnableCanvasDesigner(string.Empty, string.Empty); } [Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")] public IHtmlString EnableCanvasDesigner(string canvasdesignerConfigPath) { return EnableCanvasDesigner(canvasdesignerConfigPath, string.Empty); } [Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")] public IHtmlString EnableCanvasDesigner(string canvasdesignerConfigPath, string canvasdesignerPalettesPath) { var html = CreateHtmlHelper(""); var urlHelper = new UrlHelper(UmbracoContext.HttpContext.Request.RequestContext); return html.EnableCanvasDesigner(urlHelper, UmbracoContext, canvasdesignerConfigPath, canvasdesignerPalettesPath); } [Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")] private HtmlHelper CreateHtmlHelper(object model) { var cc = new ControllerContext { RequestContext = UmbracoContext.HttpContext.Request.RequestContext }; var viewContext = new ViewContext(cc, new FakeView(), new ViewDataDictionary(model), new TempDataDictionary(), new StringWriter()); var htmlHelper = new HtmlHelper(viewContext, new ViewPage()); return htmlHelper; } [Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")] private class FakeView : IView { public void Render(ViewContext viewContext, TextWriter writer) { } } #endregion /// /// This is used in methods like BeginUmbracoForm and SurfaceAction to generate an encrypted string which gets submitted in a request for which /// Umbraco can decrypt during the routing process in order to delegate the request to a specific MVC Controller. /// /// /// /// /// /// internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null) { Mandate.ParameterNotNullOrEmpty(controllerName, "controllerName"); Mandate.ParameterNotNullOrEmpty(controllerAction, "controllerAction"); Mandate.ParameterNotNull(area, "area"); //need to create a params string as Base64 to put into our hidden field to use during the routes var surfaceRouteParams = $"c={HttpUtility.UrlEncode(controllerName)}&a={HttpUtility.UrlEncode(controllerAction)}&ar={area}"; //checking if the additional route values is already a dictionary and convert to querystring string additionalRouteValsAsQuery; if (additionalRouteVals != null) { var additionalRouteValsAsDictionary = additionalRouteVals as Dictionary; if (additionalRouteValsAsDictionary != null) additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); else additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); } else additionalRouteValsAsQuery = null; if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false) surfaceRouteParams += "&" + additionalRouteValsAsQuery; return surfaceRouteParams.EncryptWithMachineKey(); } } }