Set data in javascript file via backend c# - javascript

I have the following situation.
I want to show a (donut) graph with data in my web page.
I'm getting the data from my database in my backend of my webpage (ASP.NET/C#).
I'm using a standalone javascript file ('graph.js') for the graph:
//Donut Chart
var donut = new Morris.Donut({
element: 'sales-chart',
resize: true,
colors: ["#3c8dbc", "#f56954", "#00a65a"],
data: [
{ label: "**DATA**", value: **10** },
{label: "**DATA**", value: **30**},
{label: "**DATA**", value: **20**}
],
hideHover: 'auto'
});
Is there a good way of putting the data in the javascript file? (Changing the DATA variables)
I know it's possible to put the javascript in script elements on my aspx page, and getting my data there:
var DataNumber = <%=DataNumber%>;
And giving this data in the backend:
private String _dataNumber = String.Empty;
protected string DataNumber {
get {
return this._dataNumber ;
}
set {
this._dataNumber = value;
}
}
but that's not what i'm looking for.
I realy want to use an standalone file for this.

I'm more into cshtml files, but you could render a serialized list containing your variables, in an hidden div in your ASPX file :
<div class="hidden" id="myData" data-data="<%= JsonConvert.SerializeObject(myData)%>"></div>
Then, you could get this data from within your javascript code:
$(function() {
var data = $("#myData").data('data');
var donut = new Morris.Donut( /* do something with data */);
})
I'm using newtonsoft JSON.NET to serialize, and JQuery to parse json data.
Another solution is to make an Ajax call to fetch your data.
Edit:
Here is an example with something similar I've done in ASP.NET:
File donut.aspx.cs:
// ...
protected void Page_Load(object sender, EventArgs e)
{
// edit the following line to suit your needs
var list = new List<Data>(your_data_as_list);
donut.Attributes.Add("data-donut", list)
}
// ...
File donut.aspx:
<script type="text/javascript" src="lib/morris.js"></script>
<!-- create a component that will be managed by C#
<div runat="server" id="donut"></div>
<!-- this will execute once the page is loaded -->
<script type="text/javascript">
jQuery(function () {
// use <%= donut.ClientID %> to get the generated Id from ASP.NET
var donutData= $("#<%= donut.ClientID %>").data("donut");
var donut = new Morris.Donut( /* do something with donutData*/);
});
</script>

Sure. Assuming that you don't want to retrieve data later after page is loaded using ajax, you can put your data in global object with you razor syntax, before your standalone script is executed like this:
window.mydata = <%=DataNumber%>;
Just keep number of global objects to a minimum. Use single root for all globals. Like this:
window.myGlobals.mydata = <%=DataNumber%>;
And later access it from wherever you want.
If you want to avoid globals completely, there is several ways you could do that, but all of them include rendering you data to your page.
For example, you could put data attributes in your script tag.
<script type="text/javascript" data-mydata="<%=DataNumber%>" src="mymodule"></script>
And in script, just access it trough $(document.currentScript).data("mydata)...
But, beware that you don't loose it during bundling process...

Related

Access RESX file from external javascript file [duplicate]

How would one get resx resource strings into javascript code stored in a .js file?
If your javascript is in a script block in the markup, you can use this syntax:
<%$Resources:Resource, FieldName %>
and it will parse the resource value in as it renders the page... Unfortunately, that will only be parsed if the javascript appears in the body of the page. In an external .js file referenced in a <script> tag, those server tags obviously never get parsed.
I don't want to have to write a ScriptService to return those resources or anything like that, since they don't change after the page is rendered so it's a waste to have something that active.
One possibility could be to write an ashx handler and point the <script> tags to that, but I'm still not sure how I would read in the .js files and parse any server tags like that before streaming the text to the client. Is there a line of code I can run that will do that task similarly to the ASP.NET parser?
Or does anyone have any other suggestions?
Here is my solution for now. I am sure I will need to make it more versatile in the future... but so far this is good.
using System.Collections;
using System.Linq;
using System.Resources;
using System.Web.Mvc;
using System.Web.Script.Serialization;
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript(string resxFileName)
{
var resourceDictionary = new ResXResourceReader(Server.MapPath("~/App_GlobalResources/" + resxFileName + ".resx"))
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.{0} = {1};", resxFileName, json);
return JavaScript(javaScript);
}
}
// In the RegisterRoutes method in Global.asax:
routes.MapRoute("Resources", "resources/{resxFileName}.js", new { controller = "Resources", action = "GetResourcesJavaScript" });
So I can do
<script src="/resources/Foo.js"></script>
and then my scripts can reference e.g. window.Resources.Foo.Bar and get a string.
There's no native support for this.
I built a JavaScriptResourceHandler a while ago that can serve Serverside resources into the client page via objects where each property on the object represents a localization resource id and its value. You can check this out and download it from this blog post:
http://www.west-wind.com/Weblog/posts/698097.aspx
I've been using this extensively in a number of apps and it works well. The main win on this is that you can localize your resources in one place (Resx or in my case a custom ResourceProvider using a database) rather than having to have multiple localization schemes.
whereas "Common" is the name of the resource file and Msg1 is the fieldname. This also works for culture changes.
Partial Javascript...:
messages:
{
<%=txtRequiredField.UniqueID %>:{
required: "<%=Resources.Common.Msg1 %>",
maxlength: "Only 50 character allowed in required field."
}
}
In a nutshell, make ASP.NET serve javascript rather than HTML for a specific page. Cleanest if done as a custom IHttpHandler, but in a pinch a page will do, just remember to:
1) Clear out all the ASP.NET stuff and make it look like a JS file.
2) Set the content-type to "text/javascript" in the codebehind.
Once you have a script like this setup, you can then create a client-side copy of your resources that other client-side scripts can reference from your app.
If you have your resources in a separate assembly you can use the ResourceSet instead of the filename. Building on #Domenics great answer:
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript()
{
// This avoids the file path dependency.
ResourceSet resourceSet = MyResource.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
// Create dictionary.
var resourceDictionary = resourceSet
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.resources = {1};", json);
return JavaScript(javaScript);
}
}
The downside is that this will not enable more than one resource-file per action. In that way #Domenics answer is more generic and reusable.
You may also consider using OutputCache, since the resource won't change a lot between requests.
[OutputCache(Duration = 3600, Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetResourcesJavaScript()
{
// Logic here...
}
http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/improving-performance-with-output-caching-cs
I usually pass the resource string as a parameter to whatever javascript function I'm calling, that way I can continue to use the expression syntax in the HTML.
I the brown field application I'm working on we have an xslt that transforms the resx file into a javascript file as part of the build process. This works well since this is a web application. I'm not sure if the original question is a web application.
use a hidden field to hold the resource string value and then access the field value in javascript
for example :
" />
var todayString= $("input[name=TodayString][type=hidden]").val();
Add the function in the BasePage class:
protected string GetLanguageText(string _key)
{
System.Resources.ResourceManager _resourceTemp = new System.Resources.ResourceManager("Resources.Language", System.Reflection.Assembly.Load("App_GlobalResources"));
return _resourceTemp.GetString(_key);
}
Javascript:
var _resurceValue = "<%=GetLanguageText("UserName")%>";
or direct use:
var _resurceValue = "<%= Resources.Language.UserName %>";
Note:
The Language is my resouce name. Exam: Language.resx and Language.en-US.resx

Passing Array to Script in EJS file [duplicate]

I'm working on a Node.js app (it's a game). In this case, I have some code set up such that when a person visits the index and chooses a room, he gets redirected to the proper room.
Right now, it's being done like this with Express v2.5.8:
server.get("/room/:name/:roomId, function (req, res) {
game = ~databaseLookup~
res.render("board", { gameState : game.gameState });
}
Over in board.ejs I can access the gameState manner with code like this:
<% if (gameState) { %>
<h2>I have a game state!</h2>
<% } %>
Is there a way for me to import this into my JavaScript logic? I want to be able to do something like var gs = ~import ejs gameState~ and then be able to do whatever I want with it--access its variables, print it out to console for verification. Eventually, what I want to do with this gameState is to display the board properly, and to do that I'll need to do things like access the positions of the pieces and then display them properly on the screen.
Thanks!
You could directly inject the gameState variable into javascript on the page.
<% if (gameState) { %>
<h2>I have a game state!</h2>
<script>
var clientGameState = <%= gameState %>
</script>
<% } %>
Another option might be to make an AJAX call back to the server once the page has already loaded, return the gameState JSON, and set clientGameState to the JSON response.
You may also be interested in this: How can I share code between Node.js and the browser?
I had the same problem. I needed to use the data not for just rendering the page, but in my js script. Because the page is just string when rendered, you have to turn the data in a string, then parse it again in js. In my case my data was a JSON array, so:
<script>
var test = '<%- JSON.stringify(sampleJsonData) %>'; // test is now a valid js object
</script>
Single quotes are there to not be mixed with double-quotes of stringify. Also from ejs docs:
"<%- Outputs the unescaped value into the template"
The same can be done for arrays. Just concat the array then split again.
I feel that the below logic is better and it worked for me.
Assume the variable passed to the ejs page is uid, you can have the contents of the div tag or a h tag with the variable passed. You can access the contents of the div or h tag in the script and assign it to a variable.
code sample below : (in ejs)
<script type="text/javascript">
$(document).ready(function() {
var x = $("#uid").html();
alert(x); // now JS variable 'x' has the uid that's passed from the node backend.
});
</script>
<h2 style="display:none;" id="uid"><%=uid %></h2>
In the EJS template:
ex:- testing.ejs
<html>
<!-- content -->
<script>
// stringify the data passed from router to ejs (within the EJS template only)
var parsed_data = <%- JSON.stringify(data) %>
</script>
</html>
In the Server side script:
ex: Router.js
res.render('/testing', {
data: data // any data to be passed to ejs template
});
In the linked js (or jquery) script file:
ex:- script.js
In JavaScript:
console.log(parsed_data)
In JQuery:
$(document).ready(function(){
console.log(parsed_data)
});
Note:
1. user - instead of = in <% %> tag
2. you can't declare or use data passed from router to view directly into the linked javascript or jquery script file directly.
3. declare the <% %> in the EJS template only and use it any linked script file.
I'm not sure but I've found it to be the best practice to use passed data from router to view in a script file or script tag.
This works for me.
// bar chart data
var label = '<%- JSON.stringify(bowlers) %>';
var dataset = '<%- JSON.stringify(data) %>';
var barData = {
labels: JSON.parse(label),
datasets: JSON.parse(dataset)
}
You can assign backend js to front end ejs by making the backend js as a string.
<script>
var testVar = '<%= backEnd_Var%>';
</script>
This should work
res.render("board", { gameState : game.gameState });
in frontend js
const gameState = '<%- JSON.stringify(gameState) %>'
Well, in this case you can simply use input text to get data. It is easy and tested when you use it in firebase.
<input type="text" id="getID" style="display: none" value="<%=id%>">
I know this was answered a long time ago but thought I would add to it since I ran into a similar issue that required a different solution.
Essentially I was trying to access an EJS variable that was an array of JSON objects through javascript logic like so:
<script>
// obj is the ejs variable that contains JSON objects from the backend
var data = '<%= obj %>';
</script>
When I would then try and use forEach() on data I would get errors, which was because '<%= obj %>' provides a string, not an object.
To solve this:
<script>
var data = <%- obj %>;
</script>
After removing the string wrapping and changing to <%- (so as to not escape html going to the buffer) I could access the object and loop through it using forEach()
Suppose you are sending user data from the node server.
app.get("/home",isLoggedIn,(req,res)=>{
res.locals.pageTitle="Home"
res.locals.user=req.user
res.render("home.ejs");
})
And now you can use the 'user' variable in the ejs template. But to use the same value using client-side javascipt. You will have to pass the data to a variable in the tag.
Passing ejs variable to client-side variable:
<script>
let user= '<%- JSON.stringify(user) %>';
</script>
<script>home.js</script>
Now you can access the user variable at home.js

Call an action from JS file instead of the view (MVC 4)

I'm using the MVC 4.
In my view i can simply get an action's url by using the: #Url.Action
Now i wanted to make a javascript file with all the view's javascript instead of writing it all in the view, the problem is i can't use the razor's stuff anymore.
so my question is how can i get the action's url from a javascript separated file?
You'll need to define a JavaScript variable within your view that you can then use in your script. Obviously this must be declared first.
I use a helper on my layout pages that has all these variables and a section for any I'd want specific to a page. Note these would come before any other script references before the body tag.
#Scripts.Variables()
#RenderSection("ScriptVariables", false)
The Scripts.Variables is something like this
#helper Variables()
{
<script language="javascript" type="text/javascript">
var ActionGetallAdmin = '#Url.Action("GetAll", "Admin")';
var ActionAccountLogin = '#Url.Action("Login", "Account")';
</script>
}
One way I did this before was to create views that served JS files (and CSS files, actually), instead of HTML files. This leverages the fact that views aren't necessarily HTML files all the time in the MVC paradigm.
You could do this by creating a controller for it:
public class AssetController : Controller {
protected void SetMIME(string mimeType) {
// implementation largely removed
this.Response.Headers["Content-Type"] = mimeType;
this.Response.ContentType = mimeType;
}
// this will render a view as a Javascript file
public void ActionResult MyJavascript() {
this.SetMIME("text/javascript");
return View();
}
}
Once you've done that, you can create a view (using the way you normally do it in ASP.NET MVC), and just write it up as Javascript. Remember not to use a layout, as you obviously don't want that.
Everything that views in MVC has to offer is available to you, so feel free to use models, et al.
#model IList<Entity>
#{
Layout = null;
}
(function ($) {
// javascript!
#foreach(var entity in Model) {
$('##entity.Id').on('click', function () {
console.log('#entity.Name');
});
}
})(jQuery);
Then you can wire that up using old-fashioned Razor in your other views.
<script src="#Url.Action("MyJavascript","Asset")"></script>
Which will roll out something like
<script src="http://your.domain/asset/myjavascript"></script>
Works like a charm. The views are dynamically created, of course, so be wary if you're nit-picky about that. However, since they are MVC controller actions and views, you can set cache options on them just as with any other view.
Uhm... I think you can define a special route, like "actionsjs", that points to an action.
routes.MapRoute(name: "actionsJs",
url: "actionsjs",
defaults: new { controller = "Home", action = "GetActions" });
In the action you've to set the content to the right type:
Response.ContentType = "text/javascript";
Then you'll return a specific View that will contains javascript code with some Razor inside.
#{
Layout = "";
}
$(function() {
var a = #(1 + 2);
});
At this point you'll able to add this "script file" to your site:
<script type="text/javascript" scr="#Url.Action("GetActions", "Home")"></script>
Should work.
If you want the root path, use a variable on layout and use that in JavaScript file, say
// In layout view
<script>
var rootPath = #Url.Content("~/")
</script>
User rootPath anywhere in your application JavaScript files
If you want to get full path of a controller with action then
// View
<script>
var url = #Url.Content("ActionName", "ControllerName")
</script>
use url in your JavaScript file.

