Thursday, June 05, 2008

In my quest to find a suitable generic update method for a generic LINQ Data Access class I have found a decent amount of code and even more theories (sans code).  Some good, some verbose, and a lot bad.  It seems that Extension Methods are a fan favorite for just about everything nowadays and I wasn't suprised to see Extension Methods being used for LINQ to SQL updates.

In reading about Extension Methods I have heard good and bad feedback.  The good usually involves the convenience of bypassing a utility class and the bad involving code readability / maintability.  Forgive me for I am the William Hung of LINQ as I have had no formal training in this arena, but IMHO Extension Methods are a pain-in-the-ass when ExtensionMethodA returns the result of ExtensionMethodB which depends on the output of ExtensionMethodC which ..... Here is an example of what I am talking about in pseudo-code:

public static bool Update<T>(this Table<T> table, T instance) where T: class
{
   try
   
{
      // do stuff here with parameters...
      
return table.Foo() > 0;
   }
   catch (Exception)
   {
      return false;
   }
}

public static int Foo<T>(this Table<T> table) where T: class
{
   return table.GetEnumerator().Bar();
}

public static int Bar<T>(this IEnumerator<T> e) where T : class
{
   return 1;

Horrible example yes and for that I apologize.  Hopefully you see where I am going with this and that if you are given a similar codebase it can be quite confusing.  When I first heard of extension methods I though they were for simple utility tasks such as outputting a decimal value as a dollar amount (again, doesn't REALLY warrant an extension method but...):

public static string PrintWithDollarSign(this decimal input)
{
   return input.ToString("c");
}

Simple. Effective. Here's how you would use:

Console.WriteLine(instance.Price.PrintWithDollarSign());

Cheap. No frills.  I could have just bypassed this extension method altogether but it provides a very "Hello World"'y introduction to extension methods for those of you not hip to them.  In my previous example if you had an object with a decimal property and the value was 5.00 the output would be $5.00. Easy.

Anyone care to chime in on extension methods relying on other extension methods? I'd love to get some feedback.

C# | Will
Thursday, June 05, 2008 6:19:17 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, April 22, 2008

I'm moving some duplicate code from a codebehind file to a class file so I can reuse it. I'm tired and it's a bit late for my best programming so I'm trying to remember is the c# return type also null now. Or maybe no return type needs to be specified if a variable isn't returned (is that vb?). If null works in SQL and it works an an object value to compare against in c#, why can't null be a valid return type instead of void. What does void really say under the covers that is so different from null. Isn't void a carryover from c and c++. Perhaps it's older than that. Why do I need to remember yet another keyword that has no value. No, that's not a pun. I have too many numbers and words in my head that have to be pulled out at a moment's notice. Why add one more? Get rid of void. Just rip it right out.

C# | Dina
Tuesday, April 22, 2008 7:43:33 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, April 07, 2008

I stared working on my sitemap tonight. Never done the SiteMap stuff before. Opened my Pro ASP.NET 2.0 in C# 2005 that I use as a jump off point for intro topics I haven't touched yet. The chapter is great but I like my data in the database which gets backed up every night. I understood enough and even got a test page up using nested site map files. Hurray!

Now on to the SQL provider. I knew there had to be one so I googled and found an article with code by Jeff Prosise. The article covers the .cs file that is the SQL provider, as well as the web.config changes, the T-SQL, and the aspnet_regsql commands.

After you get the provider up and working, don't expect the SQL provider to show up in the Data Source Configuration Wizard:

You'll have the change the SiteMapDataSource to specify the Provider that you added to the web.config for SQL:

<asp:SiteMapDataSource ID="TotalSiteMap" runat="server" SiteMapProvider="AspNetSqlSiteMapProvider" />

 

But now my data is in the database and I changed the proc to be NetTiers-compliant so I can use their Admin pages for my data management.

Monday, April 07, 2008 8:22:52 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 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]  | 
 Monday, February 18, 2008

I'm getting farther along in my new pet project. I had many issues with converting to a web application project. Then I balked at which style of data access/data layer to use. Then I fidgetted with notation and styles. After wasting bunches of time, I'm finally moving along. Data is going in, data is going out. It looks aweful and the backend is a SQL client. But the user functionality is moving along. The rest can be fixed after I feel some momentum.

So I'm using asp.net 2.0 c# with sql backend. Enterprise Framework from MS patterns and practices. MS Membership provider with a SQL provider. Data layer is business objects with provider model. I have nunit plugged in but haven't written in unit tests yet. Argh!

Since I'm not a graphic designer, it looks BAD. A bad ripoff of www.xcache.com.

 

Programming to www.pandora.com.

 

ASP.NET | C# | Dina
Monday, February 18, 2008 10:53:19 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, February 15, 2008

http://www.15seconds.com/issue/080214.htm - Create a Slide Show Using the AJAX SlideShow and TreeView Controls

ASP.NET | C# | Dina
Friday, February 15, 2008 7:45:19 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

For the longest time I couldn't skin my custom control, background: a custom control looks like this:

public class MyGridView : GridView
{
...
}

This custom controls was in a separate class library.  Bill researched the problem and it appears that you can't skin a custom control that is in a nested namespace.  I.e. the custom control can't have this:

namespace MyNamespace.SubNameSpace
{
   public class MyGridView : GridView
   {   
   ...
   }
}

It has to be in a single namespace to work:

namespace MyNamespace
{
   public class MyGridView : GridView
   {  
   ...
   }
}

Visual Studio 2005 - .NET 2.0 - ASP.NET 2.0
{6230289B-5BEE-409e-932A-2F01FA407A92}

 

ASP.NET | C# | Wayne
Friday, February 15, 2008 9:16:58 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, February 14, 2008

My office mate Chad came up with yet an even better option. You need to be using 3.5 and include the System.Linq extension method namespace. It didn't perform quite as well but pretty close. Even more general purpose. Note that the default SequenceEqual method throws an exception when either operator is null so I handled those cases first.

bool Compare<T>(IEnumerable<T> left, IEnumerable<T> right)

{

    // handles the same array

    // handles both null

    if (left == right)

        return true;

 

    // fails when either are null

    if (left == null || right == null)

        return false;

 

    return left.SequenceEqual(right);

}

 

Andy | C# | LINQ
Thursday, February 14, 2008 3:02:02 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

Slightly more efficient by starting off with a reference compare. If the same two arrays are passed in, no need to compare the elements. I don't think there is a better way unless you use unsafe code / pointers. The use of generics makes this more general purpose.

bool Compare<T>(T[] left, T[] right)

{

    // handles the same array

    // handles both null

    if (left == right)

        return true;

 

    // fails when either are null

    if (left == null || right == null)

        return false;

 

    if (left.Length != right.Length)

        return false;

 

    for (int i = 0; i < left.Length; i++)

    {

        if (!left[i].Equals(right[i]))

            return false;

    }

 

    return true;

}

 

Andy | C#
Thursday, February 14, 2008 1:03:17 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

Here is a little code that I simplified:

public Boolean Compare(Byte[] a, Byte[] b)
{
   return(a=b);
}

Seems like it should work right?  Compare each Byte in a with the same Byte position in b and return if the two arrays have equal values in each position?  It doesn't do that -- it compares the two objects to see if they are equal.  My solution:

public Boolean Compare(Byte[] a, Byte[] b)
{
    if ((a == null) && (b != null))
        return (false);

    if ((a != null) && (b == null))
        return (false);

    if ((a == null) && (b == null))
        return (true);

    if (a.Length != b.Length)
        return (false);

    for (int i = 0; i < a.Length; i++)
        if (a[i] != b[i])
            return (false);

    return (true);
}
Is there a better solution?
{6230289B-5BEE-409e-932A-2F01FA407A92}

 

C# | Wayne
Thursday, February 14, 2008 8:50:49 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, February 07, 2008

In response to the previous postingJames Arendt has comment the final word:

static internal String AredntWay(String[] list)
{
   return(String.Join(',',list));
}

Thanks James Arendt!

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

C# | Wayne
Thursday, February 07, 2008 2:21:47 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 

C# .NET 3.0 has anonymous types, since I am working on some legacy projects I have the experience of using anonymous types already in VBScript.  Remember classic ASP? Not having to Dim your variables, and being able to assign a variable to an int, then a string.  Has it been so long ago that you forgotten all the fun you have had with anonymous types in classic ASP?

I have a project that is classic ASP and SQL Server, if we change the SQL Server column (i.e. rename it or change the type) we have to scan the classic ASP (Find In Files) then make the changes to all inline SELECTS, UPDATES, and DELETES.

So then we got smart and changed to stored procedures, now if the type changes the stored procedures doesn't compile, easier to find places that need to be changed, however we had to adjust the classic ASP to handle the new type as an output -- really not a problem becuase all VBScript is anonymous types. 

So then we got really smart and used ASP.NET CLR 2.0, a class library to talk to our database, and SQL Server.  We generated the class library from CodeSmith using the database schema as a template for the library.  Now we are doing really good.  If the database type changes, the class library changes (we regenerate it), and any code behind that is calling the class library will break becuase of the type change.  Strongly typed language how nice.

Now we have LINQ -- back to anonymous types, we can jump on the bandwagen and rewrite all our code behind to call LINQ.  Now if we make a database change we are back to find In files.  Full circle to our VBScript days. Yippee.

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

 

C# | Wayne
Thursday, February 07, 2008 1:46:36 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, February 04, 2008

Creating a comma delimited string from an array came up yesterday, here is a couple of methods, one from our junior developer and one that I did.  I entitled mine old school, because of the C coding that shaped my programming.

static internal String Junior(String[] list)
{
    String output = String.Empty;

    foreach (String item in list)
    {
        output += item + ",";
    }

    output.TrimEnd(',');

    return (output);
}

static internal String OldSchool(String[] list)
{
    StringBuilder output = new StringBuilder();

    foreach (String item in list)
    {
        if (String.IsNullOrEmpty(item))
            continue;

        if (output.Length > 0)
            output.Append(",");

        output.Append(item);
    }

    return (output.ToString());
}

Which one do you like?

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

 

 

C# | Wayne
Monday, February 04, 2008 10:21:22 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Tuesday, January 22, 2008

In C# we can have nullable types, like this:

Boolean? isValid;

Which means that isValid can be true, null, or false.  It is like a three way switch.  I use it to represent a bit field in SQL Server that can have a null value.  For example I might have this table:

CREATE TABLE Account (IsValid bit)

Which creates me a table with a bit column that can be NULL.  I usually don't like to do this -- in fact I never do, however I am working with some people that don't bother to check the NOT NULL when they use the designer so I have to deal with it in my C# code.  So I ask the table designer what NULL means in the IsValid coulmn and he tells me it means false (not valid).

So I query the database and set the result to isValid, in the C# class above.  So now I need to check to see if the account is valid.  It might seem like this would work:

if (isValid) {...}

However, that throws a compiler error, becuase you can't have Nullable type default expression.  So I have to do this:

if (isValid == true) { }

Notice that the second statement is really saying that the expresion fails if the IsValid is false or null.  This is also the same but weak:

If ((isValid!=null) && (((Boolean)isValid)==true)) { }

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

 

C# | Wayne
Tuesday, January 22, 2008 9:18:07 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 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]  | 

Intermitently my code was getting this Exception: "System.ArgumentException: An item with the same key has already been added."  The code looked like this:

if (!_roleTypeNameDict.ContainsKey(roleTypeName))
_roleTypeNameDict.Add(roleTypeName, ...)

Since I have done a lot of C++ programming right away I realized that I had a threading issue, however the question was why? It just so happens this was a static method, calling a static property, which means that more then one thread might be accessing _roleTypeNameDict at a time:

private static Dictionary<String, RoleTypes> _roleTypeNameDict
   = new Dictionary<string, RoleTypes>();

public static RoleTypes FindCachedRoleTypesFromRoleTypeName(String roleTypeName)
{

if (!_roleTypeNameDict.ContainsKey(roleTypeName))
       _roleTypeNameDict.Add(roleTypeName, ...);
...
}

To solve the issue you need to create a lock to protect the check to add from the add like this:

private static Dictionary<String, RoleTypes> _roleTypeNameDict
   = new Dictionary<string, RoleTypes>();
private
static object _roleTypeNameDictLock = new object(); public static RoleTypes FindCachedRoleTypesFromRoleTypeName(String roleTypeName) {    lock (_roleTypeNameDictLock) {    if (!_roleTypeNameDict.ContainsKey(roleTypeName))       _roleTypeNameDict.Add(roleTypeName, ...); }
   ...
}

However, you can make the code slightly faster if you assume that the ContainKey is less expense then the lock from a performance stand point:

private static Dictionary<String, RoleTypes> _roleTypeNameDict
   = new Dictionary<string, RoleTypes>();
private static object _roleTypeNameDictLock = new object();

public static RoleTypes FindCachedRoleTypesFromRoleTypeName(String roleTypeName)
{
   if (!_roleTypeNameDict.ContainsKey(roleTypeName))
   {
      lock (_roleTypeNameDictLock)
      {
         if (!_roleTypeNameDict.ContainsKey(roleTypeName))
            _roleTypeNameDict.Add(roleTypeName, ...);
      }
   }
   ...
}

What we are doing here is checking to see if we need to add, then locking, then checking again, then adding.  This prevents us from locking if we don't need to add-- the majoirty of the cases, however it also prevents two threads from trying to add at the same time.

I was just thinking the other day that threading, caching, and memory management skills where still needed in .NET even though the Microsoft PR machines is making C# out to be much easier then C++.  At the same time VBScript programmers in classic ASP don't have to worry about threading issues.

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

 
 
C# | Wayne
Thursday, January 17, 2008 8:53:30 AM (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]  | 
 Tuesday, January 01, 2008

If you are converting a GUID to a String in C++ you can use this Windows API:

TCHAR szString[41];
::StringFromGUID2(guid, szString, 41);

Note that C++ adds brackets around the GUID so it appears like this:

{c200e360-38c5-11ce-ae62-08002b2b79ef}

However, if you are doing a ToString() in C# you don't get the ending brackets, for example:

String output = Guid.NewGuid().ToString();

Will return:

c200e360-38c5-11ce-ae62-08002b2b79ef

C# will parse a string into a GUID regardless of the brackets.  For example, both these get you the same GUID:

System.Guid guid = new System.Guid("c200e360-38c5-11ce-ae62-08002b2b79ef");

System.Guid guid2 = new System.Guid("{c200e360-38c5-11ce-ae62-08002b2b79ef}");

The equivalent function in C++ is:

::CLSIDFromString(sz,&guid);

However, CLSIDFromtString will not accept a GUID without brackets.  Note here that CLSID, IID and GUID are the same in C++.

If you are going between C++ and C# and you are passing GUIDs as string you need to include the brackets.  It is easier to have C# add the brackets then C++, since it requires a separate string.  Here is how you format your C# string:

String output = String.Format("{{{0}}}",Guid.NewGuid());

Note that you need to use double brackets to represent one bracket on each side.

C# | C++ | GUID | Wayne
Tuesday, January 01, 2008 10:47:06 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |