Ryan Ternier

Killer ASP.NET ninja coding monkeys do exist!

October 2007 - Posts

Two ASP.NET features that are usually missed or misunderstood...T

Enter the Tilde (~)

Browsing the asp.net forums I notice a lot of people putting the '~' (tilde) character on every control that has some sort src or href.  Many think that the tilde character is a regular character that deals with file locations. Much like: /, ../, ../../ etc.

However, this little angle is actually an ASP.NET character that is a shortcut for"   HttpRuntime.AppDomainAppVirtualPath. (say that 10x in a row). This property refers to the virtual application root - not the root of the web server.  Remember that a Virtual Directory is in fact an Application (Server 2000 / XP). You'll notice that in Vista that the IIS team has gone the better rout and actually calls them "Applications" while still having the ability to have a virtual directory that functions as a directory.

So how do we use this character?

here are some examples.

If my Folder structure is as follow:

  • Website
    • Images
    • CSS
    • Admin

I have a master page within my main website, and content pages in my Admin. One thing newer web developers will do is declare an image like:

<img src="Images/MyImage.png" alt="my Image" />

That works for everything in the root directory, however once you get into the Admin directory - all images are broken.  A way to resolve this is:

<img src="http://weblogs.asp.net/Images/MyImage.png" alt="my Image" />

This can also lead into issues if you have a more complex structure. A quick way to resolve this is:

<asp:image id="myImage" runat="server" ImageUrl="~/Images/MyImage.png" AlternateText="My Image" />

This will always go to the root of your application and then to the Images directory.  This is very useful with Hyperlinks when you are working with multiple directories.

 

Enter the ALT-SHIFT (Really... ALT-SHIFT)

I've heard about this but I've always just stored this away in the back of my mind. This little button combo allows you to select VERTICALLY in Visual Studio.

 

Capture 

So, besides the nice little vertical line, what are the uses of this?

  • Easy way to remove a single line of characters (say Line numbers from an online post) without having to format a bunch of things
  • Easy way to remove comments if you commented out lines (You can use the shortcuts: CTRL E+C to commend and CTRL E+U to uncommented)
  • Quickly change values or remove values in XML.
  • Many many more.

Needless to say it's a beautiful tool that exists in Visual Studio (not just ASP.NET).

Fancy Button 2.0 (Not A Link button)

I got a shwack of feedback and comments from my recent post: Get rid of regular buttons, use Link Buttons.  I actually thought my solution was a great one, apparently I was a bit off base. That's not to say that my solution was totally wrong - Yes I'm stubborn... but I do admit that I am "occasionally" wrong... occasionally...

From the feedback, I decided to make a new "better looking" button. This one is about the same amount of work as the previous, but I believe this one is up to standards - which was the biggest subject from the feedback.

Another comment I got was regarding users might be confused because it was a link, and not a button. If they look the same, the user will never be able to tell. (I have yet to see a user that looks at the markup of a web application and gets their underwear in a knot because something that is supposed to be an <input /> is an <a />... though I'd really like to see it  :P ).

So let's look at the markup of this new thing:

    <button id="btnTest" runat="Server" type="button" class="nButton" onserverclick="btnTest_ServerClick">

        <div class="login"></div>

        <div>This is my button</div>

    </button>

I have changed this to use the <button> element. The <button> element allows you to further style what the button looks like.

I used <div> elements so I can control the vertical alignment of the text - as well as further styling if needed.

Here's my CSS:

.nButton

{

    background-color:#84A1D6;

    border:solid 2px #415D9B;

    min-width:70px;

    height:23px;

    padding-left:3px;

    vertical-align:middle;

}

 

.nButton:hover

{

    background-color: #a0bdf2;

}

 

.nButton div

{

    float:left;

}

 

.nButton .login

{

    vertical-align:middle;

    background-image:url(Images/save.png);

    background-repeat:no-repeat;

    background-position:left top;

    width:16px;

    height:16px;

}

Very similar to my last post.  This functions the same, and it has the same functionality as a regular <asp:button />.

Now let's see what it looks like:

new button

That made my day... or did it....    Here is what I get when I surround ALL my markup with a <button>.

big button

Now I wonder how many that read this are going to go to their websites and try it out....

Posted: Oct 26 2007, 03:18 PM by Ryan Ternier | with no comments |
Filed under: , , ,
Vista and the annoying French characters

Since I've installed MS Vista I've been plauged with getting characters like: É, >, ^^,`` when I wanted characters like ?,|,}," (note those are the exact same keys that did this, i just toggled my settings... keep reading).

