0

I'd like to start by saying that my code is working perfectly, this is more a "how best to do it" kind of question.

So I have code like this in my .aspx file:

    function EditRelationship() {
        var projects=<%= GetProjectsForEditRelationship() %>;

        // fill in the projects list
        $('#erProjectsSelect').empty();
        for(var i in projects)
            $('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');

        var rels=<%= GetRelationshipsForEditRelationship() %>;

        // etc
    }

Again, it's working fine. The problem is that VS2008 kinda chokes on code like this, it's underlining the < character in the tags (with associated warnings), then refusing to provide code completion for the rest of the javascript. It's also refusing to format my document anymore, giving parsing errors. The last part is my worst annoyance.

I could put some of these in evals I guess, but it seems sorta dumb to add additional layers and runtime performance hits just to shut VS up, and it's not always an option (I can't remember off the top of my head where this wasn't an option but trust me I had a weird construct).

So my question is, how do you best write this (where best means fewest VS complaints)? Neither eval nor ajax calls fit this imo.

7
  • I'm guessing GetProjectsForEditRelationship() and GetRelationshipsForEditRelationship() return comma delimted strings or an array? Commented Jan 7, 2011 at 15:23
  • Yep, basically JSON data, so both eval and ajax calls would work. I just don't want the overhead for such little benefit. I'm pretty sure I'm stuck with this, but never hurts to ask! Commented Jan 7, 2011 at 15:26
  • 1
    append quotes as it's a variable, like var projects='<%= GetProjectsForEditRelationship() %>'; - I use this all the time, VS2008 and 2010 do not say it's wrong and keeps giving me intelisense. Commented Jan 7, 2011 at 15:31
  • 1
    On a side note, is projects[i][1] a user-editable value? If so you might have an XSS vulnerability :) Commented Jan 7, 2011 at 15:35
  • 1
    @Blindy as an aside, I think it is very important to always try to strike a balance between code that is elegant in both performance and the way it is written. Glad to see you think the same way. I'm working on a site now where every line is a response.write so you can't even view the page in the designer. Not that I need to ;) Commented Jan 7, 2011 at 15:47

5 Answers 5

2

If your aim is to reduce VS complaints, and if you are running asp.net 4 (supporting Static client Ids), maybe a strategy like the following would be better?

  1. Create a ASP:HiddenField control, set its ClientIdMode to "Static"
  2. Assign the value of GetRelationshipsForEditRelationship() to this field on page load
  3. In your javascript, read the value from the hidden field instead, I assume you know how to do this.

It's more work than your solution, and you will add some data to the postback (if you perform any) but it won't cause any VS complaints I guess :)

Sign up to request clarification or add additional context in comments.

3 Comments

Well, I just saw Hunter's answer...probably much better than mine :)
Can skip 2, I can just assign its value like <asp:HiddenField Value="<%= ... %>"... />. Interesting idea!
Don't sell your idea short, I like the fact that the array declaration is in the same code page and it's clear how to find it (instead of searching the declaration in code behind by name).
2

You could do this from your page in the code-behind

ClientScript.RegisterArrayDeclaration("projects", "1, 2, 3, 4");

or to construct something like JSON you could write it out

ClientScript.RegisterClientScriptBlock(GetType(), "JSONDeclarations", "your json stuff");

UPDATE Based on my comment

<script id="declaration" type="text/javascript">
    var projects=<%= GetProjectsForEditRelationship() %>;
    var rels=<%= GetRelationshipsForEditRelationship() %>;
</script>
<script type="text/javascript">
    function EditRelationship() {
        // fill in the projects list
        $('#erProjectsSelect').empty();
        for(var i in projects)
            $('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');
}
</script>

4 Comments

Hm, perhaps, although this would make the code less clear (you'd have to search the array name in code behind to see what's in it), plus you're polluting the global namespace inside. But it's something to keep in mind for sure.
well if the goal is to maintain the intellisense I don't know what you're options are since the inline server tags will blow that up. Maybe you could use 2 <script> blocks? One to define the JSON values and one for your code? That might not blow up intellisense
worth a shot. Rendering server tags should blow up the js intellisense because, as far as its concerned, it is invalid.
If you say so. The way I see it, the markup engine should realize that it's a server tag and treat it as such. They already do that for actual ASP tags, so why not JavaScript too?
0

I don't have VS2008 installed to test with, so take this with a grain of salt, but have you tried something like this?

var projects = (<%= GetProjectsForEditRelationship() %>);

Something like that might trick the JavaScript parser into ignoring the content of your expression.

For what it's worth, VS2010 correctly parses and highlights your original code snippet.

3 Comments

I agree with @Dave. I just copied and pasted your code and the IDE interpreted it correctly.
Aww, I had high hopes for this one, but no dice :(
@Doug, in VS2008? I just tried it again on another piece of code, it's still giving me its warning.
0

Is it an option to move this to VS2010? I just copied and pasted your code and the IDE interpreted it correctly.

1 Comment

I figured it would, and we'll move to vs2010 eventually, but it's not an option yet :(
0

The best solution is to put javascript in a separate file and avoid this entirely. For this particular function, you're doing server-side work. Why not build the list of options that you intend to add dynamically in codebehind, put them in a hidden div, and then just have jQuery add them from the already-rendered HTML?

If you have a situation where you really want to dynamically create a lot javascript this way, consider using ScriptManager in codebehind to set up the variables you'll need as scripts and register them, then your inline script won't need to escape

ScriptManager.RegisterClientScript("projects = " + GetProductsForEditRelationship());

(Basically, that is not the complete syntax, which is context dependent). Then refer to "projects" in your function.

(edit)

A little cleaner way to do this on a larger scale, set up everything you need like this in codebehind:

string script = "var servervars = {" +
  "GetProductsForEditRelationship: " + GetProductsForEditRelationship() + 
  "GetRelationshipsForEditRelationship: " + GetRelationshipsForEditRelationship() +
"}"

and refer to everything like:

servervars.GetProductsForEditRelationship

If you do this a lot, of course, you can create a class to automate the construction of the script.

5 Comments

I didn't give you the -1, but your (2nd) idea isn't any different from hunter's answer. Same hard-to-find-what-the-hell-that-array-is-at-a-glance problem :)
I have thick skin anyway :) You could use a convention that avoid this, e.g. just call your js variables the same name as the function or something like cbfunc_GetProductsForEditRelationship. A nicer solution which I've used in this kind of situation is to create a js object that encompasses everything you use in your associated js and build it in codebehind (edit in a sec)
Erm.. maybe it's too early in the morning, but wouldn't VS complain about the inline server tag in your code? That's what I'm trying to avoid in the first place.
Once you eliminate the need to escape to inline code, by making everything available as javascript variables in advance, you don't have any reason to include it directly in the markup. Put it in a JS file where VS will not complain.
I removed the naming container part of that edit. Sorry, it is early in the morning. I was trying to abstractly describe something that I actually implemented. In order to make this work with multiple instances of a control (for example) and be naming container safe you have to set up all your functions to accept the javascript object that's dynamically created as a parameter. Probably getting way far afield here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.