Emitting unencoded strings in a Razor view - asp.net

As ScottGu says in his blog post «by default content emitted using a # block is automatically HTML encoded to better protect against XSS attack scenarios».
My question is: how can you output a non-HTML-encoded string?
For the sake of simplicity, pls stick to this simple case:
#{
var html = "<a href='#'>Click me</a>"
// I want to emit the previous string as pure HTML code...
}

This is my favorite approach:
#Html.Raw("<p>my paragraph text</p>")
Source was Phil Haack's Razor syntax reference: http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx

You can create a new instance of MvcHtmlString which won't get HTML encoded.
#{
var html = MvcHtmlString.Create("<a href='#'>Click me</a>")
}
Hopefully there will be an easier way in the future of Razor.
If you're not using MVC, you can try this:
#{
var html = new HtmlString("<a href='#'>Click me</a>")
}

new HtmlString is definitely the answer.
We looked into some other razor syntax changes, but ultimately none of them ended up really being any shorter than new HtmlString.
We may, however, wrap that up into a helper. Possibly...
#Html.Literal("<p>something</p>")
or
#"<p>something</p>".AsHtml()

I'm using ASP.NET MVC and Razor under Mono.
I couldn't get HtmlHelper from System.Web.WebPages of System.Web.Mvc for some reasons.
But I managed to output unencoded string after declaring model's property as RazorEngine.Text.RawString. Now it outputs as expected.
Example
#{
var txt = new RawString("some text with \"quotes\"");
var txt2 = "some text with \"quotes\"";
}
<div>Here is unencoded text: #txt</div>
<div>Here is encoded text: #txt2</div>
Output:
<div>Here is unencoded text: some text with "quotes"</div>
<div>Here is encoded text: some text with "quotes"</div>

I ran into this problem as well when transitioning our project to the new Razor view engine. The approach I took was slightly different because we had to generate JSON data from C# and wanted to output it upon page load.
What I eventually did was to implement a RawView that was a parallel of View inside of the cshtml files. Essentially, to get a raw string,
#(new HtmlString(View.Foo))
// became
#RawView.Foo
This requires a few changes to the project layout, so I just wrote up a blog post about it here. In short, this required a duplicate implementation of MVC's DynamicViewDataDictionary and a new WebViewPage that contains the RawView. I also went ahead and implemented the index operator on the RawView to allow for
#RawView["Foo"]
In the off-chance that someone needs to loop over the data with a list of keys.
Reading anurse's comment, it probably would have been better off if I had named this as a Literal instead of RawView.

Related

how to bind data as routeValue in telerik ListView template

My template modified from MvcMusicStore tutroial:
<script type="text/x-kendo-tmpl" id="template">
<div class="product">
<a href="#Url.Action("Details", "Store", new {id = ${ProductSubCategoryId} })">
<img src="#Url.Content("${AlbumArtUrl}")" alt="${Title} image" />
</a>
<span><h3>${Title}</h3></span>
<p>${kendo.toString(Price, "c")}</p>
</div>
</script>
but there is error in Url.Action method: Unexpected symbol '$'.
Update 1:
And i can't use
#Model.First(d => d.ProductCategoryId.Equals(Convert.ToInt32("${ProductSubCategoryId}"))).ProductCategory.Name
but same code in
#Url.Content("${AlbumArtUrl}")
work fine.
new {id = ${ProductSubCategoryId} }
This is C# code for an anonymous object, and C# doesn't know anything about JS templating. Hence the error telling you it doesn't know what that $ is doing there. Usually you'd pass something from your View model, which is only available serverside:
new {id = Model.ProductSubCategoryId }
Instead of using a URL helper, you might be better off with just a string href="Store/Details/${ProductSubCategoryId}". That may not be exactly what you need, but I don't know enough about the routing and your template to know if this is what you intended, or if ProductSubCategoryId is actually a property of your model.
In regards to your updated examples:
Url.Content( works because that function takes the parameter as the page is being rendered on the server, and just spits out with the string "${AlbumArtUrl}" in the HTML pretty much as it is, and the HTML will contain the string "${AlbumArtUrl}" so that when the JS template is parsed later on the client, it can interpret that variable. So in this case, the C# function .Content( doesn't need to understand that template variable, because to it, it is just a string that it embeds in the HTML. I would recommend using F12 in Chrome to view the GET response in the network tab so you can see the HTML source as it was returned from the action, so you have a better idea in your mind of what exactly what is happening at each step of the process. You'll be able to see that in your HTML returned, there is no C# code like Url.Content, but you will see the javascript template stuff like "${AlbumArtUrl}" because those values aren't rendered on the server side.
On the other hand Convert.ToInt32("${ProductSubCategoryId}") fails, because this function expects the string it's being passed to be an integer, such as Convert.ToInt32("2134"). As far as ToInt32 is concerned, it says, ok, I see "something" is a string, now I will try to interpret the string as a number which means I expect it to contain some digits, such as "456457" but you gave me a bunch of letters and symbols which means nothing to me, I can't convert that into an integer. Again, this is C# function that is running on the server as it generates the page, and "${ProductSubCategoryId}" means nothing to C# as it is a javascript template variable.
You are mixing server-side code with client-side code. This is invalid C# code:
#Url.Content("${AlbumArtUrl}")
You cannot use helper to generate URLs this way. I suggest you to go the normal way without using the Url helper.
If you are determined to use Url.Action, then here is a way. It is a hack but you can do this:
<a href="#Url.Action("Details", "Store")?id=${ProductSubCategoryId}">

razor string manipulation

I have a razor string
#postername.Substring(0, #postername.IndexOf("#"))
If the username has email I get the username before # sign but if the username doesn't have email I want to have that whole word, how to do ?
if(#postername.Contains("#")){
#postername.Substring(0, #postername.IndexOf("#"))
}else{
#postername
}
but didn't work, pls help
If you must do this at View level, build the logic into a variable first:
#{
string posternameShort = postername;
if(postername.Contains("#")){
posternameShort = postername.Substring(0, postername.IndexOf("#"))
}
}
Then call the new variable:
#posternameShort
To further clarify this, Razor functions (what appears in the code block between { and }) fully support C# code. Additionally, Visual Basic code is supported as well.
This is powerful. Any string manipulation that would occur in C# or Visual Basic, is also available to use in Razor code.
More info on this available here and here.
Curt's response outlines a basic way to do this, but I thought it would be good to explain the "why" behind the "how," especially since I've been looking into how to manipulate strings with Razor myself.

