Check out my 3rd article on Chris Pirillo’s Lockergnome.com

Share

imageI’ve been asked by Chris Pirillo to write some articles for his web site Lockergnome.com. This is my third article. It talks about the pros and cons of the new Windows 8 app store.

Windows 8 App Store:  What You Need To Know

If you haven’t heard of Chris Pirillo (and shame on you, if you’re a techie and haven’t), he used to host the TV show “Call for Help” on TechTV and lots of other cool stuff. You can follow him on Google+ here:

Follow Chris Pirillo on Google+

For that matter, you can follow ME on Google+ here:

Follow ME on Google+

I’ll be writing some more for Lockergnome.com, so check back here and I’ll post the links as they’re posted. I’ll also be announcing them on Google+.

Share

Check out my 2nd article on Chris Pirillo’s Lockergnome.com

Share

imageI’ve been asked by Chris Pirillo to write some articles for his web site Lockergnome.com. This is my second article.  It describes how to save money and protect yourself online when making purchases with a credit card.

Save Money and Protect Yourself with Your Online Purchases

If you haven’t heard of Chris Pirillo (and shame on you, if you’re a techie and haven’t), he used to host the TV show “Call for Help” on TechTV and lots of other cool stuff. You can follow him on Google+ here:

Follow Chris Pirillo on Google+

For that matter, you can follow ME on Google+ here:

Follow ME on Google+

I’ll be writing some more for Lockergnome.com, so check back here and I’ll post the links as they’re posted. I’ll also be announcing them on Google+.

Share

Web.config and App.config variables can be fully type safe

Share

I’m going to introduce a MUCH better way of accessing your variables that you have created in your web.config or app.config file.  Most likely, you’re probably storing your variables in your .config file like this:

Click here to follow me on Google+.

 <appSettings> <add key="EMailAddress" value="me@something.com"/> <add key="IsProduction" value="true"/> <add key="MaxWait" value="15"/> appSettings>

And your code to access them probably looks like this:

this.EMailAddressLabel.Text = ConfigurationManager.AppSettings["EMailAddress"];if (ConfigurationManager.AppSettings["IsProduction"] == "true") this.NotProdNotifyLabel.visible = false;else this.NotProdNotifyLabel.visible = true;this.MaxWaitLabel.Text = "Maximum wait time is " + ConfigurationManager.AppSettings["MaxWait"] + " seconds";

That’s an awful lot of typing, has the potential for typos that aren’t caught by the editor or the compiler, doesn’t have intellisense, and is not type safe.

Solution!

Visual Studio has a very easy to use and very powerful feature for creating and accessing config variables.

Now, depending on what version of Visual Studio you’re using, things could be different.  As of this writing, the latest version is Visual Studio 2010.  But, this feature is available going all the way back to the original version of Visual Studio .Net back in February 2003.  So, it’s supported in all versions, but there are differences, not in how you do it, but in what choices you’ve already made for existing apps.  First, I’ll discuss doing this the right way when creating a new app:

BTW, this works for ALL .Net apps, not just ASP.Net web apps.  It works for WinForms, ASP.Net MVC, ASP.Net, Console apps, Windows Service Apps…

I’ll be using an ASP.Net WebForms app as an example, because that’s where the differences lie between the different version of Visual Studio.Net.

First, we’ll work with making a New app.

    1. Create a web app app.  Depending on your version of Visual Studio, you might have an option for “Web Site”.  DON’T CHOOSE THAT!  This whole solution is unavailable for web sites.  It MUST be a web app!

 

  • Right-click your project and choose “Properties:

 

  1. image

 

  • Click on the “Settings” tab.

 

  1. image

 

  • Click on the link, “This project does not contain a default settings file.  Click here to create one.”

 

  1. image

Now, your app contains what’s needed to support your simple typed config variables.  Notice the new stuff added to your project?

image

Now, never look at it again.  I just wanted you to see that it’s there.  This adds no complication to your life because you’ll never use it directly.  It’s just generated code.  Put it out of your mind and never think of it again.

Notice the grid that showed up on the screen?

image

This is where you’ll create your config variables… not in the config file itself.  This simple tool will automatically add them to the config file for you.  You don’t have to putz around with the messy config file anymore for your config variables.  Now, let’s add the 3 config variables we used the old way from the top of this article:

For each variable we create, we can choose the type of that variable!  Check out what happens when I create the IsProduction variable:

image

I picked “bool” from the “Type” drop down list.  Look at the “Value” column.  Notice that it knows what is valid for a boolean?  I’ll pick “True”.

Now, when I add MaxWait, I’ve got some options.  I can make it an int to represent number of seconds, but in reality, it’s representing a time span.  Guess what?  .Net has a TimeSpan type!

image

image

It inserts a value for me, showing me the format I need.  That’s HH:MM:SS, BTW.  I can add a decimal after the seconds to get milliseconds, if I want.  There’s a way to do days too, but I’ll let you figure that out.

I’m going to enter 15 seconds:

image

Now, this is important (but simple).  I need to hit “save”.

image

Now, look at what it did to the config file:

image

image

Now, there’s one more thing I want to draw your attention to… and it’s not important that you know this because you’ll never need to mess with this, but I want to give you a glimpse under the hood of what else has happened:

image

Pop open the Settings.settings branch and open the Settings.Designer.cs file:

 

 1: //------------------------------------------------------------------------------
 2: // 
 3: // This code was generated by a tool.
 4: // Runtime Version:4.0.30319.237
 5: //
 6: // Changes to this file may cause incorrect behavior and will be lost if
 7: // the code is regenerated.
 8: // 
 9: //------------------------------------------------------------------------------
 10: 
 11: namespace ConfigVarsSample.Properties {
 12: 
 13: 
 14:     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
 15:     [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
 16:  internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
 17: 
 18:  private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
 19: 
 20:  public static Settings Default {
 21:             get {
 22:  return defaultInstance;
 23:             }
 24:         }
 25: 
 26:         [global::System.Configuration.ApplicationScopedSettingAttribute()]
 27:         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 28:         [global::System.Configuration.DefaultSettingValueAttribute("me@something.com")]
 29:  public string EMailAddress {
 30:             get {
 31:  return ((string)(this["EMailAddress"]));
 32:             }
 33:         }
 34: 
 35:         [global::System.Configuration.ApplicationScopedSettingAttribute()]
 36:         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 37:         [global::System.Configuration.DefaultSettingValueAttribute("True")]
 38:  public bool IsProduction {
 39:             get {
 40:  return ((bool)(this["IsProduction"]));
 41:             }
 42:         }
 43: 
 44:         [global::System.Configuration.ApplicationScopedSettingAttribute()]
 45:         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 46:         [global::System.Configuration.DefaultSettingValueAttribute("00:00:15")]
 47:  public global::System.TimeSpan MaxWait {
 48:             get {
 49:  return ((global::System.TimeSpan)(this["MaxWait"]));
 50:             }
 51:         }
 52:     }
 53: }

This is the code that got generated for you.  Now, put it out of your mind (again), because you’ll never actually edit this file.

Now, remember the old way of accessing the config variables?

this.EMailAddressLabel.Text = ConfigurationManager.AppSettings["EMailAddress"];if (ConfigurationManager.AppSettings["IsProduction"] == "true") this.NotProdNotifyLabel.visible = false;else this.NotProdNotifyLabel.visible = true;this.MaxWaitLabel.Text = "Maximum wait time is " + ConfigurationManager.AppSettings["MaxWait"] + " seconds";

Here’s the new way:

Add this to your using section:

using

 

ConfigVarsSample.Properties;

And in your code, you do this:

image

Notice how you get intellisense?!?!?  Let’s continue:

var settings = new Settings();this.EMailAddressLabel.Text = settings.EMailAddress;this.NotProdNotifyLabel.visible = !settings.IsProduction;this.MaxWaitLabel.Text = "Maximum wait time is " + settings.MaxWait.ToString();