so what does this?

Pressing the left CTRL + SHIFT keys at the same time toggles a weird setting that does this. I assume it's on canadian keyboard only who have the language set to Canadian English (because all know Canadian Enlish is proper English eh?).

So if you find yourself all of a sudden churning out weird characters when you're typing along, try pressing the left CTRL + SHIFT keys at the same time to switch it back over (You might need to press them a couple times).
 

Posted: Oct 26 2007, 09:43 AM by Ryan Ternier | with 72 comment(s) |
Filed under:
FireFox Add-on - ThumbStrips

I just noticed this amazing Add On for Firefox. Normally I would not blog about things like this, but this addon is very useful. How often have you been trying to find a site you went to yesterday, and you spend 10 minutes clicking through each entry in your browser history, trying to find the site you were on.

What ThumbStrips does is take a quick snapshop of that site and save it so you have a visual history of that site. This is getting added right under FireBug for useful addons for Firefox.

Head on over to Firefox Addons to check this addon out.

 

Posted: Oct 25 2007, 04:28 PM by Ryan Ternier | with no comments |
Filed under:
Get rid of regular buttons, use link buttons

For the past 3 years I have been pushing my managers and especially the teams I work with that the web applications we make need to be visually appealing. The graphics designers I know can do amazing things. My friend Steve Sereda is an amazing graphics designer and he created some awesome skins for me for the time we worked together.

I've done a few posts leading up to this one. It all started with my post on UpdatePanel, FireFox and the Default Button, where I talked about how to get the default button working in FireFox. At this point I was in the process of moving all buttons over to fancy LinkButtons. I then wrote about CSS Pseudo Classes and their uses (which are many), and finally I finished my last post on A LinkButton, DefaultButton, UpdatePanel and FireFox, where I discuss how to get FireFox to use a LinkButton (Anchor tag) as a default button.

So let's talk about Buttons. Buttons provide functionality, and 99% of users know when they click on a button that some sort of action is going to happen. Many buttons look like this: 

button

Now, besides the ugly border my snipping tool puts in, that button isn't that great. But should that matter? Isn't a button there to tell the user that clicking it will invoke some sort of procedure? Correct. By general standards Buttons should invoke functions, while links should be directional. However, who said a button had to be grey and ugly?

ASP.NET has the LinkButton. It gets rendered as an <a /> (anchor) tag, and because of that we can do something like this:

3 buttons

Wow, that looks way better than regular buttons. What about this:

delete

I've grown tired of using JavaScript confirm boxes. I've decided to switch to modal windows. (yes yes I know my spacing isn't right....). You can see the nice presentation, and notice the spacing... isn't that amazing?!

There's a trick to these buttons, and unfortunately you do have to put more work into them. I could make a button like this a userControl/CompositeControl, but for what I need them for, that's too much work.

Let's look at the markup I use for these buttons. This will give you more clarity when you see the CSS.

<div class="button">

   <asp:LinkButton ID="btnSave" runat="Server" CssClass="bSave" Text="Save User" OnClick="btnSave_Click"  ValidationGroup="userDetails"  UseSubmitBehavior="false" />

</div>

<div class="button">

    <asp:LinkButton ID="btnCancel" runat="Server" CssClass="bCancel" Text="Cancel" OnClick="btnCancel_Click" CausesValidation="False"   UseSubmitBehavior="false" />

</div>

<div class="button">

    <asp:LinkButton ID="btnDeleteUser" runat="Server" CssClass="bDelete" Text="Delete" UseSubmitBehavior="false" />

</div>
<div class="clear"></div>

You see that I have 3 div's, and in each div I have a LinkButton. Under the LinkButtons I have a single div with the "clear" class. My clear class does clear:both;. It clears the floats that all of these div's have.

Here's the CSS

.button

{

    background-color:#84A1D6;

    border:solid 2px #415D9B;

    margin:5px;

    min-width:70px;

    height:20px;

    float:left;

    padding-left:3px;

}

 

 

.button a

{

    display:block;

    padding:2px 5px 2px 20px;

    min-width:70px;

}

 

.button:hover

{

    background-color: #a0bdf2;

}

 

.button a:active

{

    border-top:solid 1px black;

}

 

 

/* Button Style */

.button a.bLogin

{

    background-image: url(Images/Login.png);

    background-position:left;

    background-repeat:no-repeat;   

}

 

.button a.bSave

{

    background-image: url(Images/Save.png);

    background-position:left;

    background-repeat:no-repeat;   

}

 

.button a.bCancel

{

    background-image: url(Images/Cancel.png);

    background-position:left;

    background-repeat:no-repeat;   

}

You can notice that each .button class is floating left. I need to use Block elements for these buttons so I can apply padding, margin's etc. You cannot do that to an inline element. Seeing they're block, I want them line up, so I float them.  You can also see that my .button a contains the same width as the parent .button, this is because I want the entire button to be clickable, not just the link portion.

I am also using pseudo classes for this. You can see the :hover and the :active. This gives my buttons "hover" and "click" styles without having to code any javascript. (IE7 and FF).

And that is all you need to do.

Like I said, it's a tiny bit more markup and some small CSS, however, the outcome of this work is well worth it. It gives a whole new presentation to your application.

A LinkButton, DefaultButton, UpdatePanel and FireFox

What are we going to do today Brain? Today Pinky? We are going to TAKE OVER THE... learn to use the stuff in the title... 

I recently did a post regarding An UpdatePanel, FireFox and the Default button. One thing that has stumped many ASP.NET Developers is... what about the @#%)&* Linkbutton! I can click it... but I WANT TO PRESS ENTER!

As more and more websites are becoming more visual appealing the "button" is getting it's due and is being chucked off of the 50th story window and smashing into all those ugly cars on the ground. So what can we use instead? An image button is great, but it has design issues that are hard to get out of.

A LinkButton is a great tool. It renderes as an anchor (<a ... />) tag, and you can add some funky CSS style to it. Later today I'll be updating my projects site with some examples on building some very COOL linkbutton's.

So, how do we get the link button to actually do something useful when someone presses enter?

So here we go. Let's start off with some script:

 

    <script type="text/javascript">

        function keyPress(evt)

        {

            if(evt.which || evt.keyCode)

            {

                if((evt.which == 13) || (evt.keyCode == 13))

                {

                location =    document.getElementById('<% =btnLogin.ClientID %>').href;

                return false;   

            }

                return true;

            }

        }

 

    </script>

Key 13 is the Key code for the enter button. So whenever this function is called, and the KeyCode is 13 (my enter button), change the location of this document. Note that location is not a variable, changing that will redirect the browser.

We also need to return false. Why? Whenever a link button is activated through.. "enter" it will just refresh the form. Ohhh, just like the button in FireFox. Yes Pinky.. just like that.  Remember that the <asp:linkButton /> gets rendered as an anchor tag... so what does the anchor tag NOT have? a Click event. Remember default buttons fire a click event, which is how they work - seeing an Anchor tag does not have this, this won't work. The form is just submited without the __EVENTTARGET parameter.

There is one solution that creates their own "click" event for the LinkButton. You can look at it here (this solution does work as well, i just found it too much). I wanted something simpler, Simple is key.

Ok back on track.

Our JavaScript is called via the keypress on textboxes(<input type="text />) or textareas.  We need to add the folowing to each textbox/textarea we have.

 

<asp:TextBox ID="txtUserName" runat="server" SkinID="DataEntryTextBox" onkeydown="keyPress(event);" />

So everytime someone presses a key in this box, it will fire our client side function.

And... that's it.

There are a few drawbacks to the solution I have presented.

  1. If you're page has multiple buttons / imagebuttons on it, without careful checking those buttons will be "invoked" before yours is. You will have to do a bit of extra scripting to make sure that doesn't happen.
  2. You have to add the onkeydown event listener to every textbox / text area.
And that's it.  If you have any questions please let me know.


 


Updated BicNet Projects

I have updated my projects site. This section of my bicnet website is a place where I can throw working examples of blog posts, and other things I like to show.  Sometimes at home I'll find something cool, and I'll throw it up there for my manager to see.

 A small note, I got lazy while going through the Microsoft Exams which Is why you only see a few chapters on there :P

 Updated Projects:

If anyone would like me to put an example of anything ASP.NET, let me know.

Some common Gotchas in JavaScript

Over the past month I've been heavily involved in scripting. The application I'm writing is 80% JavaScript, 20% .NET. Because of this, my DOM, JavaScript, and CSS knowledge has been increasing steadily, and I've found some common errors that many Developers have encountered.

First off, I just found out the other day that JavaScript/Jscript are implements of the  ECMAScript specification. (There's a bit of semi-useless knowledge for ya).

I know that's not a "Error", but I do love useless knowledge. So asside from the mundane issues like case-sEnSiTiViTy, braces, quotes and escape characters...let's see some Gotchas.

Gotcha #1: Adjusting CSS styles through JavaScript.

Many sites use JavaScript to dynamically change the width/height of elements based on the browser size. This is very useful if you want your screen to take up the maximum aloted space without having to really grind your head into the sand with CSS. So seeing something like the bottom is quite common (except for the error in the bottom line):

 

document.getElementById("menu").style.width = menuWidth+ "px";

document.getElementById("menu").style.height= menuHeight+ "px";

document.getElementById("menu").style.background.position= "top";

The issue with this is the last line: style.background.position. Many web developers assume this is correct. However, it's an illegal identifier in ECMAScript. To get around this you need:

 

document.getElementById("rightSide").style.backgroundPosition = "top";

Basically, when you see a CSS style with dashes, - , get rid of the dash, and capitalize the next letter.

Gotcha #2: Equal is not always Equal

For C# programmers, this is a no-brainer. However, I know everyone has made this mistake. If you are a C# programmer, and you make this mistake, you'll most likely spend tons of time looking elsewhere and not at the common logic sections. Let me explain:

 

var myAge = 26;

var yourAge = 29;

 

if(myAge = yourAge)

{

    alert("Wow, I'm " + myAge + " as well, which is the same age as you!");

}

else

{

    alert("We're not the same age. That's too bad.");

}

 

The error here is the myAge = yourAge. This statement will compute and assign yourAge to myAge.  seeing myAge is now greater than 0, it will go into the if statement. This a very common mistake in JavaScript. So.. what happens if yourAge was 0? Well it ould hit the else of this if statement. Why? because in logic, anything not 0 is true. 0 is the only false. That means that -1 is true, -2 is true, 238523 is true, and -1385325.23 is true. 0 if false.

Gotcha #3: Do not self close a script tag!

This is bad:

 

    <script src="JS/gpsManagerLayout.js" type="text/javascript" />

This is good:

 

    <script src="JS/gpsManagerLayout.js" type="text/javascript"></script>

The first example (self closing script) will work in some browsers, but IE will complain like the evil step sister! You'll get partial script execution errors, and sometimes the page won't even display. So what actually happens? IE loads the first script, and then continues to look for a closing </script> tag. Ohhh Yes you understand now. IE will most likely miss every other <script> declaration you have because it wants it's </script> tag like I want coffee right now... coffee.... Ok, So what happens if no closing script tag is found (</script>)? IE assumes every bit of script, markup, styles etc. that you have to be logic... logic errors. Which means you'll get the nice "Error on Page" in the bottom left hand side which will give you an utterly useless message.

 
Gotcha #4: Variable Definitions

I had this a lot the other day. I was trying to work with the slider control in the AjaxToolkit and I needed to add a valueChanged event. I was doing:

 

var slider = $find("sPlayback");

slider.add_valueChanged(playbackDrag);

But what was happening 70% of the time was that my slider was not loaded up when this script was ran - giving me an error. I had to change it to:

    var slider = $find("sPlayback");

    if(slider)

    {

        slider.remove_valueChanged(playbackDrag);

        slider.add_valueChanged(playbackDrag);

    }

 

I also put this inside a function when I need to access the slider so that I can make sure it's loaded, and there, before I use it. 


Another common issue with undefined variables is the following:

 

    var Ninja = {

        ninjaName: "This is my Name",

        ninjaFunction: function() { alert("The Ninjas name is: " + ninjaName + ");}

    };

 You might think this is ok. However, the ninjaFunction has no idea what ninjaName is. To fix this you need to use the "this" identifier which tells the objects function to use the objects actual variable. 

The right way: 

function test

{

    var Ninja = {

        ninjaName: "This is my Name",

        ninjaFunction: function() { alert("The Ninjas name is: " + this.ninjaName + ");}

    };

}

 

JavaScript is a very sensitive scripting language, but a very useful one for web developers. If you have not yet downloaded FireFox or FireBug, I urge you to download them. They are the best tools for debugging JavaScript and web sites.

A Table, some text and CSS Pseudo Classes
To See this in a working example, please check out my projects at : bicnet Projects.

I really want to thank the IE7 team for building in more Support for CSS. It allows us web developers to do some pretty cool things with CSS without the use of javaScript. Unfortunately not all the goodies work with IE7 (:after :before) but a lot do.


This post is a quick glance at using CSS Pseudo Classes with Tables. In this example I will use a regular HTML table, however this will work with any ASP.NET control that outputs an html <table>.

First, if you have no idea what a Pseudo class is please look at this page by W3Schools.

Let's start with some CSS:

#MyTable

{

    width:460px;

}

 

#MyTable td

{

    width:150px;

}

 

#MyTable td:hover

{

    background-color:Black;

    color:Yellow;

}

 

#MyTable tr:hover

{

    border: solid 1px green;

    background-color:Yellow;

    color:Maroon;

}

 

 

#MyTable thead tr:hover

{

    background-color:ThreeDShadow;

    color:White;

 

}

 

#MyTable td span:hover:after

{

    content: "\00BB";

}

 

#MyTable td span:hover:before

{

    content:"\00AB";

}

 

#MyTable .row1

{

    border:solid 1px white;

}

 

#MyTable .row1:hover

{

    background-color:Aqua;

    color:Navy;

}

 

#Mytable .column1:hover

{

    background-color: #1b1b1b;

    color: Yellow;

}

 

#MyTable .column2:hover

{

    background-color: #545454;

    color: Yellow;

}

 

#MyTable .column3:hover

{

    background-color: #8c8c8c;

    color: Yellow;

}

 

#MyTable .row1 td:hover:before

{

    content:open-quote;

}

 

#MyTable .row1 td:hover:after

{

    content:close-quote;

}



You'll notice that the #MyTable is the only declared item that I'm using. This is because CSS can traverse my DOM and apply it's styles to the children based on how I declare it.

Let's look at my HTML Markup:

<table id="MyTable" cellpadding="0" cellspacing="0">

    <thead>

        <tr>

            <td>Column 1</td>

            <td>Column 2</td>

            <td>Column 3</td>

        </tr>

    </thead>

    <tr>

        <td>Column 1 Row 1</td>

        <td>Column 2 Row 1</td>

        <td>Column 3 Row 1</td>

    </tr>

    <tr>

        <td>Column 1 Row 2</td>

        <td>Column 2 Row 2</td>

        <td>Column 3 Row 2</td>

    </tr>

    <tr>

        <td>Column 1 Row 3</td>

        <td>Column 2 Row 3</td>

        <td>Column 3 Row 3</td>

    </tr>

    <tr>

        <td>Column 1 Row 4</td>

        <td>Column 2 Row 4</td>

        <td>Column 3 Row 4</td>

    </tr>

    <tr class="row1">

        <td class="column1">Column 1 Row 4</td>

        <td class="column2">Column 2 Row 4</td>

        <td class="column3">Column 3 Row 4</td>

    </tr>

    <tr>

        <td><span>Text in Span</span></td>

        <td><span>Text in Span</span></td>

        <td><span>Text in Span</span></td>

    </tr>

</table>


This is a very simple Table. The last row contains text in "span" tags, and the 2nd to last row has class names on the <td> and <tr> elements. Also notice I do not declare those classes in CSS, I don't need to.

To See this in a working environment please check out my projects at : bicnet Projects.
(*Note I don't have time right now to fix a few issues in my projects section. I'll be updating it and fixing a few issues later this week... if my baby isn't born  )


Like I said, this is a quick example that shows some cool things you can do with CSS. Sometimes you don't need to purchase those kick ass controls from Telerik, all you need to do is put your head down, look at some cool examples of sites and tables and then pilfer what you need.


Here's a list for those that wish to learn more about Design and CSS (because I am no expert at design):

UpdatePanel, FireFox and the DefaultButton

Recently I was pulling my hair out with this issue. Recently I blogged about using a Modal Login control instead of redirecting to a login page. I have had great success with this.

 However, the one thing that was vexing me was the Default Button. It worked like a charm in IE. In Firefox, it behaved like the ugly step sisters. The problem wasn't that it didn't do a postback. That it did. What it didn't do was hit the server side event (the button click event).

To reproduce this issue, try the following bit of markup (This is sample markup from my Modal Login):
 *This markup is inside an UpdatePanel on the parent page.

<asp:Panel ID="pnlLogin" runat="server" DefaultButton="btnLogin" CssClass="login" Style="display: none;">

    <div id="loginDrag" class="drag">

        <h3>Login</h3>

    </div>

    <div class="tcenter error">

        <asp:Label ID="lblMessage" runat="server" />

    </div>

    <table>

        <tr>

            <td class="column1">

                Agency ID:</td>

            <td class="column2">

                <asp:TextBox ID="txtAgencyID" runat="server" SkinID="DataEntryTextBox" ValidationGroup="Login" />

                <asp:RequiredFieldValidator ID="rfvAgencyID" runat="server" ControlToValidate="txtAgencyID" Text="*" ErrorMessage="AgencyID is Required." ValidationGroup="Login" />

                <ajaxToolkit:ValidatorCalloutExtender ID="vAgencyID" runat="server" TargetControlID="rfvAgencyID" HighlightCssClass="validatorCalloutHighlight" />

            </td>

        </tr>

        <tr>

            <td>

                Username:</td>

            <td>

                <asp:TextBox ID="txtUserName" runat="server" SkinID="DataEntryTextBox" />

                <asp:RequiredFieldValidator ID="rfvUserName" runat="server" ControlToValidate="txtUserName" Text="*" ErrorMessage="A Username is Required." ValidationGroup="Login" />

                <ajaxToolkit:ValidatorCalloutExtender ID="vUserName" runat="server" TargetControlID="rfvUserName" HighlightCssClass="validatorCalloutHighlight" />

            </td>

        </tr>

        <tr>

            <td>

                Password:</td>

            <td>

                <asp:TextBox ID="txtPassword" runat="server" SkinID="DataEntryTextBox" TextMode="password" />

                <asp:RequiredFieldValidator ID="rfvPassword" runat="server" ControlToValidate="txtPassword" Text="*" ErrorMessage="A Password is Required." ValidationGroup="Login" />

                <ajaxToolkit:ValidatorCalloutExtender ID="vPassword" runat="server" TargetControlID="rfvPassword" HighlightCssClass="validatorCalloutHighlight" />

            </td>

        </tr>

        <tr>

            <td colspan="2">

                <asp:Button ID="btnLogin" runat="server" Text="Login" OnClick="btnLogin_Click" ValidationGroup="Login" UseSubmitBehavior="false" />

            </td>

        </tr>

    </table>

</asp:Panel>

 

When you are selected in any textbox and you press enter, IE will submit this and hit the button click even. however with FireFox, it will only submit - not call the onclick event.

To solve this add:   UseSubmitBehavior="False" to your submit button.

Now you can press enter whenever you want in your form and it will do the propper submit regardless of IE or FireFox. 

More Posts Next page »