How should I store comments in database so that I can efficiently display them on page as html text?

I have a form where use enters multiple line of texts in a text area.
Some of the lines can have html markups as well. Say one line is bold.
How should I save the text in my database?
Should I store them as like this?
This is a greap post
<br/>
I love this type of findings.
<br/>
<br/>
Thanks for sharing
OR like this?
This is a greap post
<br/>
I love this type of findings.
<br/>
<br/>
Thanks for sharing
During editing:
I must show the text as they were entered. So line break will be replaced by new line
That way use sees there is a line break. Textarea won't unserstand br markup
During displaying:
I must render the text so that it appears like this on the page:
This is a greap post
I love this type of findings.
Thanks for sharing
I want to know the cleanest way to store text that can have markup in them.
Thanks for help
Since you want to output HTML, you will have to store the input in it's raw format in the database. There is only one catch though. You never should trust input, since all input is evil, especially in this case, since outputting HTML directly as it is inputted, opens the possibility of an cross-site scripting (XSS) attack.
You have basically got two options:
Use a HTML sanitizer that let's you remove all tags that are not known to be safe. A good sanitizer is the one that comes with the Microsoft AntiXss toolkit.
Encode the input and decode parts of the result that are known to be safe, for instance:
string[] safeList = { "<br/>", "<b>", "</b>", "<i>", "</i>" };
public static string EncodeInputWithSafeList(string unsafeInput)
{
// First: encode the complete input.
string safeInput = Encoder.HtmlEncode(unsafeInput);
// Next: decode each tag that is known to be safe.
foreach (string safeTag in safeList)
{
string encodedTag = Encoder.HtmlEncode(safeTag, false);
safeInput = safeInput.Replace(encodedTag, safeTag);
}
return safeInput;
}
Note: The example uses the Encoder class from the Microsoft AntiXss toolkit.
Now the question becomes, at what point should we clean it up. Normally you should encode the output just before you send it to the client and not store it encoded in the database, since it depends on the output type (HTML, PDF, JSON) how data should be encoded. This is amplified by the fact that in case there is a bug in the encoder, there is no way to fix it, since the data is already encoded.
In this case it is a bit more tricky though, since the input is HTML and not just text. I would say that sanitizing is something you still would want to do before hand, because this way you prevent bad input from entering your database. The EncodeInputWithSafeList method is a bit tricky, because it is both a sanitizer and an encoder. When we run it before it goes into the database, it prevents the output from changing when we change the safe list. This can be both a good thing and a bad thing, but I would say that when you add new tags to the safe list, you wouldn't want old data to suddenly change. So in this case I would go with input encoding, instead of output encoding.
When you go with input encoding, name the database column in such way that it is clear that we're dealing with sanitized, encoded data.
Try htmlentities($str, ENT_QUOTES); before you save the data, and html_entity_decode($str) after you fetch it from your db, before you render it to the browser.
saving it to your database like this:
<p>This is a greap post
<br/>
I love this type of findings.
<br/>
<br/>
Thanks for sharing</p>
would work..

ASP.NET MVC: Using LINQ to XML to render (X)HTML

There has been a lot of discussions on View-engines for ASP.NET MVC and some criticisms against the inline "tag-soup" with for-loops and thing like it.
The alternative or complement has been to use HTML-helpers, which are just inline method-calls.
When I look inside ASP.NET MVC's HTML-helpers today they are using a class called TagBuilder.
My proposal is to use LINQ to XML to get strongly typed and correctly formatted (X)HTML:
XDocument output = new XDocument();
XElement root = new XElement("div",
new XAttribute("class", "root_item"));
XElement iconImage = new XElement("img",
new XAttribute("src", ResolveUrl("~/image.gif")),
new XAttribute("alt", "This is an image"));
XElement link = new XElement("a",
new XAttribute("class", "link"),
new XAttribute("href", "http://google.com"),
new XText("Link to Google"));
root.Add(link);
root.Add(iconImage);
output.Add(root);
I like it because it's like the strongly typed controls in WebForms, where you can new-up a Button and add it to another control's Control-collection.
Are there any apparent problems or limitations in this?
This is a great idea! The only problem I see with it is the use of C#. ;) VB.NET has much better support for producing XML via it's XML literals feature.
The code you list in your question could be written like this in VB.NET. (With the addition of the text "This is a link" as your example didn't contain any text within the a element.)
Dim root = <div class="root_item">
<img src=<%= ResolveUrl("~/image.gif") %> alt="This is an image"/>
<a class="link" href="http://google.com">This is a link</a>
</div>
There are still <%= ... %> tags, but they are checked for validity at compile time. If this code was made the return value of a function that returned type XElement, then that Xhtml snippet could be reused elsewhere in the site.
I have a project on CodePlex that uses VB.NET XML Literals as a custom ASP.NET MVC View Engine at http://vbmvc.codeplex.com. It is based on code by Dmitry Robsman, who is Product Unit Manager for ASP.NET at Microsoft. Views are VB.NET classes and Master Pages are base classes. You new-up Partial view classes instead of referencing them by a name string, so that is also an additional compile time check. Instead of the HtmlHelper class, which returns strings, there is an XhtmlHelper class which returns XElement and works similarly to what you have proposed.
I can think of two problems to the above mentioned method.
First,
XElement iconImage = new XElement("img",
new XAttribute("src", ResolveUrl("~/image.gif")),
new XAttribute("alt", "This is an image"));
Referring to what you write above, we can have something like:
<img src=<%=whatever%> alt=<%=whatever%> />
This might be personal judgement or what, but I certainly vote the later one more "human" readable. Right, using LINQ 2 XML might get rid of the weird <% } %> that wandering around in my aspx pages, but at the same time, you make those "good boys" looks clumsy.
Second might come with performance issue. I think parsing and executing LINQ 2 XML could be quite slow, although I don't have any data regarding this.
Personally I am still experimenting the MVC framework, it feels like getting back to old days like ASP or PHP 3.X, since almost all the interactive parts are explicitly handled, instead of the window/GUI-OOP oriented ASP Dot Net Framework. I think the main reason I will use MVC is that it can guarantee the best quality client-side HTML codes..

Simplify e-mail body in string?

I'm just wondering about this one. I'm creating an ASP.NET webform containing lots of textboxes etc. And I want to send an e-mail based on this stuff.
And the e-mails body needs to go into a string.
And the string is supposed to contain HTML code, but the syntax changes because of the string. So how can I simplify this? Is there any software or something that lets me do this? Perhaps paste in some HTML code and then convert this to string format, ready to use with vb.net?
If I understand correctly, you are wanting to generate an HTML email from user input via textboxes. If so, you can easily generate HTML using the HtmlTextWriter:
StringBuilder sb = new StringBuilder();
using(HtmlTextWriter writer = new HtmlTextWriter(new StringWriter(sb)))
{
writer.WriteBeginTag("span");
writer.WriteAttribute("style", "font-weight:bold;");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(textboxName.Text);
writer.WriteEndTag("span");
}
return sb.ToString();
The above will generate a string which looks like:
<span style="font-weight:bold;">user input</span>
The HtmlTextWriter makes it very easy to ensure your markup is semantically correct and valid by mimicking the XML writers.
For converting a HTML formatted string back to plain text try this link,
[http://www.dreamincode.net/code/snippet1578.htm][Strip HTML from string using Regular Expressions]
This will only strip the tags and doesn't remove the html symbols like an ampersand but it will get you started.

Resources