I've had a look around and can't seem to find a working solution, so here's the requirements.
I'm building a system that takes data from a master page and loads it into a modal style window for quick data processing. I have a javascript function passing 4 status parameters, and whilst 3 of them will always be integers, one of them can be integer or string.
The function works if all 4 parameters are integer, but fails when a string is passed.
function passJob(jobid,equipid,status,location) {
var a = document.getElementById('jobnumber');
var b = document.getElementById('equipid');
var c = document.getElementById('status');
var d = document.getElementById('location');
a.value = jobid;
b.value = equipid;
c.value = status;
d.value = location;
}
PHP
<a href='#' onclick='passJob($sr,$eid,$ss,$sl);'>Modify Job</a>
$sr, $ss and $sl will always be numeric, $eid will either be integer, or a string starting with M and then having a number after it.
I've tried adding quotes to the variables, around the variables, inside the function etc and no luck :(
You need to pass as string if you do not know what they are - also make sure you do not nest the same type of quote:
onclick='passJob($sr,"$eid",$ss,$sl);'
Just wrap it in quotes. This treats it like a string at all times to avoid any potential JavaScript parsing errors.
Modify Job
That is because you do not properly encode the variables in a Javascript notation. Try:
echo "<a href='#' onclick='passJob(".json_encode($sr).",".json_encode($eid).",".json_encode($ss).",".json_encode($sl).");'>Modify Job</a>";
Do like below
Modify Job
Related
Can someone format the code below so that I can set srcript variables with c# code using razor?
The below does not work, i've got it that way to make is easy for someone to help.
#{int proID = 123; int nonProID = 456;}
<script type="text/javascript">
#{
<text>
var nonID =#nonProID;
var proID= #proID;
window.nonID = #nonProID;
window.proID=#proID;
</text>
}
</script>
I am getting a design time error
You should take a look at the output that your razor page is resulting. Actually, you need to know what is executed by server-side and client-side. Try this:
#{
int proID = 123;
int nonProID = 456;
}
<script>
var nonID = #nonProID;
var proID = #proID;
window.nonID = #nonProID;
window.proID = #proID;
</script>
The output should be like this:
Depending what version of Visual Studio you are using, it point some highlights in the design-time for views with razor.
Since razor syntax errors can become problematic while you're working on the view, I totally get why you'd want to avoid them. Here's a couple other options.
<script type="text/javascript">
// #Model.Count is an int
var count = '#Model.Count';
var countInt = parseInt('#Model.ActiveLocsCount');
</script>
The quotes act as delimiters, so the razor parser is happy. But of course your C# int becomes a JS string in the first statement. For purists, the second option might be better.
If somebody has a better way of doing this without the razor syntax errors, in particular maintaining the type of the var, I'd love to see it!
This is how I solved the problem:
#{int proID = 123; int nonProID = 456;}
<script type="text/javascript">
var nonID = Number(#nonProID);
var proID = Number(#proID);
</script>
It is self-documenting and it doesn't involve conversion to and from text.
Note: be careful to use the Number() function not create new Number() objects - as the exactly equals operator may behave in a non-obvious way:
var y = new Number(123); // Note incorrect usage of "new"
var x = new Number(123);
alert(y === 123); // displays false
alert(x == y); // displays false
I've seen several approaches to working around the bug, and I ran some timing tests to see what works for speed (http://jsfiddle.net/5dwwy/)
Approaches:
Direct assignment
In this approach, the razor syntax is directly assigned to the variable. This is what throws the error. As a baseline, the JavaScript speed test simply does a straight assignment of a number to a variable.
Pass through `Number` constructor
In this approach, we wrap the razor syntax in a call to the `Number` constructor, as in `Number(#ViewBag.Value)`.
ParseInt
In this approach, the razor syntax is put inside quotes and passed to the `parseInt` function.
Value-returning function
In this approach, a function is created that simply takes the razor syntax as a parameter and returns it.
Type-checking function
In this approach, the function performs some basic type checking (looking for null, basically) and returns the value if it isn't null.
Procedure:
Using each approach mentioned above, a for-loop repeats each function call 10M times, getting the total time for the entire loop. Then, that for-loop is repeated 30 times to obtain an average time per 10M actions. These times were then compared to each other to determine which actions were faster than others.
Note that since it is JavaScript running, the actual numbers other people receive will differ, but the importance is not in the actual number, but how the numbers compare to the other numbers.
Results:
Using the Direct assignment approach, the average time to process 10M assignments was 98.033ms. Using the Number constructor yielded 1554.93ms per 10M. Similarly, the parseInt method took 1404.27ms. The two function calls took 97.5ms for the simple function and 101.4ms for the more complex function.
Conclusions:
The cleanest code to understand is the Direct assignment. However, because of the bug in Visual Studio, this reports an error and could cause issues with Intellisense and give a vague sense of being wrong.
The fastest code was the simple function call, but only by a slim margin. Since I didn't do further analysis, I do not know if this difference has a statistical significance. The type-checking function was also very fast, only slightly slower than a direct assignment, and includes the possibility that the variable may be null. It's not really practical, though, because even the basic function will return undefined if the parameter is undefined (null in razor syntax).
Parsing the razor value as an int and running it through the constructor were extremely slow, on the order of 15x slower than a direct assignment. Most likely the Number constructor is actually internally calling parseInt, which would explain why it takes longer than a simple parseInt. However, they do have the advantage of being more meaningful, without requiring an externally-defined (ie somewhere else in the file or application) function to execute, with the Number constructor actually minimizing the visible casting of an integer to a string.
Bottom line, these numbers were generated running through 10M iterations. On a single item, the speed is incalculably small. For most, simply running it through the Number constructor might be the most readable code, despite being the slowest.
#{
int proID = 123;
int nonProID = 456;
}
<script>
var nonID = '#nonProID';
var proID = '#proID';
window.nonID = '#nonProID';
window.proID = '#proID';
</script>
One of the easy way is:
<input type="hidden" id="SaleDateValue" value="#ViewBag.SaleDate" />
<input type="hidden" id="VoidItem" value="#Model.SecurityControl["VoidItem"].ToString()" />
And then get the value in javascript:
var SaleDate = document.getElementById('SaleDateValue').value;
var Item = document.getElementById('VoidItem').value;
I found a very clean solution that allows separate logic and GUI:
in your razor .cshtml page try this:
<body id="myId" data-my-variable="myValue">
...your page code here
</body>
in your .js file or .ts (if you use typeScript) to read stored value from your view put some like this (jquery library is required):
$("#myId").data("my-variable")
Not so much an answer as a cautionary tale: this was bugging me as well - and I thought I had a solution by pre-pending a zero and using the #(...) syntax. i.e your code would have been:
var nonID = 0#(nonProID);
var proID = 0#(proID);
Getting output like:
var nonId = 0123;
What I didn't realise was that this is how JavaScript (version 3) represents octal/base-8 numbers and is actually altering the value. Additionally, if you are using the "use strict"; command then it will break your code entirely as octal numbers have been removed.
I'm still looking for a proper solution to this.
It works if you do something like this:
var proID = #proID + 0;
Which produces code that is something like:
var proID = 4 + 0;
A bit odd for sure, but no more fake syntax errors at least.
Sadly the errors are still reported in VS2013, so this hasn't been properly addressed (yet).
I've been looking into this approach:
function getServerObject(serverObject) {
if (typeof serverObject === "undefined") {
return null;
}
return serverObject;
}
var itCameFromDotNet = getServerObject(#dotNetObject);
To me this seems to make it safer on the JS side... worst case you end up with a null variable.
This should cover all major types:
public class ViewBagUtils
{
public static string ToJavascriptValue(dynamic val)
{
if (val == null) return "null";
if (val is string) return val;
if (val is bool) return val.ToString().ToLower();
if (val is DateTime) return val.ToString();
if (double.TryParse(val.ToString(), out double dval)) return dval.ToString();
throw new ArgumentException("Could not convert value.");
}
}
And in your .cshtml file inside the <script> tag:
#using Namespace_Of_ViewBagUtils
const someValue = #ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue);
Note that for string values, you'll have to use the #ViewBagUtils expression inside single (or double) quotes, like so:
const someValue = "#ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue)";
I use a very simple function to solve syntax errors in body of JavaScript codes that mixed with Razor codes ;)
function n(num){return num;}
var nonID = n(#nonProID);
var proID= n(#proID);
This sets a JavaScript var for me directly from a web.config defined appSetting..
var pv = '#System.Web.Configuration.WebConfigurationManager.AppSettings["pv"]';
With
var jsVar = JSON.parse(#Html.Raw(Json.Serialize(razorObject)));
you can parse any razor object into a JavaScript object.
It's long but universal
I am writing a tutorial page for JavaScript and to prevent xss I want to check if the user's input contains any ajax and if it does return an error string. Also any other elements that could be used for xss in the input should make it error. What would the code for this be?
Try defining a RegExp including methods, strings which should not pass validation , utilize RegExp.prototype.test() with string as argument
var re = /XMLHttpRequest|.\.ajax|.\.get|.\.post|.\.getScript|script/;
var str = "$.post";
var res = re.test(str) ? new Error("error") : str;
console.log(res)
Can someone format the code below so that I can set srcript variables with c# code using razor?
The below does not work, i've got it that way to make is easy for someone to help.
#{int proID = 123; int nonProID = 456;}
<script type="text/javascript">
#{
<text>
var nonID =#nonProID;
var proID= #proID;
window.nonID = #nonProID;
window.proID=#proID;
</text>
}
</script>
I am getting a design time error
You should take a look at the output that your razor page is resulting. Actually, you need to know what is executed by server-side and client-side. Try this:
#{
int proID = 123;
int nonProID = 456;
}
<script>
var nonID = #nonProID;
var proID = #proID;
window.nonID = #nonProID;
window.proID = #proID;
</script>
The output should be like this:
Depending what version of Visual Studio you are using, it point some highlights in the design-time for views with razor.
Since razor syntax errors can become problematic while you're working on the view, I totally get why you'd want to avoid them. Here's a couple other options.
<script type="text/javascript">
// #Model.Count is an int
var count = '#Model.Count';
var countInt = parseInt('#Model.ActiveLocsCount');
</script>
The quotes act as delimiters, so the razor parser is happy. But of course your C# int becomes a JS string in the first statement. For purists, the second option might be better.
If somebody has a better way of doing this without the razor syntax errors, in particular maintaining the type of the var, I'd love to see it!
This is how I solved the problem:
#{int proID = 123; int nonProID = 456;}
<script type="text/javascript">
var nonID = Number(#nonProID);
var proID = Number(#proID);
</script>
It is self-documenting and it doesn't involve conversion to and from text.
Note: be careful to use the Number() function not create new Number() objects - as the exactly equals operator may behave in a non-obvious way:
var y = new Number(123); // Note incorrect usage of "new"
var x = new Number(123);
alert(y === 123); // displays false
alert(x == y); // displays false
I've seen several approaches to working around the bug, and I ran some timing tests to see what works for speed (http://jsfiddle.net/5dwwy/)
Approaches:
Direct assignment
In this approach, the razor syntax is directly assigned to the variable. This is what throws the error. As a baseline, the JavaScript speed test simply does a straight assignment of a number to a variable.
Pass through `Number` constructor
In this approach, we wrap the razor syntax in a call to the `Number` constructor, as in `Number(#ViewBag.Value)`.
ParseInt
In this approach, the razor syntax is put inside quotes and passed to the `parseInt` function.
Value-returning function
In this approach, a function is created that simply takes the razor syntax as a parameter and returns it.
Type-checking function
In this approach, the function performs some basic type checking (looking for null, basically) and returns the value if it isn't null.
Procedure:
Using each approach mentioned above, a for-loop repeats each function call 10M times, getting the total time for the entire loop. Then, that for-loop is repeated 30 times to obtain an average time per 10M actions. These times were then compared to each other to determine which actions were faster than others.
Note that since it is JavaScript running, the actual numbers other people receive will differ, but the importance is not in the actual number, but how the numbers compare to the other numbers.
Results:
Using the Direct assignment approach, the average time to process 10M assignments was 98.033ms. Using the Number constructor yielded 1554.93ms per 10M. Similarly, the parseInt method took 1404.27ms. The two function calls took 97.5ms for the simple function and 101.4ms for the more complex function.
Conclusions:
The cleanest code to understand is the Direct assignment. However, because of the bug in Visual Studio, this reports an error and could cause issues with Intellisense and give a vague sense of being wrong.
The fastest code was the simple function call, but only by a slim margin. Since I didn't do further analysis, I do not know if this difference has a statistical significance. The type-checking function was also very fast, only slightly slower than a direct assignment, and includes the possibility that the variable may be null. It's not really practical, though, because even the basic function will return undefined if the parameter is undefined (null in razor syntax).
Parsing the razor value as an int and running it through the constructor were extremely slow, on the order of 15x slower than a direct assignment. Most likely the Number constructor is actually internally calling parseInt, which would explain why it takes longer than a simple parseInt. However, they do have the advantage of being more meaningful, without requiring an externally-defined (ie somewhere else in the file or application) function to execute, with the Number constructor actually minimizing the visible casting of an integer to a string.
Bottom line, these numbers were generated running through 10M iterations. On a single item, the speed is incalculably small. For most, simply running it through the Number constructor might be the most readable code, despite being the slowest.
#{
int proID = 123;
int nonProID = 456;
}
<script>
var nonID = '#nonProID';
var proID = '#proID';
window.nonID = '#nonProID';
window.proID = '#proID';
</script>
One of the easy way is:
<input type="hidden" id="SaleDateValue" value="#ViewBag.SaleDate" />
<input type="hidden" id="VoidItem" value="#Model.SecurityControl["VoidItem"].ToString()" />
And then get the value in javascript:
var SaleDate = document.getElementById('SaleDateValue').value;
var Item = document.getElementById('VoidItem').value;
I found a very clean solution that allows separate logic and GUI:
in your razor .cshtml page try this:
<body id="myId" data-my-variable="myValue">
...your page code here
</body>
in your .js file or .ts (if you use typeScript) to read stored value from your view put some like this (jquery library is required):
$("#myId").data("my-variable")
Not so much an answer as a cautionary tale: this was bugging me as well - and I thought I had a solution by pre-pending a zero and using the #(...) syntax. i.e your code would have been:
var nonID = 0#(nonProID);
var proID = 0#(proID);
Getting output like:
var nonId = 0123;
What I didn't realise was that this is how JavaScript (version 3) represents octal/base-8 numbers and is actually altering the value. Additionally, if you are using the "use strict"; command then it will break your code entirely as octal numbers have been removed.
I'm still looking for a proper solution to this.
It works if you do something like this:
var proID = #proID + 0;
Which produces code that is something like:
var proID = 4 + 0;
A bit odd for sure, but no more fake syntax errors at least.
Sadly the errors are still reported in VS2013, so this hasn't been properly addressed (yet).
I've been looking into this approach:
function getServerObject(serverObject) {
if (typeof serverObject === "undefined") {
return null;
}
return serverObject;
}
var itCameFromDotNet = getServerObject(#dotNetObject);
To me this seems to make it safer on the JS side... worst case you end up with a null variable.
This should cover all major types:
public class ViewBagUtils
{
public static string ToJavascriptValue(dynamic val)
{
if (val == null) return "null";
if (val is string) return val;
if (val is bool) return val.ToString().ToLower();
if (val is DateTime) return val.ToString();
if (double.TryParse(val.ToString(), out double dval)) return dval.ToString();
throw new ArgumentException("Could not convert value.");
}
}
And in your .cshtml file inside the <script> tag:
#using Namespace_Of_ViewBagUtils
const someValue = #ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue);
Note that for string values, you'll have to use the #ViewBagUtils expression inside single (or double) quotes, like so:
const someValue = "#ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue)";
I use a very simple function to solve syntax errors in body of JavaScript codes that mixed with Razor codes ;)
function n(num){return num;}
var nonID = n(#nonProID);
var proID= n(#proID);
This sets a JavaScript var for me directly from a web.config defined appSetting..
var pv = '#System.Web.Configuration.WebConfigurationManager.AppSettings["pv"]';
With
var jsVar = JSON.parse(#Html.Raw(Json.Serialize(razorObject)));
you can parse any razor object into a JavaScript object.
It's long but universal
I trying to store a piece of xml into a string variable in javascript and in IE8 it keeps throwing an error. FireFox doesn't show the error but of course in IE8 it does. Swictching browsers isn't an option so I have to try to solve this one.
The purpose of the function is to check if the items of a list exist in an xml object or not. So if there is a better way to do that check I am open to that as well. The system we pull from has a function to convert the xml to a string. At the bottom is an output of what that retrieves. Here is the function.
function commodityExists(newCommodityCode){
var comExists = new Boolean(0);
newCommodityCode = ">" + newCommodityCode + "<"
var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
strXML = strXML.toString();
if(strXML.indexOf(newCommodityCode,0)>0){
comExists=true;
}
return comExists;
};
Here is the output from strXML.toString(); but as you can see it is essentially xml.
var strXML = ‘<variable type="NameValuePair[]">
<item type="NameValuePair">
<name type="String"><![CDATA[No Data Found]]></name>
<value type="String"><![CDATA[95990070]]></value>
</item>
</variable>’;
I don't know what you think the code is doing, here is an explanation of what it does:
> function commodityExists(newCommodityCode){
> var comExists = new Boolean(0);
Do you really want a Boolean object? This function might return a Boolean object or primitive depending on what happens later. Consider:
var comExists = false;
.
> newCommodityCode = ">" + newCommodityCode + "<"
That overwrites whatever value was passed to newCommodityCode from the call.
> var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
I can't see how that throws an error, it's a simple assignment of a string.
> strXML = strXML.toString();
That effectivly does nothing - it calls the toString method of a string, which will just return the same string.
> if(strXML.indexOf(newCommodityCode,0)>0){
That test will always be false, since the value of nweCommodityCode is hard coded in the function and does not exist in the (hard coded) value of strXML.
> comExists = true;
> }
> return comExists; };
The function will always return false (though the original will return a Boolean object with a value of false).
You're creating a string:
var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
^--- ^---
then converting that string to... a string?
strXML = strXML.toString();
Where would this tw object be defined that you seem to be attempting to use? Because as your code is written now, you're not calling a .toXMLString() method on something in this tw object. You're just assigning the literal text of an object call as a string itself.
The approach I was trying to take will not work because I am dynamically populating the xml so there is no way for me to escape the characters (well there probably is somehow but clearly it is not worth it). Storing HTML or XML code in javascript variables
Instead I am moving the comparison to the server side instead of retrieving the xml and comparing on the client side and posting back the results via ajax unless someone has a better reccomendation.
I would like to build my own translation function in javascript.
I already have a function language.lookup(key) which translates a word or expression:
var frenchHello = language.lookup('hello') //'bonjour'
Now I would like to write a function which takes a html string and translates it with my lookup function. In the html string I will have a special syntax for example #[translationkey] that will point out that this word should be translated.
This is the result I want:
var html = '<div><span>#[hello]</span><span>#[sir]</span>'
language.translate(html) //'<div><span>bonjour</span><span>monsieur</span>
How would I write language.translate?
My idea is to filter out my special syntax with regex and then run language.lookup on each key. Maybe with string replace or something.
I suck when it comes to regex and I've only come up with a very incomplete example but I include it anyway so maybe someone get the idea of what I am trying to do. Then if there is a better but complete different solution that is more than welcome.
var value = "#[hello], nice to see you.";
lookup = function(word){
return "bonjour";
};
var res = new RegExp( "\\b(hello)\\b", "gi" ).exec(value)
for (var c1 = 0; c1 < res.length; c1++){
value = value.replace(res[c1], lookup(res[c1]))
}
alert(value) //#[bonjour], nice to see you.
The regex should of course not filter out the word hello but the syntax and then collect the key by grouping or similar.
Can anyone help?
Just use String.replace method's ability to call function specified as second argument to generate replacement text and make a global replace using regexp matching your syntax:
var value = "#[hello], #[sir], nice to see you.";
lookup = function(full_match, word){
if(word == 'hello')
return "bonjour";
if(word == 'sir')
return "monsieur"
};
console.log(value.replace(/#\[(.+?)\]/gi, lookup))
Result:
bonjour, monsieur, nice to see you.
Of course when your replacement list gets bigger, you'd better use lookup object instead of series of ifs in lookup function, but you can really do whatever you want there.
You can try this to find all occurrences:
var re = new RegExp('#\\[([^\\]]+?)\\]', 'gi'),
str = '#[value1] plain text #[value2]',
match;
while (match = re.exec(str)) {
console.log(match);
}
You could use something like:
#\\[[^\\]]*\\]
Which matches the hash followed by an opening square bracket followed by zero or more characters NOT including the closing square bracket, followed by a closed square bracket.
Alternatively, perhaps it would be better to handle the translation at the server side (maybe even through your template engine) and send back to your client the translated response. Otherwise, (depending on the specific problem you are dealing with of course), you might end up sending a lot of data to the browser which might make your application respond slowly.
EDIT:
Here is a working piece of code:
var q="This #[ANIMAL1] was eaten by that #[ANIMAL2]";
var u = {"#[ANIMAL1]":"Lion","#[ANIMAL2]":"Frog"};
function insertAnimal(aString, lookup){
var res = (new RegExp("#\\[[^\\]]*\\]", "gi"))
while (m = res.exec(aString)){
aString = aString.replace(m, lookup[m])
}
return aString;
}
function main(){
alert(insertAnimal(q,u));
}
You can call the "main()" from an HTML document's body onload event
I can compare your requirement to 'resolving template texts within content'. If it is feasible to use Jquery , you should try Handlebars.js
.