# Sunday, September 18, 2005

I'm not a happy coder right now.
I gave Eran, a new gifted programmer in my department, a task:

I have a simple table in my database, named Users, with the fields ID (int, identity) and Name(varchar).
I want to send xml to a web-service which looks like this:
<User>
    <ID>1</ID>
    <Name>Oren</Name>
</User>

I want the web-service to add this row to the Users table in some magic way. I thought that by using Typed DataSet, which will use the table's schema, and loading the xml into it will do the trick, but I was wrong. We tried many things but they didn't seem to work.

The reason I want to use schema is to verify the given data(xml) structure before I insert it to the DB (and of course, without it how the DS(DataSet) will "know" to load it properly?). In addition, if tomorrow I need to add Password field to Users table, the only thing I'll have to do is to re-generate the Typed DataSet and set the password via the xml (<Password>mypassword</Password>).

The code looks like this:

string sXml = "<User><Id>1</Id><Name>Oren</Name></User>";
using (SqlDataAdapter adapter = new SqlDataAdapter("", connString))
{
    UsersDS ds = new UsersDS();

    System.IO.StringReader xmlSR = new System.IO.StringReader(sXml);

    ds.ReadXml(xmlSR, XmlReadMode.ReadSchema);
    ds.ReadXmlSchema(HttpContext.Current.Server.MapPath (".") + "\\UsersDS.xsd");

    adapter.Update(ds.Tables["Users"]);
}

For some reason my ds isn't getting filled.

Do you have any idea what am I doing wrong ?

btw - I know I can always parse the xml by myself and create the required commands, but I thought it will be a maintenance nightmare and less comfortable than letting the schema & the Typed DataSet doing the job for me.

Update [20.09.2005]:

Amir Markowitz, again, came to the rescue and with his help we've managed to solve this one:

using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Users", connString))
{
   SqlCommandBuilder scb = new SqlCommandBuilder (adapter) ;
   UsersDS ds = new UsersDS();
                    
   XmlTextReader reader = new XmlTextReader(new StringReader(sXml));

   ds.ReadXml(reader);
   ds.ReadXmlSchema(HttpContext.Current.Server.MapPath (".") + "\\UsersDS.xsd");

   adapter.Update(ds.Tables["Users"]);
}

Now, the xml data (in "sXml" variable) looks like this:

<UsersDS xmlns="http://tempuri.org/UsersDS.xsd">
    <Users>
        <UserName>Orenn</UserName>
        <Name>Oren E.</Name>
    </Users>
</UsersDS>

So thanks again Markowitz, I owe you one (again, add it to my list).

   

Posted by Oren Ellenbogen 
18/09/2005 07:06, Israel time UTC-07:00,     Comments [0]  | 
# Saturday, September 17, 2005

I'm responsible for an hybrid ASP-ASP.NET application with an ASP log-in screen; This screen authenticate the user and set a unique session value in case he's valid. All the other ASP screens check this unique session value and let the user stay in the system as long as it exists. The problem was that there were ASP.NET pages that I had to use this security mechanism in them, meaning to check the session in my .aspx files in the same pattern (same unique session) as the other .asp pages did. In order to do that I had to access the ASP session from my ASP.NET pages, which is impossible due to the simple fact that they DO NOT share the same "room" (teenagers problems, you know). The solution came after googling a little bit and testing the suggested solution on my application.

The pattern goes like this:

aspToaspnet.gif

Once again, I'm a happy camper.

   

Posted by Oren Ellenbogen 
17/09/2005 02:53, Israel time UTC-07:00,     Comments [0]  | 
# Tuesday, September 13, 2005

I've encounter a numerous bad usages of try, catch and throw statements in my last 3 years in .NET so I thought to write here my "best practices" in this subject.

Before I begin, just to remind you about the "using" keyword

" The using statement defines a scope at the end of which an object will be disposed. " (MSDN)

Meaning, this code:

using (MyDisposableObject o = new MyDisposableObject())
{
   // use o...
}

Is equal to:

MyDisposableObject o;
try
{
   o = new MyDisposableObject();
   // use o...
}
finally
{
   // Don't forget, MyDisposableObject must implement IDisposable
   o.Dispose();
}

The using statement is much more "cleaner" than the try-finally(->call Dispose) block. Of course, in order to use the using statement, MyDisposableObject must implement IDisposable interface, but most of the .NET frameworks' classes which use external resources do, so no problem here.

When do I use the using keyword instead of "try-catch(-finally)" ?

In any case your code block doesn't required any exception handling (catch) and you're using a disposable object.
 
When do I catch an exception ?
 
You should use the catch statement only if you can REALLY handle the exception - meaning you want\need to "eat"(catch it and do nothing about it) the exception or you (want to)\can try to "fix" the application's flow according the exception type (call transactionInstance.Rollback() in my data-access-layer if an error occurred, for example).
 
Do NOT catch exceptions as a "default" behavior in your code !
The following code is a BAD practice in exception handling:

try
{
   //some code
}
catch(Exception e)
{
   throw new Exception("X operation error: " + e.Message);
}
finally // if exists.
{
   //some code
}

Why is it bad ? The catch statement doesn't handling the original exception, it creates a (bad)new one which means:
  1. The Stack Trace of the original exception will be LOST, which means I lose the ability to view the entire "process" (who called to who flow).
  2. In the demonstrated code, I catch an exception and re-throwing a pointless new exception. Throwing exceptions is an expensive task so you should avoid (at any cost) throwing them as long as you don't really need to !
  3. If you wrap an exception, at least save the original exception in the InnerException property (I'll elaborate later on).
When do I wrap an exception, when do I rethrow it ?
  1. You should catch and wrap the exception with a new one only if you can add INFORMATIVE data to the original exception which WILL be used later on. Writing this type of code (in my DAL) will be a smart idea usually:

    SqlTransaction trans;
    SqlConnection conn = null;
    try
    {
        // use the connection to do some DB operation
        
        trans.Commit();
    }
    catch(Exception e)
    {
        if (trans != null)
            trans.Rollback();
        
        // Wrap the exception with DALException
        // I can check if e is SqlException and by the e.Number -
        // Set a "clean"(show to user) message to the DALException.
        // I can add the full "sql" exception in some custom property, 
        // I can determine which stored procedure went wrong, 
        // I can determine the line number (and so on).

        throw new DALException("clean message to the user", e);
    }
    finally
    {
        if ( conn != null && conn.State == ConnectionState.Open )
            conn.Close();
    }

    Why is this code smart ? Because I call the Rollback() in case of an error, which will ensure "clean" database. Because it "hides" the original SqlException which allows me, at my Business Layer, to catch a generic DALException which will abstract the Business Layer from the Data Access Layer. Because I CAN add more informative data to the exception so the Business Layer could send the GUI (to show the user).

  2. You should rethrow the exception if you catch-ed it but you "found out" that you can't really handle it:
    try
    {
        // do some code...
    }
    catch(Exception e)
    {
        if (e is SqlException)
        {
            // Add more information about the exception and
            // throw a new, more informative, exception:
            throw new DALException ("more data", e);
        }
        else
        {
            // I can't handle it really, so I'm not even going to try
            throw; // <-- look at this syntax ! I'll explain later on
        }    
    }
     
    Calling throw; will bubble the original exception (including its' Stack Trace) - this will actually "cancel" the catch statement.
When you wrap an exception, you should *almost* always use the "InnerException" property
 
When you wrap an exception, you should save the original exception as InnerException:

try
{
}
catch(Exception e)
{
   throw new MyCustomException("custom data", e);

   // OR

   MyCustomException mce = new MyCustomException("custom data");
   mce.InnerException = e;
}

This will preserve the original stack which will be important for later debugging.

 

Any Insights you want to share with me ?

   

Posted by Oren Ellenbogen 
13/09/2005 11:16, Israel time UTC-07:00,     Comments [2]  | 
# Sunday, September 11, 2005

Searching Oren Ellenbogen in Google placed me on the third(3rd!) place !
It's a huge progress if you keep in mind that just last week I was at the 15th place (second page, at the middle)...

update [14.09.2005]:

I'm at the first place now ! Respect !

   

Posted by Oren Ellenbogen 
11/09/2005 12:36, Israel time UTC-07:00,     Comments [1]  | 
# Saturday, September 10, 2005

Man, I had a lot on my mind during the previous week.
The week began with installing my application in one of our client's server which was pretty hard task due to couple of unexpected incompatibilities - lack of local IIS(meaning - no debugger!) and AD(Active Directory) complicated tree structure. This two alone are a major headache for any programmer, but I'm glad that it's behind me now (another happy customer, I LOVE IT!). The week continued and I had to fix some nasty bugs in a couple of applications which I'm responsible for, which turns out nice - there is nothing better than a good bug and a good solution (IMHO anyway).

I spent the end of the week to prepare for my presentation on the next week. I'm going to talk about DHTML, XML and XMLHTTP with my co-worker Roee(which is going to talk about Javascript and the server-side .vs. client-side pros & cons) in one of IDF computers' unit. It's a huge time consuming task to organize a decent power-point presentation, a few demos and a set of exercises and most importantly - organize my time properly. But again, I can't complain because I love giving presentation and work a little on my speaking abilities and time organization abilities.

In addition, I'm working now on Localization and Member-Roles Management solutions for our new ASP.NET 1.1 application. I know those requirements have built-in solutions in ASP.NET 2.0, but the client demanded ASP.NET 1.1 so unfortunately I can't use them yet.

btw - I'll upload the presentations, demos and exercises about XML\DHTML\XMLHTTP at the end of next week, maybe it will save one of you some time.

OK, back to work...

   

Posted by Oren Ellenbogen 
10/09/2005 04:38, Israel time UTC-07:00,     Comments [2]  | 
# Sunday, September 04, 2005

Hey y'all,

I can't seem to stop, those add-ins bastards are too addictive !
Oh well, here are more great VS.NET add-ins you should all check them out:

  1. GhostDoc - This great utility will able you to "auto" document your methods\properties with a single mouse click.
  2. WhidbeyCommands 2 - Just read the man's post :) TIP: if you give presentations while using the VS.NET, you MUST download this baby (check out "Demo font" option) !
  3. HandleWhiteSpace - Clean your files from unnecessary white spaces.
peace.
   

Posted by Oren Ellenbogen 
04/09/2005 09:08, Israel time UTC-07:00,     Comments [5]  | 
# Saturday, September 03, 2005

Sometimes we have to close the window after our screen logic has executed, so usually we're writing window.close(); in our page BUT this causes this message to arise -

close_areyousure.gif

If you want to avoid this message, simply write:

window.opener = window;
window.close();

   

Posted by Oren Ellenbogen 
03/09/2005 11:29, Israel time UTC-07:00,     Comments [1]  | 

It's possible to use built in keywords in order to mark some lines in you code for later reference. For example, I use the "TODO" keyword as a remark over a set of lines I know I'll have to change later on -

todos.gif

As you can see, my TODO task is now appearing at my Visual Studio .Net "Task list" which is great for a constant reminder.
As default, the Task list shows only the "Build Errors" so in order to support other keywords you'll have to (mouse)right-click over one of the table headers ("Description" for example) -> Show Tasks -> All (or any other suitable option). In addition, you can select how to sort the results by (I use "Priority").

* If you want to change the custom tasks priority or names - go into Tools-> Options... -> Environment -> Task List.

   

Posted by Oren Ellenbogen 
03/09/2005 11:13, Israel time UTC-07:00,     Comments [0]  | 
# Tuesday, August 23, 2005

It stroke me today at the train (on my way home) while I was reading a book named "Object Thinking" (by David West); I'm at chapter 7 which is talking about discovering the client domain, i.e what does he(the client) expect from the application. In short, although it's hard(especially if you're a technical person in your nature), you must understand the client's requirements without casting it to your world "I'll implement it with web-service" or "This is a classic multi-threading application"; You're job in this initiatory step is just to analyze the client's needs and trying to depict his world in simple "objects" world; What are my primary entities (for example: "Employee", "Employer", "Agreement" etc), what are the relationships between them and how the client expect to "activate" those entities (screens functionality).

I remembered my meeting with our last client and reading this stuff made me think about how well (?) did I managed to handle this task. While the client was depicting his world to me I was trying to understand and write his requirements and his special needs from the application. I've noticed that writing down the client's needs\remarks\requests sometimes stopped the conversation flow, caused needless repetition over the question & answers and sometimes even got me out of focus.

So, maybe tape-recording the entire meeting(well, the important stuff anyhow), concentrating on asking the right question and analyzing the answers later can create a better characterization ? better understanding of the client's domain ? shorter and more thorough meetings ?
It seems like a good idea, I think I'll give it a try on my next meeting.

What do you think?

   

Posted by Oren Ellenbogen 
23/08/2005 08:58, Israel time UTC-07:00,     Comments [2]  | 
# Sunday, August 21, 2005

Did I mention that I'm working with a well known hacker ?
Well, It's about time, so I present to you - Amir Markowitz aka "The Hacker".

Amir taught me today how to send javascript commands directly through the address bar !
Look at the "damage" he did to my site !

redbackground1.gif

As you can see, he managed to change the background color in one simple command.

Think about changing Page_IsValid property or performing __doPostBack("","") through the address bar -

javascript:void(Page_IsValid=true); __doPostBack("","");

This could be deadly if you don't perform Server-side validation as well !

 

 

   

Posted by Oren Ellenbogen 
21/08/2005 12:35, Israel time UTC-07:00,     Comments [0]  | 
# Saturday, August 20, 2005

Read this post by the legendary Brad Abrams and watch the videos you're interested at. I've seen "Designing Inheritance Hierarchies" and "Enabling Development Tools" videos (for the moment) and I promise that you can learn a thing or two as well ;-).

Happy learning...

update:
I thought it will be interesting to write my notes from the Designing Inheritance Hierarchies video, so here it is:

  1. Interfaces don't allow backward compatibility ! Let's assume we have to following interface

          public interface IMyInterface
          {
               void MyMethod();
          }

    Now let's assume that I have MyClass which inherits from IMyInterface. If I'll decide to add a new 
    signature to the interface, MyClass will be broken (TypeLoadException will be thrown in compile time).

  2. Base Classes version better than interfaces - if MyClass was inherited from MyBaseClass instead of IMyInterface I wouldn't have a problem to add new signatures to the class without causing the inherited classes to break.
  3. If you must inherit from 2 "root" classes, the recommended pattern is:

          public class A {}
          public class B {}
        
          public class C : A // Let's assume that A is "more" root to C than B
          {
             public B BInstance
             {
                get
                {
                    // return B class instance.
                }
             }
          }

  4. You can use Interfaces in "private" way via Explicit declaration:

      public interface IMyInterface
      {
         string ReturnSomething();
      }

      public class MyClass : IMyInterface
      {
          string IMyInterface.ReturnSomething()
          {
            return "oren";
          }
      }

      Now, when you create a new instance of MyClass, you won't see 
          ReturnSomething method on the public view:

      MyClass.gif

      Though, you can always call this method simply by casting c to IMyInterface:

      MyClassViaCasting.gif

      This can be useful if you want to "hide" some of the interfaces' abilities in your 
          class. This is recommendable if you don't want the "clients" to use a 
          certain behavior directly
through the class. 
         .NET framework use this ability in Int32 structure:

      int i = 5;
      i.ToString() // work
      i.ToInt32(); // don't work.
      ((IConvertible)i).ToInt32(); // work !

      " This member supports the .NET Framework infrastructure and 
        is not intended to be used directly from your code. " 
      (from MSDN, Int32.IConvertible.ToInt32 method)

 

I hope I've managed to give you some insights, just enough to convince you to start viewing these videos.

   

Posted by Oren Ellenbogen 
20/08/2005 06:21, Israel time UTC-07:00,     Comments [0]  | 

I'm currently using a .resx file at my projects to contain my friendly client's messages. I'm reading from this file via ResourceManager class which allows me to supply consistent messages at my GUI layer, e.g for every successful delete in my application you'll get the same message format "The {0} was deleted successfully" - in my "Workers" form you'll see The worker was deleted successfully and in my "Cars" form you'll see The car was deleted successfully;

I've encounter the SR (String Resource) Generator a week ago and I thought to give it a try. So, what is SR generator ?

" This custom tool allows the generation of a resource class (and optionally .resx file) from either a .resx file, or the Microsoft SR.strings file. "

I think that a simple example will show the tool's capabilities.

  1. I've downloaded the source which also includes the .msi file and installed it.
  2. I've added a file named SR.strings to my web application:

             SRGSolutionOnAdd.gif

  3. I've used the "Custom Tool" option and call SRCodeGen - this is an EXE which will parse your .strings file.
             SRGFileProperties.gif
     
  4. Next I've edit the SR.strings file -       

      [strings]
      Worker = Worker
      ItemDeleted(string itemName) = The {0} was deleted successfully.
      ItemAdded(int itemId, string itemName) = The {1} was added successfully, it's new ID is: {0}.

      [strings.he]
      Worker = עובד
      ItemDeleted(string itemName) = ה{0} נמחק בהצלחה.
      ItemAdded(int itemId, string itemName) = ה{1} נוסף בהצלחה, מספרו החדש {0}.

  5. I've saved the file in UTF-8 format, for Hebrew support.
             SRGFileEncoding.gif
     
  6. Rebuild the web project, this will cause the SRCodeGen to generate required files:
  7.                   SRGGeneratedFiles.gif
  8. Now lets use the SR class which was generated for us, here is my usage of it 
  9.          PageMessage.Text = SR.ItemDeleted(SR.Worker); // In my Worker.Delete()
     
             OR
             
             PageMessage.Text = SR.ItemAdded(newId, SR.Worker); // In my Worker.Add()
     
  10. Finally we can select the SR.Culture we want to use, so the messages will be formated in the correct language. This can be done easily be calling:
                  SR.Culture = new System.Globalization.CultureInfo("he");
   
                  OR
 
                  SR.Culture = new System.Globalization.CultureInfo("en");

         You can put this code in your Global.asax.cs in Application_Start method or 
         change it at any time, according to your needs.

 

This tool is a MUST in my opinion for two main reasons:

  1. IntelliSense, IntelliSense, IntelliSense ! (don't you love it ?!?!).
  2. Changing the messages Culture requires only one line of code, simple as that.
   

Posted by Oren Ellenbogen 
20/08/2005 01:10, Israel time UTC-07:00,     Comments [0]  | 
# Friday, August 19, 2005

If you're trying to postback from a modal dialog window, you'll see that a new window will open up with the results. In order to stay at the same window, use <base> element inside the document's <head> element -

<html>
   <head>
      ....
      <base target="_self"/>
   </head>
   ....
</html>

   

Posted by Oren Ellenbogen 
19/08/2005 08:39, Israel time UTC-07:00,     Comments [1]  | 

As you aware by now, I'm kind of programming-gadgets freak. After sharing with you the magic of SlickRun I thought it will be nice (of you to listen, I'm gonna write it anyway) to recommend about another two tools.

  • Visual XPath - After reading Justin's recommendation about it I thought to give it a try. In my every day work I'm handling a lot of xml, mostly via XmlHttp or sophisticated client side-work (like dependable DropDownLists, custom validations, building dynamic html) and this tool just give you great ability to test XPath phrases with no effort and nice GUI (always important). 
 
  • VSTabs - My second recommended tool is actually an add-in for Visual Studio .NET; The greatest value of this add-in IMHO is the file wrapping tab. It "smart" enough to wrap your .aspx file with it's .cs file and put them all in one tab. Well, one image is better than 1000 words so -
 
          vstabs.gif
   
        As you can see, it's wrapping all the linked files in one tab which is great if like to be organized,
        or you're one of those fellows, like me, that sometimes getting lost if I have
        MyFile.aspx at the beginning of the tabs scrollbar and MyFile.aspx.cs at the end if it.
 
If you have some add-ins to share with me - bring it on !
   

Posted by Oren Ellenbogen 
19/08/2005 07:24, Israel time UTC-07:00,     Comments [1]  | 
# Friday, August 12, 2005

Hey happy coders,
 
I'm currently developing a "2-weeks-max" application for an Israeli bank (If you see "Israeli bank" instead of the name of the bank, you don't have sufficient privileges ;-)). The characterization was written and approved on the fly, without a deep understanding of the client's domain, i.e what are the other applications that the users use in his every day work ? are they look the same ? does he "MUST" have some features that his already used to in his other applications ?
Now I'm facing the harsh results.
 
I'll give you an example of "little-MUST-feature-that-can-come-back-and-bite-you". The user requested a screen which will have to following fields in it (and some others, but they're irrelevant now):
  1. Requester drop down list: show all the users from a specific group in the AD (active directory).
  2. A->B->C linked drop down list: 3  DDL (drop down list) which are connected meaning that when you select a different value in A DDL all the values in B&C DDLs must show all the children of A (changing B will change C values of course).
This looks like a trivial requests right? Well, you're right, if you look at this skeleton request it may appear trivial, but the key is to understand how to user expect to choose a value from those DDLs. In my case, the user likes to work with auto-complete drop down lists. Combining his auto-complete mechanism in this screen was NOT a trivial task at all. The client gave me his code, so it seems that I just have to integrate it in my code and Voila; BUT The code was written for ASP, so I had to wrap it in a custom web control, handle the viewstate of the control, and worst - his code didn't worked so well (client-side behavior) so I was required to adjust and fix it as well(black box component in my a$$).
 
The 2 weeks application is now estimated in 3 weeks, 50% more than the first estimation !
I'm expecting a good night 24:00-06:00 sleep at the office for the next 2 weeks, wish me luck !
 
Some lessons I've learned:
  1. Don't give a fast reply for hours estimation just to move along and get the development process running, it WILL hurt you later on.
  2. Always try to understand the solution domain as well as the client's domain. Ask him to show you other applications that he uses for his every day work, ask him if he wants the same GUI in his new application that you're going to develop for him. If he does, think about the amount of time you'll be needed in order to do that, do you need to use a specific "template" so the new application will look the same as his old ones (how are you going to integrate it with ease?), do you need to allow him some special features that his already used to (auto-complete drop down list)? do you need to support key combination (Ctrl+S will save his document) ? In a "clean"(without technical considerations) characterization it probably will not be shown, but you must consider it in the technical characterization(if you have one) and in your total hours estimation ! Don't forget that the user thinks that adding a new feature to the application is an easy task because he already saw those features in other applications he uses every day ("can't you simply copy it from here???") - you must remind him that it's not a trivial task, and allow him to choose if he wants to spend time on these features.
  3. "Milk" the client for information, write all the possible scenarios that the client expect the system to handle. What screen X will show when I login as Administrator, what it will show when I login as Technician, as Supervisor ? Don't start programming unless you have the answers for those client "trivial" scenarios, refactoring will be a bitch !
  4. update: just to clarify, I didn't write the characterization and neither was my PM (project manager), it was written by another co-worker a long time ago. This is a huge mistake IMHO, you must ask the implementors, if you're not one of them, for their opinion on the development process before you can give your hours estimation.
Any tips you can share with me ?
 
 
   

Posted by Oren Ellenbogen 
12/08/2005 01:20, Israel time UTC-07:00,     Comments [4]  |