ASP.Net C# Razor showing encoded HTML instead of raw html - asp.net-mvc

I'm using the JQM-DateBox - which needs the following Razor markup:
#Html.TextBoxFor(m => m.From, new { #name = "mydate", #id = "mydate",
#data_role = "datebox",
#data_options = "{'mode':'flipbox', 'dateFormat':'dd/mm/YYYY' ,'useNewStyle':true} ")
However, this renders as:
<input data-options=" {'mode':'flipbox', 'dateFormat':'dd/mm/YYYY' ,'useNewStyle':true} "
data-role="datebox" id="mydate"
name="From" type="text" value="29/08/2013 00:00:00" />
I know you can use html.raw - but how do you use it within a helper?
I need to show:
{'mode':
...instead of...
{'mode':

Try #Html.Raw(HttpUtility.HtmlDecode(#Html.TextBoxFor(...).ToHtmlString())).

TextBoxFor uses TagBuilder which is ultimately responsible for turning ' in to ' (since it uses MergeAttributes with the htmlAttributes parameter passed to the helper).
Instead of pasting the answer, check out Stop the tag builder escaping single quotes ASP.NET MVC 2
Also, this isn't quite the same exact question, but then it is. I'll leave it up to others if they want to close it and cite the above reference.

Related

Checkboxes generated via CheckBoxFor helper turn into type=hidden because of MaterializeCSS

I'm creating a website with ASP.NET MVC5 and I'm using MaterializeCSS for the first time, which looks like a very exciting framework.
However, the checkboxes generated by CheckBoxFor helper become hidden !
When I write :
#Html.CheckBoxFor(m => m.IsAgreeTerms)
The generated HTML is :
<input name="IsAgreeTerms" type="hidden" value="false">
Why does Materialize change my type=checkbox into type=hidden ?
I tried to add type="checkbox" in the CheckboxFor helper, but it doesnt change anything. The only way is to modify in in my browser's console.
The only solution I found is this SO thread.
However, the accepted answer doesn't change anything for me.
The other answer works, but I think it's ugly to add some JS script to modify what Materialize modifies without my consent.
Is there any way to say "Hey, I ask for a type=checkbox, so just let my type=checkbox in the generated HTML" ?
Thank you
UPDATE :
My full ASP.NET MVC code is :
#Html.CheckBoxFor(m => m.IsAgreeTerms, new { #type = "checkbox" })
#Html.LabelFor(m => m.IsAgreeTerms, new { #class = "login-label" })
The full generated HTML is
<input data-val="true" data-val-required="Le champ IsAgreeTerms est requis." id="IsAgreeTerms" name="IsAgreeTerms" type="checkbox" value="true"
<input name="IsAgreeTerms" type="hidden" value="false">
<label class="login-label" for="IsAgreeTerms">IsAgreeTerms</label>
Here's a solution in the form of a html helper. It constructs a checkbox and label in the correct order:
public static IHtmlString CheckBoxWithLabelFor<TModel>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, bool>> expression,
string labelText,
object htmlAttributes = null
)
{
if (expression == null)
{
throw new ArgumentNullException(nameof(expression));
}
var checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
var pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1, StringComparison.Ordinal));
var labelHtml = htmlHelper.LabelFor(expression, labelText).ToHtmlString().Trim();
var result = pureCheckBox + Environment.NewLine + labelHtml + Environment.NewLine + $"<input type=\"hidden\" name=\"{ExpressionHelper.GetExpressionText(expression)}\" value=\"false\" />";
return new MvcHtmlString(result);
}
Is there other html generated by materialize.css? I think this happens because it is not possible apply a custom CSS to element input of type checkbox.
So, the checkbox becomes hidden and other html component represents visually the checkbox. Many components work like that.
UPDATE:
Why is Html checkbox generating an additional hidden input
OP here. Problem looks like more complex.
Actually, when using #Html.CheckBoxFor, MVC5 generates 3 fields, in that order :
Your input, with type="checkbox", binded to your model property
An hidden field (see the Claudio's link for an explaination)
Your label, generated by #Html.LabelFor
Problem is Materialize expects that in another order to work.
In your browser's console, just move the <label> element between the input and the hidden field, and everything works fine !
I found this very useful link, where, basically, it is said that the order of the generated fields by #Html.checkBoxFor will change ... In MVC6 !
As I'm working with MVC5, I use this very ugly solution in my _Layout:
$(":checkbox").each(function () {
$(this).nextAll("label").before($(this))
})
If anyone has a better idea, please feel free to post an elegant solution.

How to insert '_' as htmlAttributes in razor?

This is probably a simple question, but to which I havent found an answer yet.
How to escape the ' _ ' when creating an HtmlElement in razor?
To render a '-' in the final Html we put an ' _ ', but to render an '_' (underscore), How do we escape it? I tryed '#:', but it didn't work, and didn't find any other options...
Example:
#Html.CheckBox("Access_Groups", false, new
{
#class = "input-control checkbox",
#data_group = "I', looking for data-group",
#Description_pt = "<----- I'm looking for Description_pt"
})
#data_group will render as data-group as expected, but...
#Description_pt will render as Description-pt, and that is not what is expected (don't know how to escape the _ for this)
thank you
If you look at the signature of Html.Checkbox, we can see that it takes an object for the htmlAttributes. Further, looking at the syntax, its actually a key based collection of objects. A Dictionary<string,object> fits that bill and allows you to absolutely specify the name of the html attributes that you want to add (note each key is typed exactly how we want it to display).
#Html.CheckBox("Access_Groups", false, new Dictionary<string,object>
{{"class", "input-control checkbox"},
{"data-group", "I', looking for data-group"},
{"Description_pt", "SomeValue"}})
This renders the following HTML
<input Description_pt="SomeValue" class="input-control checkbox"
data-group="I', looking for data-group" id="Access_Groups"
name="Access_Groups" type="checkbox" value="true" />
Have you tried the HTML character code for underscore, i.e., _?

data being passed from controller, is it encoded?

I want to ask in MVC3+; data passed from controller in form of modle or viewbag is the data encoded by default or I do have to ?
Do you mean HTML encoded? They're not, no.
This means that if you have a string property that contains the value "<b>some text</b>" then the property contents is exactly that.
If, however, you try to print this output to the View with #MyProperty then, by default, the string will be HTML-encoded by MVC. So the output would become <some text>.
You can escape this by using #Html.Raw(MyProperty).
Remember that the term 'encoded' is a bit vague. Try to be specific with what encoding you're referring to.
MVC proactively tries to encode values to prevent cross-site scripting.
#* This is HTML Encoded *#
#Model.Value
#* This value is not encoded *#
#Html.Raw(Model.Value)
#* The URL gets URL Encoded *#
<a href="#Url" />
This Razor code
# {
bool disabled = false;
bool readonly = true;
string className = null;
}
<input type="text" disabled="#disabled" readonly="#readonly" class="#className" />
Actually produces this output
<input type="text" readonly="readonly" />
A value of null or false causes the Razor view engine to not render the attribute at all.
If you did want something like this data-soldout="false" then you need to do:
data-soldout="#Html.Raw(isSoldout)" or data-soldout="#isSoldout.ToString()"

Razor syntax isn't recognizing '#' after an underscore

I am trying to do the following:
#foreach(var p in #Model.line_products){
<img class="small_img_#Model.line_products[i].short_name" src="/Content/images/#Model.line_products[i].image_name" />
}
Which isn't working, it renders the text just the way it is, not recognizing the '#'. I found this other post in Stackoverflow, which suggests adding parenthesis in the following way:
#foreach(var p in #Model.line_products){
<img class="small_img_(#Model.line_products[i].short_name)" src="/Content/images/#Model.line_products[i].image_name" />
}
Using this workaround, I get that my id is rendered as small_img_(MODEL ATTRIBUTE). Isn't there a workaround which doesn't require adding specific characters? (such as the parenthesis).
You have more errors than a simple undercore problem here. You cannot use #Model inside your if. You are already in a # block. Simply use #foreach(var p in Model.line_products).
Plus, the way you wrote the parenthesis, they will get rendered. What you want is
small_img_#(Model.line_products[i].short_name)
Put the parenthesis after the # instead of before:
class="small_img_#(Model.line_products[i].short_name)"
I sometimes put a couple of Guids in the id of an element and an underscore separator doesn't work.
There are two ways around this. First use the entity code _ instead and secondly just use a hyphen.
<input id="chk_#classLeader.ClassLeader_#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
<input id="chk-#classLeader.ClassLeader-#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
This is because I want to grab out the Guid's when the check box is clicked with some JQuery like this:
$(".chk_Done").click(function () {
var obj =[];
const itemId = ($(this).attr("id"));
const myArray = itemId.split("_");
var ClassLeaderGuid = myArray[1], IngredientGuid = myArray[2];

Writing/outputting HTML strings unescaped

I've got safe/sanitized HTML saved in a DB table.
How can I have this HTML content written out in a Razor view?
It always escapes characters like < and ampersands to &.
Supposing your content is inside a string named mystring...
You can use:
#Html.Raw(mystring)
Alternatively you can convert your string to HtmlString or any other type that implements IHtmlString in model or directly inline and use regular #:
#{ var myHtmlString = new HtmlString(mystring);}
#myHtmlString
In ASP.NET MVC 3 You should do something like this:
// Say you have a bit of HTML like this in your controller:
ViewBag.Stuff = "<li>Menu</li>"
// Then you can do this in your view:
#MvcHtmlString.Create(ViewBag.Stuff)
You can use
#{ WriteLiteral("html string"); }
Sometimes it can be tricky to use raw html. Mostly because of XSS vulnerability. If that is a concern, but you still want to use raw html, you can encode the scary parts.
#Html.Raw("(<b>" + Html.Encode("<script>console.log('insert')</script>" + "Hello") + "</b>)")
Results in
(<b><script>console.log('insert')</script>Hello</b>)
You can put your string into viewdata in controller like this :
ViewData["string"] = DBstring;
And then call that viewdata in view like this :
#Html.Raw(ViewData["string"].ToString())
Apart from using #MvcHtmlString.Create(ViewBag.Stuff)
as suggested by Dommer, I suggest you to also use AntiXSS library as suggested phill http://haacked.com/archive/2010/04/06/using-antixss-as-the-default-encoder-for-asp-net.aspx
It encodes almost all the possible XSS attack string.
Complete example for using template functions in RazorEngine (for email generation, for example):
#model SomeModel
#{
Func<PropertyChangeInfo, object> PropInfo =
#<tr class="property">
<td>
#item.PropertyName
</td>
<td class="value">
<small class="old">#item.OldValue</small>
<small class="new">#item.CurrentValue</small>
</td>
</tr>;
}
<body>
#{ WriteLiteral(PropInfo(new PropertyChangeInfo("p1", #Model.Id, 2)).ToString()); }
</body>

Resources