MVC - Handling unterminated string literal for new line - javascript

In my MVC view am having the below piece of code
<script type="text/javascript">
#foreach (var item in Model.Test)
{
<text> jsFunction(#item.someValue); </text>
}
</script>
Where am calling the Javascript function based on the data i get from model dynamically.
For Example At run time it is rendered like below based on the model data
jsFunction("Works Fine");
jsFunction("works Fine");
Which correctly calls my javascript function
But in case of a new line getting "unterminated string literal" because of the new line
jsFunction("not working
with new line");
What is the best way to handle this Scenario
Thanks

What is the best way to handle this Scenario
Use a JSON serializer which will ensure that the value passed to your javascript function is properly escaped:
<script type="text/javascript">
#foreach (var item in Model.Test)
{
<text>jsFunction(#Html.Raw(Json.Encode(item.someValue)));</text>
}
</script>
or if you update your jsFunction to take an array instead of a single item you could do this:
<script type="text/javascript">
var values = #Html.Raw(Json.Encode(Model.Test));
jsFunction(values);
</script>
and then loop through the normal javascript array that will be passed to your function.
P.S: Don't worry if Razor Intellisense is putting a red squiggle around this code. Visual Studio Intellisense in Razor views doesn't work well. Just ignore the warning and run your application and observe the properly generated code.

Simplest solution is to create a helper or something:
#* declared at top of razor page *#
#helper jsFunction(String str)
{
str = (str ?? String.Empty).Trim().Replace(Environment.NewLine, "\\n");
#:jsFunction("#Html.Raw(str)");
}
#* example usage *#
foreach (var item in Model.Test)
{
#jsFunction(#item.Comment)
}
That would perform sanitization on the string to make it convert \n in to the JavaScript counter-part \\n. You may also include exceptions for quotation marks (turn " into \", etc.)
The better alternative is to use something like JSON.NET though:
<text>jsFunction(#Html.Raw(JsonConvert.Serialize(#item.Comment)))</text>
That would make it completely safe to JavaScript (and handle the exceptions for you).

try this
jsFunction(#Html.Raw(Json.Encode(item.Comment)))
I think this should solve your issue.

Related

How do I pass a JSON object from JSP to Javascript?

I have a variable for myInitState that is initialized within a controller that is then passed to a jsp view.
<script>
myInitFunction({
myInitState: '${myInitState}',
componentName: 'myCompName',
divId: 'divId'
});
</script>
However by using '${myInitState}', in my Javascript I notice I get a string of "{...}" when debugging in browser. Is it possible to pass the object as json and have it be recognized as such or would I have re-parse the object within myInitFunction?
In order to take advantage of string interpolation, you need to use backticks
`${myInitState}`
You will then want to parse the string inside the function using JSON.parse(someString)
Updating answer here:
A couple of things I had left out of my question due to my misunderstanding:
- myInitState is a Map of <String,Object>
- The values of the map could be already escaped JSON blobs.
In this case the flow was from Server to client, so in order to convert the map into a JSON blob correctly I would need to do something like this in JSP:
<script>
var jsonBlob = {
<c:forEach items="${myInitState}" var="state" varStatus="loop">
"${state.key}": ${state.value} ${not loop.last ? ',' : ''}
</c:forEach>
};
</script>
However, a better approach, and what I went with, would be to just do conversion in the controller itself where myInitState is constructed.

Using MVC resource in Jquery - function stops working

I have a Jquery function in MVC View that check if at least one checkbox is clicked. Function is working properly if I use hardcoded string. But when I add
#Resources.myString into, it stops working, I can't figure out why
$('.form-horizontal').on('submit', function (e) {
if ($("input[type=checkbox]:checked").length === 0) {
e.preventDefault();
alert("This is working");
alert(#Resources.myString); //with this the function is not working anymore
return false;
}
});
I need to add the the string for multilingual purpose.
I tried diferent aproches
alert(#Resources.myString);
alert(#Html.Raw(Resources.myString))
var aaa = { #Html.Raw(Resources.myString)} //and calling the aaa
I think I am missing some basic knowlage of how this should work together
During page rendering, #Resources.myString will be injected as is in the code. For instance, if myString == "abc";, you'll end up with alert(abc); which is not what you want.
Just try to enclose your string in quotes:
alert("#Resources.myString");
As an aside, putting Razor code in Javascript logic is usually considered bad practice, as it prevents you from putting Javascript code in separate files (and therefore caching), and makes the code less readable.
Take a look as this question and the provided answer which gives a simple way to deal with that.
As ASP.NET dynamically generates HTML, CSS, JS code, the best way to find the error is to read the generated sources (Ctrl + U in most modern browsers).
You will see that your code
alert(#Resources.myString);
produces
alert(yourStringContent);
and should result in a console error yourStringContent is not defined.
You need to use quotes as you are working with a JavaScript string:
alert('#Resources.myString');
It will produce a correct JavaScript code like:
alert('yourStringContent');

Convert C# string to JavaScript String

Does anybody know a way to convert a C# string to a JavaScript String in Asp.net. My code looks like this:
<script>
#{string thing = "Cats";}
var thing = String(#thing);
</script>
</div>
<body onload="eventAlert(thing)"></body>
You need to JavaScript Encode your string before you write it out, otherwise your string may contain characters that cause the JavaScript string constant to be terminated prematurely. You can do this with HttpUtility.JavaScriptStringEncode in the System.Web namespace. Once you have done that you need to stop razor from HTML Encoding the result which can be done with HtmlHelper.Raw like this:
#{string thing = "Cats Special Chars \"!'£$%^&*()#;:";}
var thing = "#Html.Raw(HttpUtility.JavaScriptStringEncode(thing))";
Try the following:
var thing = "#(thing)";
There are a couple of good ways to do this. But a very clean way is to use a cookie. This is clean because you are not injecting javascript code from the server into your static client code. Writing C# to create JavaScript and then insert that into a variable may have timing issues, depending on when your code runs and what .Net is doing. Be very careful in reading strings back for security concerns.

javascript literals from C# - avoiding warnings

First off, this code does work, but it gives me a low level of annoyance that I'd like to be rid of. I have a .cshtml page that is built using the razor syntax. There is a big, nasty, knockout object living behind the scenes to which many things on the page are bound. Currently, when instantiating that knockout model, I'm doing so by serializing the C# viewmodel object in question within a string literal like below.
<script type="text/javascript">
$(document).ready(function() {
var data = #Html.Raw(Json.Encode(Model));
var contentListingModel = new ContentListingModel(data);
ko.applyBindings(contentListingModel, $('#pageRoot').get(0));
});
</script>
Like I said, the code works. However, on the line with the #Html.Raw call, I get a warning. Visual Studio believes there is a syntax error there (there isn't, after it is rendered). Now, it totally makes sense WHY the thing believes there is a syntax problem there. But I would love to get rid of the warning by coding in a way that doesn't trigger this issue (I realize I could hide the warning or do any number of other things), but I just want it to not show in cases where I'm serializing C# objects into JSON and stuffing them into javascript on the page. Any ideas?
I accept fully that it is pedantic and petty to ask about this one, since the code works perfectly well and is seemingly clean, but it annoys me.
The IDE is smart enough to accept lines which consist purely of Razor, so you can write:
#Html.Raw( "var data= " + Json.Encode(Model) + ";" )
alert(data);
If the (assumed) implicit global bothers you (e.g. it triggers a Resharper warning), split the declaration and assignment.
var data; // javascript
#Html.Raw( "data= " + Json.Encode(Model) + ";" ) // all razor
Which produces at runtime:
var data;
data = {"foo": "bar"};
'You Can Just Serialize Your Model To Json In Your ActionMethod , And Pass It To Your View Through ViewData Or ViewBag And Simply Pass It To ViewModel With Html.Raw , Something Like This :
//In Your ActionMethod
var serializer = new JavaScriptSerializer();
Viewdata["SomeName"] = serializer.Serialize(model);
//In Your cshtml
#{
string data = (string)Viewdata["SomeName"];
}
$(document).ready(function() {
var contentListingModel = new ContentListingModel('#Html.Raw(data)');
ko.applyBindings(contentListingModel, $('#pageRoot').get(0));
});
the javascript debugger ignore the razor code and see this
var data = ;
which is a syntax error, replace this
var data = #Html.Raw(Json.Encode(Model));
with this, and the warning will be gone.
var data #('=') #Html.Raw(Json.Encode(Model));

How I access a variable from JavaScript and Grails?

I have a Grails variable which is of type JASONList that is rendered in a template.
Is there a way to access this list from inside a JavaScript function?
Let's say I want onresize to fit all the objects on the screen. Without making a database call and refetching the entire list from Ajax...
Let's say the template does something like this:
<g:each var="report" in="${reportList?.myArrayList}">
<li style="display:inline; list-style:none;">
<img src=" ${report?.img}">
</li>
</g:each>
<script type="text/javascript">
function resize(list) {
if (list.size <givenSize) // Pseudocode
list.subList() // Pseudocode
}
window.onresize = resize("${reportList}")
</script>
The problem with this is that for some reason Grails gsp does not render "${reportList}" as a list. Instead it renders it as the string "${reportList}".
I am probably thinking of this problem completely wrong, but is there a way to resize these objects or get them through document.getElementById or something of that nature?
The $reportList is populated by POJO as JSON conversion...
Grails variables only exist on the server side. JavaScript runs in the browser (client side). Everything that's sent to the browser is a string, so while you can use Grails to generate a piece of JavaScript like window.onresize = resize("${reportList}"), the browser will only see the string that ${reportList} evaluates to.
That means that, if you use Grails to pass a variable to the resize() JavaScript function, the parameter (list) will only ever be a string - you won't be able to access server-side list methods like list.size or list.subList(), because the list variable is no longer a list; it's just a string.
I don't know, but maybe Grails doesn't want to evaluate expressions inside script tags. Dynamically generated scripts is not a very good practice.
But until you find the exact cause, you could try something like this:
<g:each var="report" in="${reportList?.myArrayList}">
<li style="display:inline; list-style:none;">
<img src=" ${report?.img}">
</li>
</g:each>
<%= """<script type=\"text/javascript\">
function resize(list){
if(list.size <givenSize) //posudo code
list.subList() // psudocode
}
window.onresize = resize(\"$reportList\")
</script>""" %>
I'm not sure why your ${reportList} is being rendered as ${reportList}, because when I do the following:
var t = "${taskList}";
I get the following in my HTML:
var t = "[com.wbr.highbar.Task : 1, com.wbr.highbar.Task : 4, com.wbr.highbar.Task : 2, com.wbr.highbar.Task : 5]";
That said, you're still going to have issues, because JavaScript will have no idea what to do with your reportList. If it is pure JSON, you would need to eval() it so that it gets turned into a JavaScript Object.
I figured out my problem. Basically if you are using POJO in Grails the Grails as JSON conversion is not very smart. All it does is a toString on the object instead of potentially looking at all the public accessors, etc.
It is kind of disappointing, but basically I need to create the JSON conversion in the toString method of my POJO.

Categories