Wanting to mix server side ASP.Net MVC expansion in javascript file, but how... RenderPartial?

I have some common javascript functionality that I want to share across several views/pages.
However I want to put some C#/ASP.net into the javascript - pulling in some data from the server.
It seems like the best option is to use a partial page, and include the javascript in that.
Just wondering if there is a javascript equivalent of the partial page?
Or is there another/better/alternative way of doing this?
EDIT:
I realise I could use ajax to pull the server code in (although how do I refer to the server, Url.Content won't work) but this code is to handle page permissions, ie the server data details what functions the user can access and the javascript functions are then used to show/hide buttons based on that. So the data needs to be present early on rather than triggering the page to be built after the ajax callback happens.
Thanks in advance,
Chris
I usually put some data that is needed by javascript into the top of the page.
I have it in the Masterpage.
After that I include the common js files. The variables defined at the top of page are available to the scripts.
Don't forget to JavascriptEncode these values. Html-Encode is not enough, it doesn't handle the '. Use Web Protection Library for it http://wpl.codeplex.com/.
<script language="JavaScript">
var controller = <%= AntiXss.JavaScriptEncode(ViewContext.RouteValues.GetRequiredString("controller")) %>;
var userRightRead = <%= AntiXss.JavaScriptEncode(Model.UserRightRead) %>;
</script>
However I want to put some C#/ASP.net
into the javascript - pulling in some
data from the server
You don't need to put any C#/ASP.NET into javascript to pull data from the server. You can simply use AJAX. Example with jQuery:
$.ajax({
url: '/home/someaction',
success: function(data) {
alert(data);
}
});
I'll normally wrap the javascript up in a class and then pass in the view model values I need.
For example with this javascript:
var testClass = function(config){
this.width = config.width;
this.height = config.height;
this.showDimensions = function(){
alert( this.width + " by " + this.height);
}
}
the view/partial view would contain:
<script>
var dim = new testClass({
width: <%=Model.Width %>
height: <%=Model.Height %>
})
dim.showDimensions();
</script>

Embed raw data in HTML to parse in jQuery

I've been living in the desktop world for most of my career, so forgive me for asking such a basic question, but I'm not quite sure where to start looking.
I want to return some raw data along with my HTML, and parse and display the data using jQuery as soon as the HTML is ready. I know roughly what my js code should look like, but I'm not sure how I should embed the raw data in my HTML.
I could use $.getJSON(), but it'd be better if I could have the data right in my HTML.
I think either json or XML would work, but what's the proper way to escape/embed/parse these when they're embedded in HTML?
Thanks in advance.
You can put the JSON data in a hidden div, then decode and use from jQuery.
For example, we'll take:
{"foo":"apple","bar":"orange"}
Escape it and put in a div:
<div id="data">%7B%22foo%22%3A%22apple%22%2C%22bar%22%3A%22orange%22%7D</div>
Then from jQuery, we can use the data:
var data = jQuery.parseJSON(unescape($("#data").html()));
So calling alert(data.foo) will give us apple.
Here's a working example.
Where and when do you want this data?
If you want it in your view, just pass the data to the view
Action/Controller:
public ActionResult MyAction()
{
ViewData["MyData"] = "this is a sample data of type string";
return View();
}
And then, somewhere in your view:
<script>
var data = '<%= ViewData["MyData"] %>';
$(document).ready(){
alert(data);
}
</script>
<h1><%: ViewData["MyData"] %></h1>
Of course, if you're working with a List<string> or `string[]', you would need to format it to proper JavaScript for jQuery to understand it.
<script>
var dataArray = [
<% foreach(string s in (string[])ViewData["MyDataArray"]){ %>
<%= s %>,
<% } %>
];
</script>
It would be getter if you generated the proper JavaScript in the action instead of the view to avoid ugly markup in your view:
public ActionResult MyAction()
{
string[] myArray = new string[]{ "hello", "wolrd" };
ViewData["MyData"] = myArray;
ViewData["JavaScriptArray"] = "[" + myArray.Aggregate((current,next) => string.Format("'{0}','{1}',", current, next).TrimEnd(new char[] { ','})) + "]";
// or you can use your favorite JavaScript serialize
return View();
}
Now you can do the following in your view:
<script>
var dataArray = <%= ViewData["MyJavaScriptArray"] %>;
alert(dataArray[0]); // alerts 'hello'
</script>
Like you said it is probably best to get it via Ajax using $.post or $.get or $(element).load() etc...
But if you must save it in the page it is common to save in a hidden field. Asp.net saves things in hidden fields using binary serialization and Base64 but you can save it as a Json string and then use it in your JS.

Categories

Resources