Tuesday, February 26, 2008

Here is a little code that will create a class that you can use with Enterprise Library caching.  Basically it allows you to define a WHERE clause where any object in that WHERE clause changes (across a single table) then the cache will expire the object in the cache.  Think of it as a way to store a List<> of object that represent rows in a table in the cache and be able to detect if any row changes so that you can drop the cached list.  LastUpdate is a timestamp column that needs to be on every row.  This works since timestamp column type is always incremented by one, which means that SELECT MAX(LastUpdate) will tell you the maximum change across all rows.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Properties;

namespace ERS.Base
{
    /// <summary>
    /// 
    /// </summary>
    public class TableSqlDependency : ICacheItemExpiration
    {
        String _tableName = String.Empty;
        String _connectionString = String.Empty;
        String _where = String.Empty;
        Byte[] _lastUpdate = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="tableName"></param>
        public TableSqlDependency(String connectionString, String tableName)
        {
            _connectionString = connectionString;
            _tableName = tableName;
        }

        public TableSqlDependency(String connectionString,
            String tableName,
            String where)
        {
            _connectionString = connectionString;
            _tableName = tableName;
            _where = where;
        }

        // Summary:
        //     Specifies if item has expired or not.
        //
        // Returns:
        //     Returns true if the item has expired, otherwise false.
        public bool HasExpired()
        {
            Byte[] lastUpdate = LastUpdate;

            if ((lastUpdate == null) && (_lastUpdate != null))
                return (true);

            if ((lastUpdate != null) && (_lastUpdate == null))
                return (true);

            if ((lastUpdate == null) && (_lastUpdate == null))
                return (false);

            if (lastUpdate.Length != _lastUpdate.Length)
                return (true);

            for (int i = 0; i < lastUpdate.Length; i++)
                if (lastUpdate[i] != _lastUpdate[i])
                    return (true);

            return (false);
        }

        private Byte[] LastUpdate
        {
            get
            {
                Byte[] lastUpdate = null;

                using (SqlConnection sqlConnection =
                    new SqlConnection(
                        ConfigurationManager.ConnectionStrings[_connectionString]
                        .ConnectionString))
                {
                    String sql = String.Empty;

                    if (!String.IsNullOrEmpty(_where))
                        sql = String.Format(
                            "SELECT MAX([LastUpdate]) 'Max' FROM [{0}] WHERE {1}",
                            _tableName, _where);
                    else
                        sql = String.Format(
                            "SELECT MAX([LastUpdate]) 'Max' FROM [{0}]",
                            _tableName);

                    using (SqlCommand sqlCommand =
                        new SqlCommand(sql, sqlConnection))
                    {
                        sqlConnection.Open();

                        sqlCommand.CommandType = CommandType.Text;

                        using (SqlDataReader sqlDataReader =
                            sqlCommand.ExecuteReader())
                        {
                            if (!sqlDataReader.HasRows)
                                lastUpdate = null;

                            sqlDataReader.Read();

                            lastUpdate = (Byte[])sqlDataReader["Max"];
                        }
                    }
                }

                return (lastUpdate);
            }
        }

        //
        // Summary:
        //     Called to give the instance the opportunity to
        //        initialize itself from information
        //     contained in the CacheItem.
        //
        // Parameters:
        //   owningCacheItem:
        //     CacheItem that owns this expiration object
        public void Initialize(CacheItem owningCacheItem)
        {
            _lastUpdate = LastUpdate;
        }

        //
        // Summary:
        //     Called to tell the expiration that the CacheItem to which
        //        this expiration
        //     belongs has been touched by the user
        public void Notify()
        {
        }
    }
}

{6230289B-5BEE-409e-932A-2F01FA407A92}

.net | C# | T-SQL | Wayne
Tuesday, February 26, 2008 10:44:49 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, February 06, 2008

I'm working on the infrastructure for a new web site. Lots of data layer so I can test. But I don't want to spend loads of time with the UI for insert/update/delete from an admin standpoint. Sure the UI for customers will get plenty of time but my own interface can be functional but not pretty. I already have robust classes for the data layer. Do I build my own pages with calls to the data layer in the code behind? I want to remove as much testable code from the UI (aspx and aspx.cs) as possible. So I'm going to try to use the GridView with a DataSourceObject. Make the GridView and ObjectDataSource do most of the work since they are far more tested than any UI code I could write.

That's my logic anyway.

 

.net | Dina
Wednesday, February 06, 2008 8:30:17 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, February 05, 2008

I have a friend who is constantly saying he can write code much faster by configuring the various data controls with the SQL insert, select, update, and delete statements. I tried this. It is true the page was much faster built. A few clicks, a few typed attributes. However, and this is a big however, that style of coding makes several assumptions. Under each assumptions, I'll also list why I think a middle layer needs to exist between the GUI and the database. For those of you who are laughing that I even need to make this argument, beware what project you take over. Look at the code first.

you configured the controls correctly the first time

   In order for the process to truely be fast, you can only touch it once. With a code library, you can easily grow the middle layer to suit all your needs without having to retouch that page using a data control.

you don't have any need to use that code again in that web app, ever

   Whatever you write is what the user, admin, etc see - one interface only. I know this is bogus but it's the only thing that backs up a "much faster" arguement. With a code library, you can have as many views into the data as you need. But, yes, you do have to write that code.

you don't test your code beyond it's first unit test

   In order to test this type of code, it's either by hand or a high-end gui/web tester. With a code library, there are several tools to unit test including nUnit or it's new version xUnit. Once you have the unit test, you can run your tests against every build. The unit tests will find error before your customers do - which is so much nicer.

no one else will ever touch your code

   Few decent programmers would work this way. It says you are lazy and work alone.

those controls will never change or be removed

   In order to get the full benefit of time savings, it has to live for the life of the project. However, with the middle layer, the logic can live beyond that app to any other app or variant. Of course, you could totally munge the library into a piece of #$% but both approaches assume the design skills are solid.

 

.net | Dina
Tuesday, February 05, 2008 7:57:07 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, February 01, 2008

This presentation was given by Brad Wilson and James Newkirk, Microsoft. I sat in on Brad's Pair Programming Agile presentation at the first Seattle Code camp which I enjoyed alot. The first code camp had more Agile presentations. Apparently Agile is no longer the shinny new toy because there was only one presentation on saturday in that area. James has been with xUnit, since some part of it's JUnit days, through NUnit and now the new version of XUnit. He went through the history which explained some of the wierdness the process has had. He also went through a discussion of what they were concerned about when they decided to build a new TDD framework. It was nice to hear real world examples of bad logic or implementation. My favorite they mentioned was using the framework for code coverage. Code coverage is the process make making sure every line of code is executed. The idea being that the more executed code that goes through testing, the fewer bugs the release product will have. These two said that blank tests or non-functional nUnit tests were created in some environments they saw just to reach code coverage percentage requirements. The only place I have ever seen code coverage as a metric for quality was microsoft while working as a tester on OLEDB.  They wrote issues on the board people wanted to cover and they covered all of them. Very impressive.

During the code samples and execution, it was obvious these two preferred TestDriven.Net over any other runner of the framework.

I had to feel for the guy that asked about UI testing. He obviously didn't know anything about TDD. In response, the discussion for UI testing covered watiN.

Other linkable names mentioned during the discussion:

MBUnit

CruiseControl

Windows Presentation Foundation

Jeremy Miller

 

 

 

 

.net | Dina
Friday, February 01, 2008 8:41:08 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 31, 2008

This was Wayne Berry's presentation about real-world crypto coding for web sites. The presentation was identical to his asp.net user group presentation. He stayed calm with 15 minutes of Digipen equipment not working and two room switches. But it was a great presentation and the level of detail and code was just right. He said he will post the presentation here at some point.

.net | Dina
Thursday, January 31, 2008 1:08:13 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, January 30, 2008

This presentation was given by Zlatko Michailov & Asad Khan, PMs, Microsoft ADO.NET. The best thing said in the entire presentation was that if your model is well built you shouldn't have to do any group bys or joins. Drink the kool-aid, swallow the pill, enjoy that illusion in a real-world situation. Especially some piece of $%^@ database that is mission critical and the data is 10 years old, not normalized, and some one else's baby. But if you are going to dream, dream big, right?

Their blogs can be found at: http://blogs.msdn.com/esql/. E for entity. Why be normal? right?

 

 

.net | Dina
Wednesday, January 30, 2008 1:03:54 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, January 29, 2008

Rod Paddack gave this session wearing a great geek shirt. His enthusiasm for open source was reciprocated by many in the audience. Here is the list:

Mentions during session included http://code.google.com/

What are your top tools?

 

.net | Dina
Tuesday, January 29, 2008 12:54:50 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, January 28, 2008

From https://seattle.codecamp.us/ 

Jonathan Carter, Microsoft Developer Evangelist, gave an introductory talk about the Entity Framework which has just had a Community Preview release. It is basically a middle layer framework driven by Domain Driven Design for creating and extending objects on top of a data source. The data source presented was SQL Server but you could imagine all sorts of layers. There are two parts, the Entity Model and the framework for asp.net. A simple but nowhere complete comparison could be drawn to CodeSmith. Open Visual Studio, create a "file". You are asked for a data source and data objects to include. The framework displays an Entity Relationship diagram which you can dink with to create the objects the way they will work for the upstream code and not the downstream DB.

While the presentation was a tad buggy, the framework looks like it is going someplace cool.

The best part was the intellisense to your objects you just created via the framework as well as the underlying data. This was best represented by a URI demonstation to get at the data - similar to a web service test page. Type in your URI for an object called customer with a customerid of 23 to get the Title of the customer: http://server/page.x?customer(23)/Title/ displays the result.

 

Community Preview Download http://www.microsoft.com/downloads/info.aspx?na=47&p=3&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=e9ba57aa-2a27-4658-ad04-4380a2df836c&u=details.aspx%3ffamilyid%3dD8AE4404-8E05-41FC-94C8-C73D9E238F82%26displaylang%3den

ADO.NET Team Blog http://www.microsoft.com/downloads/info.aspx?na=40&p=1&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=d8ae4404-8e05-41fc-94c8-c73d9e238f82&u=http%3a%2f%2fblogs.msdn.com%2fadonet%2f

.net | Dina
Monday, January 28, 2008 12:22:43 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, January 27, 2008

Wayne, Rusty, Andy, and I went to code camp yesterday. The speakers were good, and there was a lot of code. I focused on the asp.net and core .net sessions. I attended two talks on Entity Framework, one on top 10 open source .net tools, one on crypography given by Wayne, and one on xUnit. By far the most interesting one was the xUnit discussion with it's dev team.

I'll give sessions reviews and related links in the following days.

 

.net | Dina
Sunday, January 27, 2008 12:27:57 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 17, 2008

The ClientID property is my favorite property this week and will definitely reshape how I write asynchronous functionality in the future.  I learned about this while adding some functionality to a client's site earlier this week.  The original site was created off-shore and people like me are the ones who get to take care of it.  It's been fun so far and had I not been working on this site this week I would've totally overlooked this wonderful property.

First off, ClientID is a readonly property (as it should be!) that does nothing more than get you the id of the control that is rendered.  Take the following rendered RequiredFieldValidator.

<span id="datalistContent_ctl05_requiredDescription" style="color:Red;visibility:hidden;">I saw what you did there.</span> 

Not quite the same as my original "requiredDescription" ID set in the .aspx.  When this control was processed this original ID was appended to the UniqueID created for this control. ASP.NET does this to make sure that there are unique id's for controls and this process is especially prevalent in Repeaters, DataLists, and GridViews.  Most of you probably knew that.  As you can tell from the HTML above my "requiredDescription" was in my DataList called "datalistContent" in the 5th generated table cell ("ctl05").

So how will this help me with asynchronous programming, cleaner UI's, etc, etc?  If you're familiar with the ItemDataBound event of the Repeater, DataList, Gridview controls then you can probably see why. Let's say I have a DataList that contains a TextBox and a HyperLink.  The Description property of my object is displayed in a multi-line textbox with a CSS style attribute (see below) that makes it appear to be normal text (i.e. can't see the border, scrollbars, etc..).  The link that reads "Change Description" should enable the already-disabled textbox, hide the link, apply a TextBox-like style, and focus the cursor on this newly-enabled TextBox.  After editing the text the onblur event triggers a client-side function that disables the textbox and adds the disabled, plain-ole-text feeling CSS, then display the link again for changing the description.  It's actually easier than it sounds (demo below). Take the following example (ps. If this were production code I would use e.Item.FindControl("string") as Foo and check for null before adding attributes):

protected void ItemDataBound(object sender, DataListItemEventArgs e)
{
   TextBox text = (TextBox) e.Item.FindControl("textDescription");
   HtmlAnchor link = (HtmlAnchor) e.Item.FindControl("linkChangeDescription");

   text.Attributes.Add("style", "border: none 0px #fff; overflow: hidden; width: 250px;");   
   text.Attributes.Add("onblur", string.Format("Blur('{0}', '{1}');", text.ClientID, link.ClientID));   
   link.Attributes.Add("onclick", string.Format("Edit('{0}', '{1}');", text.ClientID, link.ClientID));
}

Those JavaScript functions consist of a whopping 6 lines so I won't paste here.  If you are curious, leave a comment and I will send you a download link to AspNetAjaxLolSike.csproj. Quick tangent, if you are into Internet memes check out LOLCode.  Chances are you you have been on the receiving end of an image such as this or this.  Think of a programming language with that vernacular. Try-Catch = Hai-KThnxBye.  ANYWAY, that's where the LolSike project name came from as I spent a good 2-3 hours laughing uncontrollably at the user-submitted codebase at LOLCode.  Some guys at Microsoft actually created a compiler for it, which I have yet to track down.

Anyway, that code will render as follows with the appropriate client-side id of the ASP.NET Control from our code-behind:

<a href="#" id="datalistContent_ctl04_linkChangeDescription" onclick="Edit('datalistContent_ctl04_textDescription', 'datalistContent_ctl04_linkChangeDescription');">Change Description</a><br />
<textarea name="datalistContent$ctl04$textDescription" rows="2" cols="20" id="datalistContent_ctl04_textDescription" disabled="disabled" class="hidden" onblur="Blur('datalistContent_ctl04_textDescription', 'datalistContent_ctl04_linkChangeDescription');" style="border: none 0px #fff; overflow: hidden; width: 250px;">Hai 5</textarea><br /> 

Moving on, I came across exploring this functionality after getting tired of finding solutions requiring a Postback (i.e. asp:LinkButton control).  This, as far as I'm concerned: sucks.  The next best option was to wrap the datalist in an UpdatePanel.  That is wrong on so many levels.  My general attitude towards the UpdatePanel is that it generally sucks 80% - 90% of the time.  80% - 90% may seem like a large number and I will explain my feelings.  The UpdatePanel is a slippery slope of bad practices (imho) for those that want to start with asynchronous technologies.  I say this because most of those that use it (80% - 90%) don't know WHEN to use it.  I can't tell you how many times I've seen someone wrap a DataGrid of 100+ records (with update, add, delete functionality) in an UpdatePanel.  Set up a project in Visual Studio that has a textbox and button in an update panel.  On "postback" set the textbox to the current date time (DateTime.Now) and use Firebug or Fiddler to check out the size of the response.  It will probaby surprise you.  I'm not saying that if you use an UpdatePanel you suck at AJAX.  By no means do I consider myself the authority figure on asynchronous programming.

You can add a button to this (hidden if there are no records in your IEnumerable<T>) to give your application "Update" functionality.  Your button OnClick event would then check all the DataListItem's in the DataList, cast your DataListItem.Item.DataItem to type T, interpret the data, and process accordingly by way of some class library. Easy.

Notice that there are no postbacks when I edit the descriptions in my DataList.

ClientID Demo

When I get some more time I will explore the avenue of asynchronous GridView paging.  I have never used the GridView so I'll have to be REALLY motivated to try.  I only used this in the DataList because I needed to display columns based on user input and treated the DataList as a Repeater with Columns functionality.

.net | C# | Will
Thursday, January 17, 2008 6:03:04 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, January 16, 2008

Just finished a little app to have a treeview control the file system navigation for images to be displayed in the AJAX Slide Show provided in the Microsoft AJAX Control toolkit. A www.15seconds.com articles about the application will be posted soon.

.net | C# | Dina
Wednesday, January 16, 2008 10:22:55 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, January 11, 2008

I've been reading a couple of renditions of this SessionWrapper class via DotNetKicks over the past couple of days.  While I must admit that this code isn't 100% original, I can say that I have given it a more generic feel and added a little bit of functionality.  With my implementation you can not only use any class, you can specify a name for the session object.  That way if you want to store say the Account and Order objects in Session you could use the same method without creating a wrapper for each type.

using System.Web;

namespace NamespaceNameGoesHere
{
   public class Session<T> where T: class
   
{
      private string _name = string.Empty;

      public string Name
      {
         get { return _name; }
         set { _name = value; }
      }

      public T Object
      {
         get { return HttpContext.Current.Session[Name] as T ?? null; }
         set { HttpContext.Current.Session[Name] = value; }
      }

      public Session(string name)
      {
         _name = name;
      }

      public Session()
      {
      }
   }
}

Pretty straight-forward. Here's how you would use it from a Page_Load for example:

Session<Foo> session = new Session<Foo>("Foo");

if (session.Object == null)
   session.Object = new Foo(-1, "hai guyz!");
