Is there a way to use "<%= someObject.ClientID %>" in an external javascript file?
Asked Answered
H

8

33

Is there a way to use "<%= someObject.ClientID %>" in an external javascript file?

If I use the code

<%= someObject.ClientID %>

in a script tag inside my as(c/p)x page, it works fine. On the rendered page, the ClientID is resolved. Howvever, if I put in an external JS file and just add:

It doesn't. Is there a way to do this or am I stuck with leaving that code in the as(c/p)x file?

Side question -- what is the act of doing <%=... %> in your markup file called?

Herbivore answered 30/6, 2011 at 23:8 Comment(2)
JS files are not processed by the ASP.NET runtime, so it won't work. I too hate the massive amount of code that ends up inline because of this... You can make functions and pass parameters, but the server side blocks can't go into the JS files.Landlordism
Certainly there is a way to configure IIS so that JS files also go through the same pipeline as aspx/ashx files?Precedent
J
20

This is totally possible.

In your .aspx page, create a script reference to an aspx page that contains your javascript code:

<script src="../MyJavaScriptFile.js.aspx" type='text/javascript'></script>

Then, in MyJavaScriptFile.js.aspx you can write the following:

<%@ Page Language="C#" AutoEventWireup="false"  ContentType="text/javascript" %>

<% 
    var foo = new Whatever();
    foo.ClientId = 123;
%>

// Start Javascript
var clientId = <% HttpContext.Current.Response.Write(foo.ClientId); %>;

.

Also helpful - this technique supports querystring parameters:

 <script src="../MyJavaScriptFile.js.aspx?username=<% somevalue %>" 
       type='text/javascript'></script>

Then, in MyJavaScriptFile.js.aspx, I can reference the value with

var username = '<% Request.QueryString["username"] %>';

It's not the "best practice" way to do things, but it gets the job done in a way that my caveman brain can understand without resorting to fancy workarounds.

Jolinejoliotcurie answered 1/7, 2011 at 0:12 Comment(11)
How do you reference for example a button client id in this way?!...you will use just a string, OK so why don't we do that in javascript file itself?!....Filip
@Filip - There are a couple ways. You can pass it as a url parameter in the reference to the file <script src=myurl.js.aspx?buttonClientID=<%= Btn.clientID %> ></script> or you can save the button's client id to a session variable and reference it in your .js.aspx file with <% Request.QueryString["SessionVariableName"] %>Jolinejoliotcurie
Don't use <% Request.QueryString[...] %> in javascript files, it is vulnerable to XSS, and that means if the value somehow shared between all users then malicious user can even hijack all users sessions...Filip
If you're not comfortable using Request.Querystring, store it as a session variable then and reference it that way in your file.Jolinejoliotcurie
@Filip - How would it not work? The clientID gets generated, saved to session, and then the Javascript file uses that ID to reference its target. The only way they change is if you manually change them in the pres layer. Either way, the javascript file is using the correct ID.Jolinejoliotcurie
Storing client ids in session because we are not comfortable with dynamic script tag in page!...Filip
You're right about session, but we have to check if it's null and storing client ids in it again yes yes, you're right,But what if i have a save button in a page an another one in another page with the same name but not same control hierarchy!???Filip
What if we're using other session modes than inprocess, making network busy for saving each client id!...each page with 10 control and each user 10 request means 100 request for each user just for storing client ids in, SqlServer or StateServer. what i'm saying is session is not right place for client id neither QueryString...imagine if google or yahoo do things like thisFilip
Your assuming that he's going to store every single client ID in his page in session state. If he's only going to store a single client ID, it's not a big deal at all.Jolinejoliotcurie
no, storing client-id in javascript using querystring is not a problem neither security risk, like just i said session-state is not right place for client id not even QueryString...Filip
I get an HTTP 500 on MyJavaScriptFile.js.aspx... any ideas why?Anglonorman
F
33

If you really want to do this you can do following

<%@ Page ContentType="text/javascript" Language="C#" AutoEventWireup="false" %>
<%@ OutputCache Duration="86400" Location="Any" VaryByParam="None" %>

var time = "<%= DateTime.Now.ToString() %>";
alert(time);

And then reference it in your page

<script src="Scripts/file.aspx" type="text/javascript"></script>

Note When using mentioned method, the only way to pass target page controls client-ids, is to store client id as string in a public property, and then reference it using new instance of that page

If the only thing that made you to do this is client-id then you can use following ASP.NET 4 feature

<any-tag ID="myCustomId" runat="server" ClientIDMode="Static" />

You can also put all your client-ids in C# class then serialize it using JSON and render it in script tag, could be smart way for ASP.NET prior to version 4.

Note using serialization method you have possibility to change any tag ids without worrying about javascript element usages, remember that this is not even possible with ASP.NET 4 ClientIDMode

See

Page-Code-File

public partial class About : System.Web.UI.Page
{
    ...