See how much cleaner this code is?  And, since it’s typed, you can use the IsProduction variable as a boolean rather than examining the text value of it.  The MaxWait variable can actually be used in time and date functions and directly in calculations!

What have you gained?

    1. Intellisense.

 

  • Edit time typo checking.

 

 

  • Compile time error checking.

 

 

  • Strongly typed variables.

 

 

  • Code that won’t fail at run time.

 

 

  • .config files that you don’t have to edit directly as often.

 

 

  • Increased productivity.

 

See this image?

image_thumb26

You’ll find an actual working version of it at the bottom of this article. Please click the appropriate buttons in it to let your friends know about this article.

Check back later for updates too!

Click here to follow me on Google+.

Share

How to use untyped Session Variables

Share

Session variables are helpful, of course, but they have many drawbacks, including having to access them by name in a string (no intellisense, no compile time error checking), they’re untyped, so you have to cast them, and it’s easy to accidentally use the same name from different pages for different purposes and overwrite their contents, creating odd runtime behavior that’s nearly impossible to track down.  (BTW, this works for application variables too, of course).

Click here to follow me on Google+.

In this article, I’ll provide simple techniques to completely eliminate ALL of these problems.

Accidental reuse of the same name

Take this session variable as an example:

Session["SomeEventTime"] = DateTime.Now;

Imagine two developers (or even ONE developer… I’ve done this myself) working on 2 pages of the same app at the same time.  The app may have timestamps that it needs to track.  It’s not uncommon for 2 programmers who work together to come up with the same name for their own session variables.  When a user runs the app and uses one page that sets the variable, then visits the other page, that resets it, then any code that depended on the first one will behave poorly.

Typos of the name

Take this example:

Session["SomeEventTime"] = DateTime.Now;
this.EventTimeLabel.text = ((DateTime)Session["SomEvenTime"]).ToString();

Notice the error?  On the second line, the “e” in “Some” is missing and the “t” in “Event” is missing.  The compiler won’t catch this.  It’ll only be caught at run time and likely by the customer, which is embarrassing and gives both you and your team a negative image and increases the cost to the customer because you’ve got to go back in and fix it.

Notice also that you don’t get intellisense with session variable names like you do with components and other variables?  You just have to know that the session variable exists, what its name is, and what type of data is stored in it.  There’s no catalog or anything at all to know what session variables are used.  You just have to be extremely diligent, search the source for use before you make up a new one, do this 100% of the time, and hope that the other developers on your team are also doing this, diligently, 100% of the time.  Chances of that happening?  Nearly zero.

Untyped

Notice also that the compiler has no idea what type of object is stored in the session variable?  In C#, you have to cast it, which means you have to just “know” what’s in there, and if you’re wrong, the compiler won’t know… It’ll just accept it, compile it, and then it’ll crash at run time.  VB.Net doesn’t require you to cast it, but same runtime problem.  If you assign it to a variable of the wrong type, the compiler won’t catch it, will compile it, and your customers will find the runtime error.

Solutions!

Here’s how to resolve each of these problems:

Accidental reuse of the same name

This one’s easy, but apparently not obvious to most programmers until it’s pointed out to them.  Let’s see if you can figure it out before I tell it to you.  Think of databases.  How do you guarantee that a record identifier is 100% unique and never used anywhere else?

A GUID, of course!

image

So, give your session variable names a GUID.  Each session variable gets a different GUID.  Don’t be so judgmental just yet.  Yes, of course, they’re impossible to remember and to type, but I’ll cover that in a moment.  For now, I’m solving the problem of accidental reuse.  You KNOW no one else is going to use the same GUID.  So, your SomeEventTime session variable now looks like this:

Session["E4D1DE1A-ECC9-45FF-8B78-C5CD16803CFF"]

Now, to solve THREE more problems at once… one of them that we just introduced:

Gaining intellisense, giving it a usable name, and giving it a type

