How do I write unencoded Json to my View using Razor? - asp.net-mvc

I'm trying to write an object as JSON to my Asp.Net MVC View using Razor, like so:
<script type="text/javascript">
var potentialAttendees = #Json.Encode(Model.PotentialAttendees);
</script>
The problem is that in the output the JSON is encoded, and my browser doesn't like it. For example:
<script type="text/javascript">
var potentialAttendees = [{"Name":"Samuel Jack"},];
</script>
How do I get Razor to emit unencoded JSON?

You do:
#Html.Raw(Json.Encode(Model.PotentialAttendees))
In releases earlier than Beta 2 you did it like:
#(new HtmlString(Json.Encode(Model.PotentialAttendees)))

Newtonsoft's JsonConvert.SerializeObject does not behave the same as Json.Encode and doing what #david-k-egghead suggests opens you up to XSS attacks.
Drop this code into a Razor view to see that using Json.Encode is safe, and that Newtonsoft can be made safe in the JavaScript context but is not without some extra work.
<script>
var jsonEncodePotentialAttendees = #Html.Raw(Json.Encode(
new[] { new { Name = "Samuel Jack</script><script>alert('jsonEncodePotentialAttendees failed XSS test')</script>" } }
));
alert('jsonEncodePotentialAttendees passed XSS test: ' + jsonEncodePotentialAttendees[0].Name);
</script>
<script>
var safeNewtonsoftPotentialAttendees = JSON.parse(#Html.Raw(HttpUtility.JavaScriptStringEncode(JsonConvert.SerializeObject(
new[] { new { Name = "Samuel Jack</script><script>alert('safeNewtonsoftPotentialAttendees failed XSS test')</script>" } }), addDoubleQuotes: true)));
alert('safeNewtonsoftPotentialAttendees passed XSS test: ' + safeNewtonsoftPotentialAttendees[0].Name);
</script>
<script>
var unsafeNewtonsoftPotentialAttendees = #Html.Raw(JsonConvert.SerializeObject(
new[] { new { Name = "Samuel Jack</script><script>alert('unsafeNewtonsoftPotentialAttendees failed XSS test')</script>" } }));
alert('unsafeNewtonsoftPotentialAttendees passed XSS test: ' + unsafeNewtonsoftPotentialAttendees[0].Name);
</script>
See also:
Does the output of JsonConvert.SerializeObject need to be encoded in Razor view?
XSS Prevention Rules

Using Newtonsoft
<script type="text/jscript">
var potentialAttendees = #(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>

Related

Send data via post to action create Jquery and Ruby on Rails

I am using Jquery. I have created a array javasript called #provinces in localhost:3000/provinces/new. I need pass that array to localhost/provinces through the POST method, I mean to the create action
I created a special button for that called Send data via post
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$provinces=new Array();
$(".add").click(function(e) {
$("body").append("<label class='label1'>Add Province</label>");
$("body").append("<input type='text' class='value'/>")
$(".add").prop('disabled', true);
$("body").append("<input type='button' id='save' value='Save'>")
});
$("body").on("click","#save", function(){
$provinces.push($(".value").val());
$(".label1").remove();
$(".value").remove();
$(".add").prop('disabled', false);
$(this).remove();
});
$("body").on("click",".show", function(){
$cadena="";
for($i=0;$i<$provinces.length;$i++){
$cadena=$cadena+"\n"+$provinces[$i];
}
alert($cadena);
});
$("body").on("click",".send", function(){
});
});
</script>
</head>
<body>
<h1>New province</h1>
<button class="add">Add Province</button>
<button class="show">Show array</button>
<button class="send">SendData via post</button>
<br/><br/>
</body>
</html>
Examine this line:
$provinces=new Array();
1) In js, the $ sign has no special meaning when used like that. In fact, the $ sign is sometimes used in jQuery to indicate that a variable has been assigned a wrapped set, and your array is not a wrapped set, so the $ sign is misleading.
2) new Array() is equivalent to [], so you can simply write:
var provinces = [];
You cannot pass arrays between javascript and ruby code(or vice versa). However, you can use javascript to send a request that contains a string to a ruby program on the server.
1) You can convert your array to a string using:
JSON.stringify()
2) You can send a string to a ruby program on the server using jQuery's .ajax() function:
$.ajax({
url: '/provinces/create',
type: 'POST',
contentType: 'application/json',
data: json_str
})
.success(function(resp_data, text_status) {
console.log('resp: ' + resp_data);
console.log('status: ' + text_status);
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log('status: ' + textStatus);
console.log('error: ' + errorThrown);
})
3) On the server side, if a request has a Content-Type equal to 'application/json', Rails will automatically parse the body of a request(your json_str) into ruby Arrays and Hashes, which Rails makes available in the params hash. The array will be available as params['_json'] or params[provinces]['_json].
If you don't like having to look for your array under the '_json' key in the rails params hash, then in your js code you can convert your array to an object, like this:
var provinces = [];
...
var obj = {my_array: provinces};
var json_str = JSON.stringify(obj);
Then in your ruby code, the array will be available as params[my_array] or params[provinces][my_array].

Why cannot I paste codes generated from dust website directly?

Now I wrote a template very easily:
Hello, my name is {name}, I'm {age}.
And then open this website: http://linkedin.github.io/dustjs/test/test.html, do some pasting and the template js codes are generated below:
(function() {
dust.register("demo", body_0);
function body_0(chk, ctx) {
return chk.write("Hello, my name is ").reference(ctx._get(false, ["name"]), ctx, "h").write(", I'm ").reference(ctx._get(false, ["age"]), ctx, "h").write(".");
}
return body_0;
})();
Then I created a js file and copy all the js codes generated above and refer this into my app:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DustDemo</title>
<script src="jsfiles/dust.js"></script>
<script src="jsfiles/staticpagetemplate.js"></script>
<script>
function Demo1() {
dust.render("demo", { name: "test", age: 13 }, function (err, out) {
alert(out);
});
}
</script>
</head>
<body onload="Demo1()">
<h1>Demo 1——Static Page</h1>
<div id="divDemo1">
</div>
</body>
</html>
Question is that if I use like this, it reports me "_get" cannot be found. Later I found the problem in dust.js:
Context.prototype.get = function (key) {
var ctx = this.stack, value;
while (ctx) {
if (ctx.isObject) {
value = ctx.head[key];
if (!(value === undefined)) {
return value;
}
}
ctx = ctx.tail;
}
return this.global ? this.global[key] : undefined;
};
So no "_get" but "get" instead!
Why this MISMATCHES the translator online?? Anyone can help me??
You are likely using an old version of Dust in jsfiles/dust.js. As of Dust 2.2.0 get has been replaced with _get. The compiler on http://linkedin.github.io/dustjs/test/test.html uses the new version of Dust, so it compiles the template using _get instead of get.
You have compiled your template with a new version of Dust, but you are trying to render it with an old version of Dust, and the two are not compatible.

Javascript function with name from ViewBag

How to generate javascript function with the name taken from ViewBag? I'm trying the below
#{ (ViewBag.ModuleId + "DatePickerStartDateChange = function() {console.log('asdf');};");}
and hoping that it will emit javascript in the html output as
xxxxxxDatePickerStartDateChange = function() {alert("asdf");};
Absolutely no idea why on earth you would need to do that, but here's the correct syntax:
<script type="text/javascript">
#(ViewBag.ModuleId)DatePickerStartDateChange = function() {
console.log('asdf');
};
</script>

ASP.NET MVC with google analytics tacking root url

I have an ASP.NET MVC site and my google analytics code is the example code cut/pasted into my layout page. This is how it records root requests:
Can anyone tell me how to get it to record only the / as the root url? For reference here is my analytics code:
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("my code");
pageTracker._trackPageview();
} catch (err) { }
</script>
You need to set the _trackPageview value to the page you want to log the metrics under, e.g.:
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("my code");
pageTracker._trackPageview("/");
} catch (err) { }
</script>

MVC Render JSONResult as a Literal

I have a JsonResult action in my MVC project...
public JsonResult GetData(string term) {
List<String> data = repo.GetData(term).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
This powers a jquery autocomplete lookup but as there is only 30 values in the database, I think that this is not efficent use of database resources...
<script type="text/javascript">
jQuery(document).ready(function ($) {
$("input#MyTextBox").autocomplete({
source: '<%: Url.Action("GetDate","Controller") %>',
delay: 1,
minChars: 2
}
);
});
</script>
I would like to generate something simlar to this...
<script>
$(document).ready(function() {
$("input#MyTextBox").autocomplete({
source: ["my","list","of","values"]
});
});
</script>
I am missing something here as this should be simple. Is there a way that I can change the url.action to something that will render the JSON almost like a PartialView ?
Also, is this a good solution to the problem or can someone show me a better way?
2 points:
Yes, there is a way to render JSON easier:
<script type="text/javascript">
jQuery(document).ready(function ($) {
$("input#MyTextBox").autocomplete({
source: <%: Html.Raw(Json.Encode(Model.AutocompleteSourceFromDb)) %>,
delay: 1,
minChars: 2
}
);
});
</script>
From database usage perspective this doesn't change a thing. You still rendering the whole JSON on page render and not querying database on autocomplete.

Resources