    protected string GetTagIds()
    {
        return new JavaScriptSerializer()
                    .Serialize(new
                     {
                            myButton = Button1.ClientID,
                            myCalendar = Calendar1.ClientID
                     });
    } 

    ...
}

Page-ASPX

<script type="text/javascript">
    var IDs = <%= GetTagIds() %>;
</script>

Anywhere

<script type="text/javascript">
    IDs.myCalendar.doSomthing...
</script>

There is another option that you can pass all javascript files to ASP.NET handler but i don't recommend it, because of just a single javascript file you make asp.net handler busy.

Code Blocks

<% inline code %>

This is an inline code definition which you can execute codes in it :

<% Response.Write("Hi"); %>

<% while(i < 0) { %>
      <% 
         Response.Write(i.ToString()); 
         i++;
      %>
<%}%>

Note You have to include ';' on end of each statement when using inline code with C# language, you can change inline language using page directive language attribute

<%= inline expression %>

This one equals to calling Response.Write your self, see:

<%= "Hi" %> equals to <% Response.Write("Hi"); %>

Note You shouldn't include ';' when using inline expression

<%: encoded inline expression %>

This one equals to :

Response.Write(HttpUtility.HtmlEncode("<script type="text/javascript">alert('XSS');</script>"))

And is used for security reasons --XSS, any input HTML to this one outputs HTML encoded text which is safe to display user entered contents in page.

Note You shouldn't include ';' when using encoded inline expression

<%$ expressionPrefix: expressionField %>

This one is expression that you can use to bind values from ConnectionStrings, Resources and AppSettings

expressionPrefix possibilities is

  • AppSettings
  • ConnectionStrings
  • Resources

expressionField is the property of specified expressionPrefix that you need, see:

// AppSettings
<asp:Label ... Text="<%$ AppSettings: version %>" />

// ConnectionStrings
<asp:SqlDataSource ... ConnectionString="<%$ ConnectionStrings:dbConnectionString %>" />

// Resources
<asp:Label ... Text="<%$ Resources: Messages, Welcome %>" />

Note You shouldn't include ';' and you can use expressions only on ASP.Net controls attributes

<%# data-binding expression %>

You can use this anywhere inside controls with data-binding support, and usually is used by Eval and Bind methods.

<asp:DropDownList SelectedValue='<%# Bind("CategoryID") %>' 
                  DataSourceID="CategoriesDataSource"
                  DataTextField="CategoryName"
                  DataValueField="CategoryID"
                  runat="Server" />

Which one Eval or Bind?

Using Bind you have two-way binding set over specified attribute of ASP.NET control see the mentioned drop-down, it is using Bind that means if end-user selects a value and then submit the page, drop-down will not loose its selected value.

Use Eval just for displaying data.

<asp:FormView ...>
     <ItemTemplate>
          <a href='Eval("Link")'>Eval("LinkText")</a>
     </ItemTemplate>
</asp:FormView>

<%@ text template directive %>

<%@ Page ...%>
This one is Page Directive

<%@ OutputCache...%>
This one is OutputCache Directive and so on...
Filip answered 1/7, 2011 at 16:39 Comment(0)
J
20

This is totally possible.

In your .aspx page, create a script reference to an aspx page that contains your javascript code:

<script src="../MyJavaScriptFile.js.aspx" type='text/javascript'></script>

Then, in MyJavaScriptFile.js.aspx you can write the following:

<%@ Page Language="C#" AutoEventWireup="false"  ContentType="text/javascript" %>

<% 
    var foo = new Whatever();
    foo.ClientId = 123;
%>

// Start Javascript
var clientId = <% HttpContext.Current.Response.Write(foo.ClientId); %>;

.

Also helpful - this technique supports querystring parameters:

 <script src="../MyJavaScriptFile.js.aspx?username=<% somevalue %>" 
       type='text/javascript'></script>

Then, in MyJavaScriptFile.js.aspx, I can reference the value with

var username = '<% Request.QueryString["username"] %>';

It's not the "best practice" way to do things, but it gets the job done in a way that my caveman brain can understand without resorting to fancy workarounds.