Wrap your session variable up in a property.

 public DateTime SomeEventTime 
{
get{return (DateTime)Session["E4D1DE1A-ECC9-45FF-8B78-C5CD16803CFF"];}
set{Session["E4D1DE1A-ECC9-45FF-8B78-C5CD16803CFF"] = value;}
}

Now, when you use your session variable, you reference the property name.  This gives you intellisense, fully typed session variables, and eliminates any concern of the internal session variable name being too hard to remember and type out.

You’ve just gained another benefit by making it a property:  Triggers!

Now that it’s wrapped up in a property, you can add special code during the assignment or during the reading of the variable.

Scope

One last thing to consider:  Scope.

Where do you create the property wrapper?  In the page?  Do you make it private? Public?  Do you put it in Global.asax?  I’ll leave that up to you to judge on a per case bases.  It might be the topic of another article here too.

What have you done?

You’ve eliminated every problem you have with session variables and gained:

  1. Type Safety.
  2. Intellisense.
  3. Compile time name checking.
  4. Triggers on setting and reading.
  5. Scope.
  6. Prevention of accidental reuse of the same name.

You’ve lost:

  1. Embarrasing runtime bugs.
  2. Wasted time looking for hard to find logic problems caused by two different parts of the code using the same name for what was believed to be different session variables.

See this image?

image_thumb26

You’ll find an actual working version of it at the bottom of this article. Please click the appropriate buttons in it to let your friends know about this article.

Check back later for updates too!

Click here to follow me on Google+.

Share

Accessing form UI elements in your ASP.NET code-behind

Share

I can’t believe that in 2011, when .Net has been around over 8 years and is in version 4.0 now (It’s 6th release, BTW (1.0, 1.1, 2.0, 3.0, 3.5, 4.0)), that people are still coding like this to access form elements:

 <input id="username" name="username" type="text">
<input id="password" name="password" type="password">

 string userName = Request.Form["username"];
string passWord = Request.Form["password"];

if(userName.IndexOf("@") > 0)
{
//do this
}
else
{
//do that
}

Click here to follow me on Google+.

That may have been necessary back in the old classic asp days, but there’s a way to do it that’s fully object oriented AND compile-time checked (as well as IDE editing time checked too!):

First, I wouldn’t use HTML elements, I’d use serverside objects, like this:

 <asp:TextBox ID="UserNameTextBox" runat="server">asp:TextBox>
<asp:TextBox ID="PassWordTextBox" runat="server" type="password">asp:TextBox>
 

(side note: Give objects names that say what they are, such as appending “TextBox” to TextBox objects, and put it at the end, so that it reads like you speak.)

But, if you insist on using HTML elements, add runat=”server” to them.  That way, the code-behind can have access to them as objects.


 <input id="UserNameInput" runat="server" type="text">
<input id="PassWordInput" runat="server" type="password">

 if(this.UserNameTextBox.Text.Contains("@"))
{
//(yes, I realize I ref’d UserNametTextBox
        //and not UserNameInput… Look at the code further up…)
}
else
{
//do that
}

The benefits of this are many-fold:

  1. Server-side objects have lots of extra capability since they’re fully object oriented objects.
  2. Adding runat=”server” to any element (including plain old HTML elements) makes them actual objects, accessible from your code-behind.
  3. While in the code-behind, you can type this. (or me. in VB.Net), as soon as you type the period, you’ll get intellisense popping up listing your GUI elements.
  4. Intellisense prevents typos.
  5. Since you’re referencing actual objects, the IDE will detect whether you have a typo and put the red squiggles underneath it in addition to adding an entry to your errors list in your errors view.
  6. The compiler will catch any typos or references to objects that don’t exist.
  7. You’ll catch errors before you publish your code, preventing your customers from finding the bugs, making you look bad.
  8. Since you’re catching bugs earlier, you’ll spend less time fixing your bugs that your customer finds, saving your customer money and embarrassment.

See this image?

image_thumb26

You’ll find an actual working version of it at the bottom of this article. Please click the appropriate buttons in it to let your friends know about this article.

Check back later for updates too!

Click here to follow me on Google+.

Share