I'm looking for a way to write a value in my razor view, without encoding it, AND without using the Html Helper.
I'm rendering the view in a hybrid website, where I parse my View programmatically, like this:
string html = "<html>#("Write something <strong>unencoded</strong>"</html>")
html = Razor.Parse<TModel>(html, model);
So essentially, my html variable contains a template containing razor c# code. Because I am compiling my view like this, I have no access to the Html helper (the accepted answer in this post implies this is indeed the case: How to render a Razor View to a string in ASP.NET MVC 3?)
However, my html variable also contains a statement like this:
#Html.Raw("<strong>This should be printed unencoded</strong>")
This does not work but gives "Html is not available in this context".
How can I achieve the same behavior? Using Response.Write gives the exact same error.
Are there any other ways?
Note: this is a hybrid website, containing both classic ASP webforms and some newer Web API and MVC stuff. The View I'm using is NOT accessed through conventional MVC ways.
HtmlString type of string should work for you.
Represents an HTML-encoded string that should not be encoded again.
Sample with creating such string inline (normally you'd have such values in Model set by controler):
#(new HtmlString("<strong>This should be printed unencoded</strong>"))
It took me a while to figure out, but this is the final solution (which works for me, but has some security implications, so do read on!)
Compile your view like this
var config = new TemplateServiceConfiguration();
config.EncodedStringFactory = new RawStringFactory();
var service = RazorEngineService.Create(config);
html = service.RunCompile(html, "templateNameInTheCache", null, model);
As you can see, I employed the RawStringFactory to make sure no HTML at all gets encoded. Of course, MVC automatically encodes HTML as a safety precaution, so doing this isn't very safe. Only do this if you're 100% sure that all of the output in the entire Razor view is safe!
Related
I hear that using HTML.Raw in Razor views is not recommended, and if so I have a problem.
I am using Entity Framework for interacting with my SQL DB. Also I am using SummerNote as an editor for the front end.
Now my view code is in #{ } block, which I believe does some encoding/decoding.
The scenario is that the user inputs some text in the SummerNote editor and applies some formatting (e.g making a word bold) and clicks saves. This will generate an HTML string and passes it to my controller:
<p>Test <b>string </b>with formatting.</p>
In the controller, I use HTML encode to encode:
customerData.Description = HttpUtility.HtmlEncode(summerNoteFieldData);
And then send it to DB. It looks like the following in DB:
<p>Test <b>string </b>with formatting.</p>
Then in the view when presenting it, I do:
<div class="summernote">#Html.Raw(#HttpUtility.HtmlDecode(#Model))</div>
So if I remove the Html.Raw, then I will see the above HTML string rather than formatted one.
Is this the safe and right way to go about this? Can it be improved?
Thank you for any help.
You should HTML encode as you print in your view (using #Model).
Do not encode or decode anywhere else; do not store encoded content in your database.
Create a default ASP.NET Core 2 MVC project normally, then modify the action a little:
public IActionResult About()
{
ViewData["Message"] = "This is Chinese[中文]";
return View();
}
And this is the view (About.cshtml):
<h3>#ViewData["Message"]</h3>
<h3>这也是中文</h3>
This is the output result in browser:
<h3>This is Chinese[中文]</h3>
<h3>这也是中文</h3>
I found that the Chinese text rendered by the '#' sign is html unicode escaped. The question is how to stop the '#' sign to escape my text?
According to this article:
By default encoders use a safe list limited to the Basic Latin Unicode
range and encode all characters outside of that range as their
character code equivalents. This behavior also affects Razor TagHelper
and HtmlHelper rendering as it will use the encoders to output your
strings.
The article also provides a proper way to customize default html encoder. Add following registration to Startup.ConfigureServices method:
services.AddSingleton<HtmlEncoder>(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs }));
Here is result html code after this adjustment:
<h3>This is Chinese[中文]</h3>
<h3>这也是中文</h3>
Issue:
DotNet Core Controller is returning HTML that is not being rendered correctly because the HTML is being ESCAPED.
Caveat: It should be noted the 'auto escaping' performed by the framework is for safety issues to avoid unwanted or dangerious html being injected.
Answer:
#Html.Raw(ViewData["Message"])
Rational
When Razor calls custom functions that create HTML, the HTML that is returned is typically automatically escaped. This is by design and is not uncommon to many frameworks (like Rails). Anyway, the OUTPUT that custom function returns must be rendered as RAW.
I have a controller which generates a string containing html markup. When it displays on views, it is displayed as a simple string containing all tags.
I tried to use an Html helper to encode/decode to display it properly, but it is not working.
string str= "seeker has applied to Job floated by you.</br>";
On my views,
#Html.Encode(str)
You are close you want to use #Html.Raw(str)
#Html.Encode takes strings and ensures that all the special characters are handled properly. These include characters like spaces.
You should be using IHtmlString instead:
IHtmlString str = new HtmlString("seeker has applied to Job floated by you.</br>");
Whenever you have model properties or variables that need to hold HTML, I feel this is generally a better practice. First of all, it is a bit cleaner. For example:
#Html.Raw(str)
Compared to:
#str
Also, I also think it's a bit safer vs. using #Html.Raw(), as the concern of whether your data is HTML is kept in your controller. In an environment where you have front-end vs. back-end developers, your back-end developers may be more in tune with what data can hold HTML values, thus keeping this concern in the back-end (controller).
I generally try to avoid using Html.Raw() whenever possible.
One other thing worth noting, is I'm not sure where you're assigning str, but a few things that concern me with how you may be implementing this.
First, this should be done in a controller, regardless of your solution (IHtmlString or Html.Raw). You should avoid any logic like this in your view, as it doesn't really belong there.
Additionally, you should be using your ViewModel for getting values to your view (and again, ideally using IHtmlString as the property type). Seeing something like #Html.Encode(str) is a little concerning, unless you were doing this just to simplify your example.
you can use
#Html.Raw(str)
See MSDN for more
Returns markup that is not HTML encoded.
This method wraps HTML markup using the IHtmlString class, which
renders unencoded HTML.
I had a similar problem with HTML input fields in MVC. The web paged only showed the first keyword of the field.
Example: input field: "The quick brown fox" Displayed value: "The"
The resolution was to put the variable in quotes in the value statement as follows:
<input class="ParmInput" type="text" id="respondingRangerUnit" name="respondingRangerUnit"
onchange="validateInteger(this.value)" value="#ViewBag.respondingRangerUnit">
I had a similar problem recently, and google landed me here, so I put this answer here in case others land here as well, for completeness.
I noticed that when I had badly formatted html, I was actually having all my html tags stripped out, with just the non-tag content remaining. I particularly had a table with a missing opening table tag, and then all my html tags from the entire string where ripped out completely.
So, if the above doesn't work, and you're still scratching your head, then also check you html for being valid.
I notice even after I got it working, MVC was adding tbody tags where I had none. This tells me there is clean up happening (MVC 5), and that when it can't happen, it strips out all/some tags.
How can I validate Razor template, which is used to render mail template.
string template = #"
My template
#if (Model.Condition { <span>is true</spaM> }"
I made two mistakes: missing closing bracket and wrong closing tag.
I need to validate it and known what should I fix (the best is to known in which line). I would like to use native Razor methods.
If I understand correctly, you want to be notified that the code you've written in the Template is invalid HTML.
If so, I'm afraid there is no easy way. The Template is purely producing text that you specify to go out to the response.
It may not even be HTML - could be JavaScript or a number of other outputs - it's just a string of text.
You may have a Template that produces the start of a table, another that produces the body, and another that produces the footer and end table tags. Each of these would produce invalid HTML on their own, but output one after the other would produce a valid HTML table. (That's a lot of produces there - sorry).
What would make it invalid is the parser of the HTML - i.e. the browser. You would only be able to validate your Template output when it is in a complete document that can then be parsed.
You mean ?
#{
string template = Model.Condition ? "My template <span>is true</span>" : "";
}
string MyString = string.empty;
#if(Model.Condition)
{
MyString ="<span>"+ "is true"+"</span>";
}
I have purposfully (for testing) assigned the following variable in WebMatrix C#:
string val = "<script type='text/javascript'>alert('XSS Vector')</script>";
Later in the page I have used razor to write that value directly to the page.
<p>
#val
</p>
It writes the text, but in a safe manner (i.e., no alert scripts run)
This, coupled with the fact that if 'val' contains an html entity (e.g., <) it also writes exactly "<" and not "<" as I would expect the page to render.
Is this because C# runs first, then html is rendered?
More importantly, is using razor in this fashion a suitable replacement for html encoding, when used like this?
The #Variable syntax will HtmlEncode any text you pass to it; hence you seeing literally what you set to the string value. You are correct in that this is for XSS protection. It is part of Razor that does this; the #Variable syntax itself.
So basically, using the #Variable syntax is not so much a 'replacement' for Html Encoding; it is HTML encoding.
Related: If you ever want some string to render the HTML, you would use this syntax in Razor:
#Html.Raw(Variable)
That causes the Html Encoding not to be done. Obviously, this is dangerous to do with user-supplied input.