Why does MVC double-encode unobtrusive validation attributes? - asp.net

For example:
data-val-equalto="'MyProperty5' and 'MyProperty4' do not match."
Question: Why is the & character encoded again into & ('), instead of just outputting the character reference as is (') ?
The jquery.validate plugin seems to be parsing ' as '.
The problem doesn't seem to be in Razor, but with the code that generates the unobtrusive validation attributes, the following code:
<span title="#("'MyProperty5' and 'MyProperty4' do not match.")"></span>
... outputs correctly:
<span title="'MyProperty5' and 'MyProperty4' do not match."></span>
Found out that the problem is in ASP.NET MVC, there's a method called GetValidationAttributes that adds HTML-encoded values to a dictionary, and then the values are encoded again by TagBuilder. It would be good to know why they are doing this.

Try outputting using the Html.Raw method.
Otherwise, Razor does not assume you are trying to output encoded HTML and encodes it again.
Given
string text = `Bread & Breakfast`;
#text will be output as Bread &amp; Breakfast because the & is HTML Encoded
#Html.Raw(text) will be output as "Bread & Breakfast"
UPDATE based on your update
I can't tell you why jQuery Validate works that way, but there's an old adage "if it hurts when you do X, stop doing X".
You don't really need to encode the single quote in your output HTML. Both of the following produce the same result:
<span title="'MyProperty5' and 'MyProperty4' do not match.">
Span With Encoded Title
</span>
<br />
<span title="'MyProperty5' and 'MyProperty4' do not match.">
Span With non-Encoded Title
</span>

This issue was fixed on MVC v4.

Related

In ASP.NET Razor, how to include model attribute in a string?

Is there a clean way to include a string substitution inside a razor page?
That is, I have some razor code that looks like this but does not work. I feel like I'm missing some punctuation.
<div class='card-img'>
<img src='images/User-#Model.Id.jpg'/>
</div>
With your current code, razor thinks the the expression Model.Id.jpg is some server side code it needs to execute.So you are going to get an error message saying there is no such method/property called jpg on whatever the type of Id is or there are no extension method called jpg in that type.
To fix the problem, you shall wrap your C# expression with an explicit ( and )
<div class='card-img'>
<img src='images/User-#(Model.Id).jpg'/>
</div>
This tells razor that Model.Id is the C# expression it needs to execute. The output of exuecuting that expression will pe rendered in the HTML.For example, If the value of Model.Id is 100, the rendered output will be
<img src="images/User-100.jpg">
Now make adjustments to your path (src value) based on where you are storing the image.
Try to use either Razor code block #(...) or #Url.Content() helper for string concatenation:
#* Code block string concatenation *#
<img src='images/User-#(Model.Id).jpg'/>
#* Content helper string concatenation *#
<img src='#Url.Content("images/User-" + Model.Id + ".jpg")'/>
Take note that #Model.Id.jpg doesn't work because Id property doesn't have member named jpg, since the second dot (.) treated as member access expression.

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}">

Dangerous Request values with ISO Latin-1 codes?

I have an Asp.net form ( runat=Server)
Im trying to figure out what is the difference between HTML Entities and ISO Latin-1 codes - and why does one Do cause exception while the other Isnt.
I have input and button
<input type="text" value="<d"/>
<asp:Button ID="s" runat="server" Text="press" />
when I press submit - it goes with Exception which is fine.
1 way to solve it is by encodeUriComponent :
so putting the value :
value="%3Cd"/>
is fine and No expcetion on submit.
Also , as we know - if i put
> or < ( which is html entity) it wont go exception. ( it has other role in Html world - to DISPLAY '<' '>' - and not try to parse them as html...)
(no exception - except the second press - because when its back from the server - the textbox shows <d which is bad...
NOw lets go to the ISO Latin-1 code like here
now lets try to put instead of <d ----> <d
and it goes bang !
1)why do i get an exception in the Latin code and not in the html entity ?
1) what is the difference between them ?
2) when should i use one or another ?
Edit
I know I can disable the checking by set validateRequest = false.
but my questions are not related to this.
Your Latin example contains &#. Those are exactly the characters which trigger a validation error What characters or character combinations are invalid when ValidateRequest is set to true?. So no surprise here.

How can I write raw XML to a Label in ASP.NET

I am getting a block of XML back from a web service. The client wants to see this raw XML in a label on the page. When I try this:
lblXmlReturned.Text = returnedXml;
only the text gets displayed, without any of the XML tags. I need to include everything that gets returned from the web service.
This is a trimmed down sample of the XML being returned:
<Result Matches="1">
<VehicleData>
<Make>Volkswagen</Make>
<UK_History>false</UK_History>
</VehicleData>
<ABI>
<ABI_Code></ABI_Code>
<Advisory_Insurance_Group></Advisory_Insurance_Group>
</ABI>
<Risk_Indicators>
<Change_In_Colour>false</Change_In_Colour>
</Risk_Indicators>
<Valuation>
<Value xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></Value>
</Valuation>
<NCAP>
<Pre_2009></Pre_2009>
</NCAP>
</Result>
What can I do to make this appear on the screen? I noticed that Stack Overflow does a pretty good job of putting the XML on the scren. I checked the source and it's using <pre> tags. Is this something that I have have to use?
It would be easier to use a <asp:Literal /> with it's Mode set to Encode than to deal with manually encoding Label's Text
<asp:Literal runat="server" ID="Literal1" Mode="Encode" />
You need to HtmlEncode the XML first (which escapes special characters like < and > ):
string encodedXml = HttpUtility.HtmlEncode(xml);
Label1.Text = encodedXml;
Surrounding it in PRE tags would help preserve formatting, so you could do:
string encodedXml = String.Format("<pre>{0}</pre>", HttpUtility.HtmlEncode(xml));
Label1.Text = encodedXml;
As Bala R mentions, you could just use a Literal control with Mode="Encode" as this automatically HtmlEncodes any string. However, this would also encode any PRE tags you added into the string, which you wouldn't want. You could also use white-space:pre in CSS which should do the same thing as the PRE tag, I think.

webmethod encoding issue

I am facing a n00b issue in .NET webservices. the WebMethod return type is encoding an already encoded string (already encoded by my xml writer).
Is there a way to turn of this off?
Example
the prepared xml before the webmethod returns it
<p> Hello World </p>
but the xml received by the client from the webmethod response
<p> Hello World </P>
the ampersand is getting encoded by the web method
I am using xmlwriter object to build the xml... has anyone a solution to this?
I'm guessing you're sending this to a webpage. What you're getting is the encoding to show the actual '<' characters on the screen and not the HTML reserved characters.
These '<' '>' are reserved characters in a HTML page for the HTML parsers to use. If you want to use them in your page, you use &lt (lesser than) &gt (greater than).
Try putting a '\' in front of each of your HTML reserved character. This is a guess, I'm not sure that it'll work.

Resources