Can I manage C# variable into .js? - c#

I have my script.js into the folder script.
I'd like to manage, into that script, some C# variable, from a Web Form (e.g. <%= myString = 3 %>).
I think this is not possible, but maybe can I do it in some way? Thank you

Javascript is client side executed code, and C# is server side executed code. So you can't strictly make a "variable" visible, as they're two completely different code platforms/runtimes, running on two different computers. However you can still marshal the data between them in a few different ways.
Write a web service and call it via AJAX
Populate a control or your URL for your page with your data, and query it via the Javascript DOM API (or via some wrapper library like jQuery)
An example of the 2nd (since you asked):
<!-- Somewhere in your page -->
<span style="visibility:hidden" id="myData"><%= myString %></span>
// In Javascript, using jQuery:
var myData = $('#myData').text();

If the variable is directly related to a particular element on the page then you should definitely consider using the HTML5 data-* attributes to store the value. Imagine the variable pertains to the an anchor element, you could output like so:
Blah
You can then access the variables with jQuery like so $("#myLink").data("myVar") (note the camel case). jQuery will attempt to convert value to the correct type. If you want the raw value then just use the attr jQuery method like this $("#myLink").attr("data-my-var") (note the attribute name has not changed).
Alternatively you could do the following in your server-side code to output to your page:
<script type="text/javascript">
var myVar = <%= someVariableToOutput %>;
</script>
As long as this code is output above your dependent script it will be accessible as with any other JS variable.
Finally, you could execute an AJAX request when the page is loading and get the variable that way (though this may not be applicable if the data is only available during the main request)
Hope that helps

Related

How do I pass a variable from a view to a JavaScript function?

I'm working on a website that has a JavaScript function I want to call passing in a value when a hyperlink is clicked. I'm generating some table rows in the view like this:
foreach(var e in Model.Collection)
{
...
//This is just an example piece of code that tries to get the big picture
//across. I want to call the JS function below passing in the ShipAddress property
<td>#e.ShippedDate</td>
...
}
And I have a JavaScript function like this:
function popup(data)
{
$('#lblShipAddress').text(data.Address1);
...
// rest of code to fill out labels in a div
$('#divShipInfo').dialog('open');
}
I'm having issues getting the ShipAddress property(which has a number of properties i.e. Address1, Address2, etc.) passed into the JavaScript function from the View. The
href="javascript:popup(#e.ShipAddress)" part doesn't work, and I've also tried using data attributes e.g.
<a href="javascript:popup();" data-shipAddress="#e.ShipAddress" />
but have not had any luck.
EDIT: Added some clarity to what I'm looking for. If at all possible I would like to only pass the ShipAddress property to the function.
By default, just #e.ShipAddress is going to return the equivalent of .ToString(), which is not useful for your method as input. Instead, you'll want to JSON serialize the object like:
#e.ShippedDate
This will result in final html something like:
#e.ShippedDate
And so the popup method would have access to the object values.
Warning: make sure there aren't any fields on your address object that you don't want leaked to your end consumers - Json.Encode will serialize all public properties.
First, I wouldn't use javascript:popup() - try one of these. Also, don't use the quote marks with the razor syntax, or it probably won't evaluate the variable.
If none of that solves it, then it could be a timing issue. I've had a lot of trouble with MVC-controlled pages (as opposed to use JavaScript/jQuery and callbacks) not updating when you think they will. For some reason, the MVC controller deals with the button press, runs the server-side code, updates the page objects... THEN releases control to JavaScript, et. al.
It basically makes using JavaScript with the built-in Microsoft controls almost impossible.

Best way to transfer data from view to javascript

I'm working in an Asp.Net MVC 3 project where in one of my javascript file, a message is displayed to the user. This message in currently in one language but I want this message to be in multiples languages. I don't want to store theses languages directly in the javascript file but instead in a database. I want to know if it possible to transfer data (string) from the view to the javascript file.
One solution that I've found is to set data from my view in hidden fields and then extract it from my javascript file. The problem with this solution is that I must put a lot of hidden fields and this is very hard to maintain.
Is there any other solution to this problem?
You can try JavaScriptModel ( http://jsm.codeplex.com ).
With this library you can add variables by calling the following function in your controller action:
this.AddJavaScriptVariable("VariableNameInJavaScript", SomeValue);
You can pass primitive types or complex types.
Furthermore you could execute javascript functions with the following code in your controller action:
this.AddJavaScriptFunction("FunctionInJavaScript", SomeParameter, AnotherParameter);
Yes, your on the right path. All you need to do is hydrate your model appropriately and use Razor syntax to pass the value from the server to the client "along the following lines":
<script src="#Url.Content("~/scripts/yourapi.js")"></script>
<script>
yourapi.foo('#Model.SomeValue');
</script>

Passing .CS arraylist to JQuery

I am trying to create an autocomplete text box based on an ArrayList from my main page's cs.
I am fairly new to JQuery and I am wondering what the best way to call the ArrayList from that page would be.
I feel like I have search all terms possible but all I can find are AutoComplete examples that either create the Array in a variable before it executes the script or it makes a vague reference to calling a URL.
Thanks for any information on this.
This is what I have so far in my newby experience.
<script type="text/javascript">
$(document).ready(function(){
$("#example").autocomplete("Requests.aspx.cs");
});
</script>
A few things....
You don't call Request.aspx.cs (that is a code file that gets compiled). The client served page is Request.aspx, and that's what you need to call.
Since you're using the jQuery UI Autocomplete, the Request.aspx will need to respond with JSON data in the correct format (I believe it is a 3 field object with id, name and value).
Request.aspx will need to be setup to take in a parameter (I believe it is called term), do logic to lookup, and return the results of that lookup serialized as JSON. There are C# classes to help with JSON serialization.
You've got quite a few things you need to go figure out in order to achieve this. Hopefully the above will help get you started.
You can create a $.ajax request for the page Request.aspx, whose code behind should return your data. Then use the jQuery autocomplete.
Edit:
If you want to take the approach that Matthew has suggested, I would suggest checking out this page ASP.NET AJAX from ScottGu, as it describes a way to make server-side service calls directly from your javascript and should eliminate any mess JSON handling on your end.
May be you could expose some kind of restful service for this purposes.

Alternative to Query Strings to Pass Data Between ASP.Net Pages?

I am currently using a number of query string parameters to pass some data from one page to a second page (the parameters hold confirmation/error messages to display in the second page), that due to a third party product can no longer work correctly in the production environment. The user completes an action on the first page, and is then transferred to the second page. What are the possible alternatives to use instead of a query string and GET - session variables, POST data, or something completely different?
Thanks, MagicAndi.
You could create public properties in a source page and access the property values in the target page when using a server transfer. You could also get control information in the target page from controls in the source page by referencing the Page.PreviousPage property.
Both of these methods are oulined here: http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx
Both POST data and session variables would work just fine. POST data has the drawback that it can be changed by the client and session variables take up memory, so you can choose based on that. I personally don't think that you should pass such messages to the client for the reason stated above but I guess you are already doing that, so...
you can use this if you use window.open("openTheotherPage",...etc)
so form the opened page you can do something like this
var valuefromCallerPage = window.opener.document.FormNmae.textbox.value
or button or anything on the caller page

Can I stop .NET eating IDs?

I'm an Information Architect and JavaScript developer by trade nowadays, but recently I've been getting back into back-end coding again. And, whilst trying to get an HTML prototype integrated and working with our C#-based CMS, I've come to blows with our programmers over the HTML ID attributes being arbitrarily rewritten by .NET for form elements.
I can understand the code-behind reasoning for .NET changing IDs, but the fact you can no longer use IDs when trying to develop e.g. jQuery enhanced interfaces is causing some friction. What can I do to work around this?
I've tried using the class attribute instead, but that's really crappy, not what it's meant for and doesn't get around that problem of .NET effectively changing rendered source on the fly. It also means that CSS is less useful now and less efficient to create and maintain.
Any tips or advice greatly appreciated--anything for a few less sleepless nights...
The short answer is no, with webforms the id can always be rewritten depending on the nesting of the element. You can get access to the id through the ClientID property, so you could set the ids into variables in a script at the end of the page/control then put them into jQuery.
something like this:
<asp:button id="ImAButton" runat="server">Click Me</asp:button>
<script type="text/javascript">
var buttonId = "<%=ImAButton.ClientId%>";
$("#"+buttonId).bind('click', function() { alert('hi); });
</script>
It's a hack I know, but it will work.
(I should note for the un-initiated, I'm using the Prototype $ get by id method there)
One method is to override the ID's manually:
public override string UniqueID
{
get { return this.ID; }
}
public override string ClientID
{
get { return this.ID; }
}
Rick Strahl wrote a blog post with some more information on that approach.
Look at ASP.Net MVC - it addresses the over-kill object hierarchies that ASP.Net generates by default.
This site is written in MVC (I think) - look at it's structure. Were I working on a new project right now I would consider it first
If you're stuck with basic ASP.Net then be careful overriding the ClientID and UniqueID - it tends to break many web controls.
The best way I've found is to pass the unreadable ClientID out to the Javascript.
You can extend .net controls and make them return actual id's when related properties are called.
ClientID is the id attribute and UniqueID is the name attribute of html elements. So when you create a textbox like the following and using this instead of the textbox in framework, you make id and name attributes render as the same as the server-side id.
public class MyTextBox : TextBox
{
public override string ClientID { get { return ID; } }
public override string UniqueID { get { return ID; } }
}
To use this new user control, basically register this control as you would do for a custom user control (you can do is in web.config so you won't have to do it in all your pages):
<%# Register Assembly="MyLibrary" NameSpace="MyLibrary.WebControls" TagPrefix="MyPrefix" %>
And use it like you would use a text box:
<MyPrefix:MyTextBox ID="sampleTextBox" runat="server" />
Personally, I use a set of methods I have developed for bridging the server-side ASP.NET "magic" (I have yet to use the MS MVC stuff yet) and my client-side code because of the munging of the IDs that happens. Here is just one that may or may not prove useful:
public void RegisterControlClientID(Control control)
{
string variableDeclaration = string.Format("var {0} = \"{1}\";", control.ID, control.ClientID);
ClientScript.RegisterClientScriptBlock(GetType(), control.ID, variableDeclaration, true);
}
So, in your server-side code you simply call this and pass in the instance of a control for which you want to use a friendlier name for. In other words, during design time, you may have a textbox with the ID of "m_SomeTextBox" and you want to be able to write your JavaScript using that same name - you would simply call this method in your server-side code:
RegisterControlClientID(m_SomeTextBox);
And then on the client the following is rendered:
var m_SomeTextBox = "ctl00_m_ContentPlaceHolder_m_SomeTextBox";
That way all of your JavaScript code can be fairly ignorant of what ASP.NET decides to name the variable. Granted, there are some caveats to this, such as when you have multiple instances of a control on a page (because of using multiple instances of user controls that all have an instance of m_SomeTextBox within them, for example), but generally this method may be useful for your most basic needs.
What I usually do is create a general function that receives the name of the field. It adds the usual "asp.net" prefix and returns the object.
var elemPrefix = 'ctl00-ContentPlaceHolder-'; //replace the dashes for underscores
var o = function(name)
{
return document.getElementById(elemPrefix + name)
}
With that you can use this kind of calls in jQuery
$(o('buttonId')).bind('click', function() { alert('hi); });
You definitely don't want to hard-code the asp.net-generated ID into your CSS, because it can change if you rearrange things on your page in such a way that your control tree changes.
You're right that CSS IDs have their place, so I would ignore the suggestions to just use classes.
The various javascript hacks described here are overkill for a small problem. So is inheriting from a class and overriding the ID property. And it's certainly not helpful to suggest switching to MVC when all you want to do is refactor some CSS.
Just have separate divs and spans that you target with CSS. Don't target the ASP.NET controls directly if you want to use IDs.
<div id="DataGridContainer">
<asp:datagrid runat=server id="DataGrid" >
......
<asp:datagrid>
</div>
If you're using jQuery then you have loads of CSS selectors and jQuery custome selectors at your disposal to target elements on your page. So rather than picking out a submit button by it's id, you could do something like:
$('fieldset > input[type="submit"]').click(function() {...});
I can see how the .NET system feels less intuitive, but give it a chance. In my experience it actually ends up creating cleaner code. Sure
<asp:button id="ImAButton" runat="server">Click Me</asp:button>
<script type="text/javascript">
var buttonId = <%=ImAButton.ClientId%>
$(buttonId).bind('click', function() { alert('hi); });
</script>
works fine. But this is suffers from not being modular. What you really want is something like this:
<script type="text/javascript">
function MakeAClick(inid)
{
$(inid).bind('click', function() { alert('hi); });
}
</script>
and then later with your code on the java side or the C# side you call MakeAClick. Of course on the C# side it makes more sense, you just ClientID in there.
Maybe this is the real problem with the code you are reviewing.
A much better approach would be to use the ClientIDMode and set it to static. You can even set it for a specific page or globally in the web.config file. Then you never have to deal with this issue again and your JQuery is much cleaner.
Top of page:
<%# Page Title="" ClientIDMode="Static" Language="C#" CodeBehind="..." Inherits="WebApplication1.WebForm2" %>
On control only:
<asp:Panel runat="server" ClientIDMode="Static"></asp:Panel>

Categories