Jolinejoliotcurie answered 1/7, 2011 at 0:12 Comment(11)
How do you reference for example a button client id in this way?!...you will use just a string, OK so why don't we do that in javascript file itself?!....Filip
@Filip - There are a couple ways. You can pass it as a url parameter in the reference to the file <script src=myurl.js.aspx?buttonClientID=<%= Btn.clientID %> ></script> or you can save the button's client id to a session variable and reference it in your .js.aspx file with <% Request.QueryString["SessionVariableName"] %>Jolinejoliotcurie
Don't use <% Request.QueryString[...] %> in javascript files, it is vulnerable to XSS, and that means if the value somehow shared between all users then malicious user can even hijack all users sessions...Filip
If you're not comfortable using Request.Querystring, store it as a session variable then and reference it that way in your file.Jolinejoliotcurie
@Filip - How would it not work? The clientID gets generated, saved to session, and then the Javascript file uses that ID to reference its target. The only way they change is if you manually change them in the pres layer. Either way, the javascript file is using the correct ID.Jolinejoliotcurie
Storing client ids in session because we are not comfortable with dynamic script tag in page!...Filip
You're right about session, but we have to check if it's null and storing client ids in it again yes yes, you're right,But what if i have a save button in a page an another one in another page with the same name but not same control hierarchy!???Filip
What if we're using other session modes than inprocess, making network busy for saving each client id!...each page with 10 control and each user 10 request means 100 request for each user just for storing client ids in, SqlServer or StateServer. what i'm saying is session is not right place for client id neither QueryString...imagine if google or yahoo do things like thisFilip
Your assuming that he's going to store every single client ID in his page in session state. If he's only going to store a single client ID, it's not a big deal at all.Jolinejoliotcurie
no, storing client-id in javascript using querystring is not a problem neither security risk, like just i said session-state is not right place for client id not even QueryString...Filip
I get an HTTP 500 on MyJavaScriptFile.js.aspx... any ideas why?Anglonorman
S
3

I like to embed a single line of javascript on my page.

<script type="text/javascript">
   Application.init({variable1: "value1", variable2: "value2"...});
</script>

It's poor practice to have a ton of javascript rendered on your page, but it is common to need to pass initialization values to your javascript from the server. This allows you to do it without a whole bunch of unnecessary code and without polluting the global namespace with callback functions. I usually replace Application with some project specific global wrapper.

Sherrisherrie answered 30/6, 2011 at 23:27 Comment(0)
T
3

This adds a bit more HTML but it works; wrap each server control in a div...

<div id="myContainer">
    <asp:HiddenField ID="hdMyControl" runat="server" /></div>

Set the HiddenField's value in the code behind

hdMyControl.Value = "something";

Then in your external JS file you can get the server control's value

$(document).ready(function () {
    var myValue= $('#myContainer input[type=hidden]').val();

I'm not sure that it matters, but I'm adding the script reference to the page via the codebehind using RegisterClientScriptBlock

Teodorateodorico answered 17/7, 2013 at 16:55 Comment(0)
N
2

You could create an empty callback function in the external file:

var MyCallback = function () { };

And then in the asp/cx do something like:

MyCallback = function () {return "<%= someObject.ClientID %>";}

And then, back in your external file:

var myClientID = MyCallback();
Normy answered 30/6, 2011 at 23:16 Comment(2)
@myself, I guess it's not really a callback but more a function variable? hook? delegate?Normy
If you're just trying to deal with the way ASP.NET builds-up server control id's, and don't want to deal with finding them all everytime it changes, use ClientIDMode="Static", and it won't change. Be careful not to do this on two controls with the same id, of course.Normy
G
1

No, it won't work like that because the javascript file is being transmitted independently as a separate file and it isn't parsed by ASP.NET on the way out, while your aspx file IS being parsed and the .NET engine is replacing the tag w/ the actual value.

Now when your objects call those JS functions, what they could do is pass references to themselves into the function, or even pass in a dictionary list of some sort with your own key for what the control is and the assigned name.

One thing to think about as well - IF you are going to make a JS file independent of an ASPX page, then that JS file absolutely should not presume to know anything about the specific controls of the aspx file that calls it - because later on someone else might decide, "Oh that's a good JS file, I'll incorporate it too" and it won't work for them cause their objects wont match yours. Thus the pattern you should follow would have to be more generic - thus why you'd want to pass in references or lists of identifiers.

Gorgonzola answered 30/6, 2011 at 23:20 Comment(0)
I
1

The server tag <%= %> is used to enter code that is processed on the server.

You cannot use <%= someObject.ClientID %> in an external js file because the server tag is an asp.net thing and js doesn't know what this is.

If you use ASP.NET 4 you can set the client id in the properties of the control making it predictable.

If you don't use ASP.NET 4 you could put this client id in a hidden field or an inline js variable.

Idyllist answered 30/6, 2011 at 23:22 Comment(0)
L
-5

Use the standard prefix identifier in script source files:

document.getElementById("ctl00_ContentDetail_textboxelename").value = "";
document.getElementById("ctl00_ContentDetail_radioORcheckboxelename").checked = false;
document.getElementById("ctl00_ContentDetail_elename").style.visibility = "hidden";
var javaele = document.getElementById("ctl00_ContentDetail_elename");
var boolIsChecked = document.getElementById("ctl00_ContentDetail_radioORcheckboxelename").checked;
Lynnet answered 21/3, 2012 at 17:25 Comment(1)
No, no, NO. Don't EVER do this. As soon as you add another container control to your page the IDs will all change and your JS will break. Just no.Zook

© 2022 - 2024 — McMap. All rights reserved.