From 31dc1b2cdbcf52ea92b9635b56b35b8447df9d80 Mon Sep 17 00:00:00 2001 From: engern Date: Sat, 21 Nov 2015 13:20:13 +0100 Subject: [PATCH 1/4] Fixes U46340 --- .../src/common/resources/macro.resource.js | 21 ++++++------------- src/Umbraco.Web/Editors/MacroController.cs | 4 +++- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 9ba64838c9..af0d5292c6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -36,7 +36,7 @@ function macroResource($q, $http, umbRequestHelper) { * @methodOf umbraco.resources.macroResource * * @description - * Gets the result of a macro as html to display in the rich text editor + * Gets the result of a macro as html to display in the rich text editor or in the Grid * * @param {int} macroId The macro id to get parameters for * @param {int} pageId The current page id @@ -47,37 +47,28 @@ function macroResource($q, $http, umbRequestHelper) { //need to format the query string for the custom dictionary var query = "macroAlias=" + macroAlias + "&pageId=" + pageId; + var macroParams = {}; if (macroParamDictionary) { - var counter = 0; _.each(macroParamDictionary, function (val, key) { //check for null val = val ? val : ""; //need to detect if the val is a string or an object if (!angular.isString(val)) { //if it's not a string we'll send it through the json serializer - var json = angular.toJson(val); - //then we need to url encode it so that it's safe - val = encodeURIComponent(json); + val = angular.toJson(val); } - else { - //we still need to encode the string, it could contain line breaks, etc... - val = encodeURIComponent(val); - } - - query += "¯oParams[" + counter + "].key=" + key + "¯oParams[" + counter + "].value=" + val; - counter++; + macroParams[key] = val; }); } return umbRequestHelper.resourcePromise( - $http.get( + $http.post( umbRequestHelper.getApiUrl( "macroApiBaseUrl", "GetMacroResultAsHtmlForEditor", - query)), + query), JSON.stringify(macroParams)), 'Failed to retrieve macro result for macro with alias ' + macroAlias); } - }; } diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index 11fef4a25d..e14971db36 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -49,7 +49,9 @@ namespace Umbraco.Web.Editors /// /// /// - public HttpResponseMessage GetMacroResultAsHtmlForEditor(string macroAlias, int pageId, [FromUri]IDictionary macroParams) + [HttpPost] + [HttpGet] + public HttpResponseMessage GetMacroResultAsHtmlForEditor(string macroAlias, int pageId, [FromBody]IDictionary macroParams) { // note - here we should be using the cache, provided that the preview content is in the cache... From 54ab26e2ed61864ff8a26c60f5c80a2d3c6640fa Mon Sep 17 00:00:00 2001 From: engern Date: Sat, 21 Nov 2015 14:00:58 +0100 Subject: [PATCH 2/4] Simplifying thge code even further Realized that we don't need to convert the exisitng dictionary to a new dictionary. --- .../src/common/resources/macro.resource.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index af0d5292c6..e4201c6d3e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -45,28 +45,14 @@ function macroResource($q, $http, umbRequestHelper) { */ getMacroResultAsHtmlForEditor: function (macroAlias, pageId, macroParamDictionary) { - //need to format the query string for the custom dictionary var query = "macroAlias=" + macroAlias + "&pageId=" + pageId; - var macroParams = {}; - if (macroParamDictionary) { - _.each(macroParamDictionary, function (val, key) { - //check for null - val = val ? val : ""; - //need to detect if the val is a string or an object - if (!angular.isString(val)) { - //if it's not a string we'll send it through the json serializer - val = angular.toJson(val); - } - macroParams[key] = val; - }); - } return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( "macroApiBaseUrl", "GetMacroResultAsHtmlForEditor", - query), JSON.stringify(macroParams)), + query), JSON.stringify(macroParamDictionary)), 'Failed to retrieve macro result for macro with alias ' + macroAlias); } }; From c9f57c6ce31ccba73d4bdd4cc530fd88ccb79e01 Mon Sep 17 00:00:00 2001 From: Tommy Enger Date: Mon, 23 Nov 2015 15:52:36 +0100 Subject: [PATCH 3/4] Split Get and Post Split Get and Post into 2 separate methods to maintain backwards compability --- .../src/common/resources/macro.resource.js | 2 +- src/Umbraco.Web/Editors/MacroController.cs | 64 ++++++++++++++++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index e4201c6d3e..c8dc62fc6c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -51,7 +51,7 @@ function macroResource($q, $http, umbRequestHelper) { $http.post( umbRequestHelper.getApiUrl( "macroApiBaseUrl", - "GetMacroResultAsHtmlForEditor", + "GetMacroResultAsHtmlForEditorUsingHttpPost", query), JSON.stringify(macroParamDictionary)), 'Failed to retrieve macro result for macro with alias ' + macroAlias); } diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index e14971db36..fed4fe6805 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -49,9 +49,8 @@ namespace Umbraco.Web.Editors /// /// /// - [HttpPost] [HttpGet] - public HttpResponseMessage GetMacroResultAsHtmlForEditor(string macroAlias, int pageId, [FromBody]IDictionary macroParams) + public HttpResponseMessage GetMacroResultAsHtmlForEditor(string macroAlias, int pageId, [FromUri] IDictionary macroParams) { // note - here we should be using the cache, provided that the preview content is in the cache... @@ -83,7 +82,66 @@ namespace Umbraco.Web.Editors //the 'easiest' way might be to create an IPublishedContent manually and populate the legacy 'page' object with that //and then set the legacy parameters. - var legacyPage = new global::umbraco.page(doc); + var legacyPage = new global::umbraco.page(doc); + UmbracoContext.HttpContext.Items["pageID"] = doc.Id; + UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements; + UmbracoContext.HttpContext.Items[global::Umbraco.Core.Constants.Conventions.Url.AltTemplate] = null; + + var renderer = new UmbracoComponentRenderer(UmbracoContext); + + var result = Request.CreateResponse(); + //need to create a specific content result formatted as html since this controller has been configured + //with only json formatters. + result.Content = new StringContent( + renderer.RenderMacro(macro, macroParams, legacyPage).ToString(), + Encoding.UTF8, + "text/html"); + return result; + } + + /// + /// Gets a rendered macro as html for rendering in the rich text editor. + /// Using HTTP POST instead of GET allows for more parameters to be passed as it's not dependant on URL-length limitations like GET. + /// The method using GET is kept to maintain backwards compatibility + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage GetMacroResultAsHtmlForEditorUsingHttpPost(string macroAlias, int pageId, [FromBody]IDictionary macroParams) + { + // note - here we should be using the cache, provided that the preview content is in the cache... + + var doc = Services.ContentService.GetById(pageId); + if (doc == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + //need to get a legacy macro object - eventually we'll have a new format but nto yet + var macro = new macro(macroAlias); + if (macro == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + //if it isn't supposed to be rendered in the editor then return an empty string + if (macro.DontRenderInEditor) + { + var response = Request.CreateResponse(); + //need to create a specific content result formatted as html since this controller has been configured + //with only json formatters. + response.Content = new StringContent(string.Empty, Encoding.UTF8, "text/html"); + + return response; + } + + //because macro's are filled with insane legacy bits and pieces we need all sorts of wierdness to make them render. + //the 'easiest' way might be to create an IPublishedContent manually and populate the legacy 'page' object with that + //and then set the legacy parameters. + + var legacyPage = new global::umbraco.page(doc); UmbracoContext.HttpContext.Items["pageID"] = doc.Id; UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements; UmbracoContext.HttpContext.Items[global::Umbraco.Core.Constants.Conventions.Url.AltTemplate] = null; From de41a1f1ca0a2026a7d9023c45f69f35086692b2 Mon Sep 17 00:00:00 2001 From: Tommy Enger Date: Mon, 23 Nov 2015 16:29:09 +0100 Subject: [PATCH 4/4] Clean up the code DRY --- src/Umbraco.Web/Editors/MacroController.cs | 51 +++------------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index fed4fe6805..1364679b93 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -52,51 +52,7 @@ namespace Umbraco.Web.Editors [HttpGet] public HttpResponseMessage GetMacroResultAsHtmlForEditor(string macroAlias, int pageId, [FromUri] IDictionary macroParams) { - // note - here we should be using the cache, provided that the preview content is in the cache... - - var doc = Services.ContentService.GetById(pageId); - if (doc == null) - { - throw new HttpResponseException(HttpStatusCode.NotFound); - } - - //need to get a legacy macro object - eventually we'll have a new format but nto yet - var macro = new macro(macroAlias); - if (macro == null) - { - throw new HttpResponseException(HttpStatusCode.NotFound); - } - - //if it isn't supposed to be rendered in the editor then return an empty string - if (macro.DontRenderInEditor) - { - var response = Request.CreateResponse(); - //need to create a specific content result formatted as html since this controller has been configured - //with only json formatters. - response.Content = new StringContent(string.Empty, Encoding.UTF8, "text/html"); - - return response; - } - - //because macro's are filled with insane legacy bits and pieces we need all sorts of wierdness to make them render. - //the 'easiest' way might be to create an IPublishedContent manually and populate the legacy 'page' object with that - //and then set the legacy parameters. - - var legacyPage = new global::umbraco.page(doc); - UmbracoContext.HttpContext.Items["pageID"] = doc.Id; - UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements; - UmbracoContext.HttpContext.Items[global::Umbraco.Core.Constants.Conventions.Url.AltTemplate] = null; - - var renderer = new UmbracoComponentRenderer(UmbracoContext); - - var result = Request.CreateResponse(); - //need to create a specific content result formatted as html since this controller has been configured - //with only json formatters. - result.Content = new StringContent( - renderer.RenderMacro(macro, macroParams, legacyPage).ToString(), - Encoding.UTF8, - "text/html"); - return result; + return GetMacroResultAsHtml(macroAlias, pageId, macroParams); } /// @@ -110,6 +66,11 @@ namespace Umbraco.Web.Editors /// [HttpPost] public HttpResponseMessage GetMacroResultAsHtmlForEditorUsingHttpPost(string macroAlias, int pageId, [FromBody]IDictionary macroParams) + { + return GetMacroResultAsHtml(macroAlias, pageId, macroParams); + } + + private HttpResponseMessage GetMacroResultAsHtml(string macroAlias, int pageId, IDictionary macroParams) { // note - here we should be using the cache, provided that the preview content is in the cache...