I am trying to use a Razor template to produce a .aspx page as output. I'm not having luck looking in the documentation for how to do this. The Page and namespace declarations are breaking the template:
<%# Page Language="C#" Title="#Page.Metadata.browser_title" %>
<%# Import Namespace="System.Xml" %>
These are causing this error:
TemplateCompileException: CS1501: No overload for method 'Write' takes 0 arguments Line 27 Column 1: Write();
I assume this is because Razor templates using C# syntax makes the two conflict, since the declarations above use "#". Is there a way to get them to work together so a Razor template can produce an output with C# in the rendered product after the template is run? The example above also shows how the value for "Title" needs to be rendered out of the template.
The #s in the <% are invalid Razor syntax.
You need to escape them by writing <%##.
If you like Razor, maybe you should check out DD4T (http://code.google.com/p/dynamic-delivery-4-tridion/). It allows you to build a web site using ASP.Net MVC with Razor views.
You could write a C# TBB to add the tags after all your Razormediator templates or even better if you could add after the Default Finish Actions(if you're using one).
Quick and dirty sample code...
Item OutputItem = package.GetByName(Package.OutputName);
string OutputText = OutputItem.GetAsString();
// Page tag declaration..
string pagePretags = #"<<TWO LINES OF DECLARATIONs..>>"
string FinalOutputText = pagePretags + OutputText ;
OutputItem.SetAsString(FinalOutputText);
Hope this helps..
Related
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!
I have a legacy ASP.Net site (recently upgraded to .NET 4.0) which never had Request Validation turned on and it doesn't Html encode any user input at all.
My solution was to turn on request validation and to catch the HttpRequestValidationException in Global.asax and redirect the user to an error page. I don't Html Encode the user input as I'll have to do it in thousands of places. I hope my approach will stop any XSS vectors getting saved into database.
However, in case if there is already any XSS vector stored in database I reckon I should also Html encode all output. Unfortunately I have very limited dev and test resource to successfully achieve this. I came up with a list of changes I need to go through:
Search and Replace all <%= %> with <%: %>.
Search and Replace all Labels with Literals and add Mode="Encode".
Wrap all eval() with HtmlEncode.
My questions are:
Is there any simpler way of turning on all output to be automatically Html encoded?
Am I missing anything from above list?
Any pitfalls I should be careful about?
Thanks.
Search and Replace all <%= %> with <%: %>.
Don't forget the <%# and Response.Write which will be harder to replace
Search and Replace all Labels with Literals and add Mode="Encode".
But you will loose all formatting on the previously generated spans, break the DOM
and the corresponding js/css
You would also have to search all Literals with Mode="PassThrough" and set them to Encode
Wrap all eval() with HtmlEncode.
Yes, it seems like a subset of the <%# matter above
Also, you could have some custom controls with funky render method
Assuming there is "only" a relational DB as back-end, If I had access to the DB, I would first go on identifying the problematic tables and columns which values contain markup.
I would then :
cleanup as best as I can those values in DB.
ensure HtmlEncoding of the corresponding outputs in my pages
I could then go for a basic global replace <%= becoming <%: and sanitize outputs on the long run.
So, simple question really. :)
I had this following code with ASPX View Engine:
<strong><%: ((City)Model.Location).Name %></strong>
Which renders
Los Angeles
If i do this with Razor View Engine:
<strong>#((City)Model.Location).Name</strong>
^
|
syntax highlighting stops here
It renders this:
(really huge object name must be .ToString).Name
So, the highlighting cuts off at Location), and it's treating the .Name code i have (which is a property on a City object) as pure HTML.
Why is it deeming the ) as the end of the Razor code block?
Any ideas?
Also - is there a Razor reference which has all the syntax/keywords? (it took me a while to figure out that <% Import Namespace is #using with Razor).
Thanks Guys!
Does <strong>#(((City)Model.Location).Name)</strong> work? I think it's thinking the expression contained within #() is closed.
Also, for slightly easier reading...
<strong>#( (Model.Location as City).Name )</strong>
I've been struggling to find some way to do my required conditional binding.
I want to use Eval("products_image") in conditional binding in such a way that if product_image exists in images directory then it's ok, otherwise it should display "noimage.jpg".
I tried to do it this way:
<%# (File.Exists(("ProductImages/"+Convert.ToString(Eval("products_image"))))) ? ("ProductImages/"+Convert.ToString(Eval("products_image"))) : "ProductImages/noimage_small.jpg" ; %>
I have tried other ways as well, but every time, I mess up with a bunch of errors.
Can anyone guide me the right way to do this?
<%# (File.Exists(("ProductImages/"+Convert.ToString(Eval("products_image"))))) ? ("ProductImages/"+Convert.ToString(Eval("products_image"))) : "ProductImages/noimage_small.jpg" ; %>
Quite long and unreadable, isn't it?
I'd suggest adding a method to your code behind or in a <script> tag
// returns the imageFile parameter if the file exists, the defaultFile parameter otherwise
string ImageFileExists(string imageFile, string defaultFile) {
if (File.Exists(Server.MapPath(imageFile)))
return imageFile;
else
return defaultFile;
}
And then you'd simply use
<%# ImageFileExists("ProductImages/" + Eval("products_image").ToString(), "ProductImages/noimage_small.jpg") %>
Note that I've added a Server.MapPath call to the method so that File.Exists will actually look in the right place.
I just moved the whole <script> tag and System.IO namespace inside the usercontrol .ascx file itself and it did it.
Thanks a ton configurator for help :)
How do i escape text for html use in C#? I want to do
sample="<span>blah<span>"
and have
<span>blah<span>
show up as plain text instead of blah only with the tags part of the html :(.
Using C# not ASP
using System.Web;
var encoded = HttpUtility.HtmlEncode(unencoded);
Also, you can use this if you don't want to use the System.Web assembly:
var encoded = System.Security.SecurityElement.Escape(unencoded)
Per this article, the difference between System.Security.SecurityElement.Escape() and System.Web.HttpUtility.HtmlEncode() is that the former also encodes apostrophe (') characters.
If you're using .NET 4 or above and you don't want to reference System.Web, you can use WebUtility.HtmlEncode from System
var encoded = WebUtility.HtmlEncode(unencoded);
This has the same effect as HttpUtility.HtmlEncode and should be preferred over System.Security.SecurityElement.Escape.
In ASP.NET 4.0 there's new syntax to do this. Instead of
<%= HttpUtility.HtmlEncode(unencoded) %>
you can simply do
<%: unencoded %>
Read more here:
New <%: %> Syntax for HTML Encoding Output in ASP.NET 4 (and ASP.NET MVC 2)
.NET 4.0 and above:
using System.Web.Security.AntiXss;
//...
var encoded = AntiXssEncoder.HtmlEncode("input", useNamedEntities: true);
You can use actual html tags <xmp> and </xmp> to output the string as is to show all of the tags in between the xmp tags.
Or you can also use on the server Server.UrlEncode or HttpUtility.HtmlEncode.
For a simple way to do this in Razor pages, use the following:
In .cshtml:
#Html.Raw(Html.Encode("<span>blah<span>"))
In .cshtml.cs:
string rawHtml = Html.Raw(Html.Encode("<span>blah<span>"));
You can use:
System.Web.HttpUtility.JavaScriptStringEncode("Hello, this is Satan's Site")
It was the only thing that worked (ASP.NET 4.0+) when dealing with HTML like this. The' gets rendered as ' (using htmldecode) in the HTML content, causing it to fail:
It's Allstars
There are some special quotes characters which are not removed by HtmlEncode and will not be displayed in Edge or Internet Explorer correctly, like ” and “. You can extend replacing these characters with something like the below function.
private string RemoveJunkChars(string input)
{
return HttpUtility.HtmlEncode(input.Replace("”", "\"").Replace("“", "\""));
}