I\'m implementing Content Security Policy headers using the following policy
Content-Security-Policy: default-src \'self\'
so will need to avoid
$('#@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)')
Yeah this isn't a good approach in general. Razor will HTML-escape by default but the context isn't simply HTML here, it's:
<script>
)so just HTML-escaping is the wrong thing - any characters that are special in the context of selectors or JS string literals (such as dot, backslash, apostrophe, line separators...) would break this statement.
Maybe that's not super-important for this specific example, assuming the result of GetFullHtmlFieldName
is always going to be something safe, but that's not a good assumption for the general case.
C# Generated JavaScript: a bit clunky and it kind of defeats some of the advantages of using a CSP
Agreed, avoid this. Getting the caching right and transferring the information from the ASP that generates the page content to the page that generates the script is typically a pain.
Also generating JavaScript is not necessarily that simple. ASP and Razor templates don't give you an automatic JS escaper. JSON encoding nearly does it, except for the niggling differences between JSON and JS (ie U+2028 and U+2029).
Hidden Form Fields
More generally, putting the information in the DOM. Hidden form fields are one way to do this; data-
attributes are another commonly-used one. Either way I strongly prefer the DOM approach.
When using hidden form fields you should probably remove the name
attribute as if they're inside a real <form>
you typically don't actually want to submit the data you were passing into JS.
This way you can inject the content into the template using normal default-on HTML escaping. If you need more structure you can always JSON-encode the data to be passed. jQuery's data()
helper will automatically JSON.parse
them for you too in that case.
<body data-mcefields="@Json.Encode(GetListOfHtmlFields())">
...
var mce_array = $('body').data('mcefields');
$.each(mce_array, function() {
var element = document.getElementById(this);
$(element).tinymce({ ... });
});
(Although... for the specific case of selecting elements to apply an HTML editor to, perhaps the simpler way would be just to use class="tinymce"
and apply with $('.tinymce').tinymce(...)
?)