else
{
   Foo foo = session.Object;

Not cutting-edge but could be useful if you want a type-safe session state.

.net | C# | Will
Friday, January 11, 2008 3:46:40 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, January 07, 2008

I just finished my first VB.NET project and it was pretty interesting. Some of you might be wondering why I did a project in VB.NET.  There are actually 3 reasons:

  1. Client's money is still green
  2. Site was the first .NET application by someone straight out of classic ASP
  3. Client won't pay to upgrade to C#

Now that we've cleared that up, I'd like to say how awkward it was.  First of all, it took me probably twice as long to write this as it would if it were in C#.  This is due to my not knowing the in's and out's of VB.NET 2.0 and not necessarily something I can blame on VB.  While there are some great additions to VB.NET such as Generics (even though the syntax isn't very intuitive), the Using construct (about time!) there is one feature that is still not there that I use day-to-day when writing applications in C#. I am talking about collapsible regions within methods.

Take the following code example:

Protected Sub ButtonClick(ByVal sender As Object, ByVal e As EventArgs)

   
Dim button As Button = sender

   If Not button Is Nothing Then

      Dim stringVariable As String = String.Empty

      Select Case button.ID

         Case "foo"
            stringVariable = "foo"

         Case "bar"
            stringVariable = "bar"

         Case "asdf"
            stringVariable = "bar"

         Case "qwert"
            stringVariable = "qwert"

      End Select

   End If

   If Not String.IsNullOrEmpty(stringVariable) Then
      
DataAccessOrBLL.DoSomethingCoolWithThisString(stringVariable)
   End If

End Sub

Given the opportunity to start from scratch I like to setup my event handlers like this.  One method that handles everything I need. To me, it makes for cleaner code and much easier to read.  If something goes wrong with an event handler, I can look in one place. In a C# environment I would setup a collapsible region like so:

Protected Sub ButtonClick(ByVal sender As Object, ByVal e As EventArgs)

   
Dim button As Button = sender

   If Not button Is Nothing Then

      Dim stringVariable As String = String.Empty

#Region "button switch"

      Select Case button.ID

         Case "foo"
            stringVariable = "foo"

         Case "bar"
            stringVariable = "bar"

         Case "asdf"
            stringVariable = "bar"

         Case "qwert"
            stringVariable = "qwert"

      End Select

#End Region "button switch" 'C# would actually be #endregion

   End If

   If Not String.IsNullOrEmpty(stringVariable) Then
      
DataAccessOrBLL.DoSomethingCoolWithThisString(stringVariable)
   End If

End Sub

The reason I would do that is because when I am writing code I view monitor space as real estate. On each screen I like to see as much code as possible. In the example above I could add a collapsible region outside of this sub routine but that wouldn't work (at least for me).  In scanning through the code I'd still want to see the section where I call DoSomethingCoolWithThisString because it's an action item so to speak.  In scanning this code-behind I could see that in my handler method I am setting a string based on the button that was clicked and then calling that method in my DAL / BLL.  Even though the code segment is collapsed I can still see what it is doing and if I need to fix that section (i.e. add a case for a new button added to the page) I could just uncollapse that region.

Quick tangent: Is it just me or does Intellisense seem a little slow and different than C#?  Also, what's up with not being able to hightlight a segment of code, right-click, 'Surround With' when in the VB.NET environment?  The 'Surround With' functionality is great for using constructs and try-catch blocks amongst other things.

At the end of the day it's all .NET and I'm kind of glad I came across this project.  As a software developer in the consulting world it's nice to be dextrous when it comes to writing / reading code but I'm still partial to C#.

.net | Will
Monday, January 07, 2008 7:07:42 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Friday, January 04, 2008

Still working on treeview with ajax slide show. I had to write 2 expandnode functions: one based on file system ("/dir/dir1/dir2") and one based on treeview with PathSeparator as "|" ("/dir/|/dir/dir1/|/dir/dir1/dir2/"). This is so that the currently selected node (ie directory) can be expanded and highlighted regardless if the web page is opening for first time, on postback, on querystring, etc.

It should be as easy as filling in a datatable-ish structure where the structure automatically resolved down the hierarchy based on a given path. But I can't figure out how to get two very similar structure into a single container without doing alot of work myself. If you know where I'm going wrong - let me know.

-Dina

 

 

Dina | .net
Friday, January 04, 2008 12:37:41 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 03, 2008

I'm writing a web app that connects a treeview control with a ajax slide show. Tons of feature creap but what is new.

I don't get a chance to program as often as I would like so when problems pop up like FindNode returning null on a valid ValuePath, I assume it's me, my programming, my install, my whatever.

I look at the docs, I look at sample code. I even look for other people having the problem but I don't see any solutions but others definitely having the problem. In one forum, the poster mentions that he figured out his path separator can't be a symbol in the valuepath. Hmmm. If you don't set the PathSeparator, it defaults to "/" which is the same thing as the directory structure I'm using in the valuepath. So problem is solved when I explicitly set the PathSeparator to "|".

-Dina

 

 

 

 

 

.net | Dina
Thursday, January 03, 2008 7:26:23 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |