Home

Archived Posts from “C#”

Analyzing Your .NET Code with NDepend

30

July

NDepend is a static analyzer that simplifies the management of a complex .NET code base. Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and compare different versions of the code. The result is better communication, improved quality, easier maintenance and faster development.  Sounds good, eh?

Full disclosure: I received a free pro version of the NDepend from Patrick Smacchia last week along with little encouragement to use the tool and buzz about it if I find it useful.  Patrick’s timing, in fact, could not have been better as just the evening before a colleague of mine was asking for code metric tool recommendations.  Hopefully the review represents me well, but I am thrilled with NDepend and recommend it highly to anyone wanting to get "more familiar" with their code.

As published by Patrick Smacchia

…something difficult in promoting a tool such as NDepend is to educate about what it can bring to your development shop in terms of agility. NDepend comes with a set of innovative features currently not supported by any other .NET tool. I like to think that what tools such as ReSharper or CodeRush are doing to your code at micro level (i.e methods’ body structuring), NDepend does it at macro level (i.e class, namespace, assembly structuring). Hence, as a developer I personally use both kind of tools to automatically control every aspects of the code base I am working on…

Being a big fan of ReSharper, I had high hopes for NDepend.  Knowing my co-worker could use some help finding a good code analyzer and having a free copy of the software dropped in my lap, I had the immediate incentive to dig into the NDepend tool kit…

How to Get Started

Since I wasn’t all too familiar with NDepend, I opted to first gather basic information about the tool and capabilities.  Here’s what I did:

1. I watched two online demos: Getting started and VisualNDepend basics

2. I reviewed three online tutorials: How do I analyze my .NET applications using NDepend?, What does the NDepend report tell me about my code? and I want to go further to have a better control over my code

3. I read a recent NDepend review posted by Andre Loker and previewed Patrick Smacchia’s Blog for his latest comments.

First Impressions

Before even opening the software it was very clear that NDepend was super powerful and, as another colleague of mine recently said, "it can be a mind blower."  As I am very sensitive to informatiimageon overload, I proceeded simply and cautiously by basically following the steps found in the online demos.  The Visual NDepend 2.9.0 IDE is friendly and somewhat familiar as the start page could be compared to that of Visual Studio.  Here you may create/open projects or analyze/compare assemblies using the provided shortcuts.  Additionally, you are presented with quick links to the online demos and the installers for NDepend Visual Studio and Reflector add-ins. 

imageI opted to analyze a set of assemblies.  After selecting a half dozen assemblies managed within my current application, the assembly analysis is run and then, after a few moments, the results are presented within the VisualNDepend UI. 

Remember my earlier comment about being sensitive to information overload?  Well, if I wasn’t ready for it, the tool’s default display may have knocked me off my seat.  As you can see in the accompanying screen shot, there are many views and the UI is quite busy.  For the experienced user this is great as the numerous windows actually work nicely together.  For a new user, in my opinion, the elaborate UI may be inappropriate — possibly intimidating — especially if the new user really only wants to gather a simple metric like how many lines of code (LOC) make up a specific component.

With this said, the UI can be customized and all the information is very useful once you understand it.  Don’t be intimidated by NDepend even though the first impression can be a "mind blower."

I clicked around the UI for about 30 minutes and I quickly got a good sense of its power.  Certainly the demos, tutorials and blogs noted above helped lessen my learning curve so I encourage you to follow my footsteps.

Code Query Language (CQL)

What impressed me most about the NDepend is its Code Query Language (CQL).  Per the NDepend site:

NDepend considers your code as a database and you can write some CQL statements to query and check some assertions on this database.

Out-of-the-box, NDepend comes with dozens of queries which fall into varying categories from Code Quality to Test Coverage .NET Framework Usage. 

And NDepend provides the same 82 code metrics to support you in building your own queries!   Here are a few simple examples of what you can do with the CQL:image

1. Which public methods have more than 30 lines of code?
SELECT METHODS WHERE NbLinesOfCode > 30 AND IsPublic

2. Which classes implement System.IDisposable?
SELECT TYPES WHERE IsClass AND Implements "System.IDisposable"

3. Which methods have been refactored recently and is not thoroughly covered by tests?
SELECT METHODS WHERE CodeWasChanged AND PercentageCoverage < 100

On top of that you can enable/disable or even edit the out-of-the-box queries.  For example, if you don’t agree that all static fields should be prefixed with an ’s_’ change the query to validate your standard or remove the check all together.

With the Code Query Language, the sky is the limit.  Did I mention the editor comes with Intellisense?

Reports

Go ahead and generate a report.  Check out this example which gives you a run down of the application and assembly metrics, an assembly dependency diagram, CQL Queries and Constraints and much more.  Whereas the VisualNDepend UI is geared toward the architect or lead developer type who is wanting to really dig into an application, the report seems to be more suitable for a less technical audience.  Perhaps the report could be used as part of an executive summary or could complement a developer’s code review.  Simply, it is a professional output (HTML only, I think) consisting of endless information and even pictures. 

Integration

Very quickly I wanted to call out that NDepend integrates not only with VisualStudio and Reflector but also MSBuild, NAnt, and CruiseControl.NET.  I personally think it is great that NDepend was implemented in a manner in which its frequent (read: continuous) and easy (read: automated) use is promoted.  Well done.

Final Thoughts

NDepend is darn impressive. It is a "mind blower" if you will.  NDepend provides more than ample metrics, a flexible (albeit busy) UI, a customizable query language, professional reports and hooks into applications like Visual Studio and Reflector along with support for processes like automated builds and continuous integration.  If you really want to know your code and you are looking for a tool which provides more than simple application metrics, NDepend may be the right product for you.  I highly suggest you check it out.

kick it on DotNetKicks.com


Export GridView to Excel within an UpdatePanel

25

July

There’s a ton of information online about exporting a DataGrid or GridView to Excel, but most variations do not consider the GridView may reside within an UpdatePanel.  It goes without saying, but I was disappointed when I recently dusted off my “Export GridView to Excel” code snippet and encountered a number of exceptions.  So I revisited a number of links and I collected a working solution.  If you need a “simple” way to export your GridView to Excel and you are using an UpdatePanel, I hope the following code finds you well:

protected void btnExport_Click(object sender, EventArgs e)
{
    // Reference your own GridView here
    if (AccountGrid.Rows.Count > 65535)
    {
        DisplayError(“Export to Excel is not allowed” +
            “due to excessive number of rows.”);
        return;
    }

    string filename = String.Format(“Results_{0}_{1}.xls”,
        DateTime.Today.Month.ToString(), DateTime.Today.Year.ToString());

    Response.Clear();
    Response.AddHeader(“Content-Disposition”, “attachment;filename=” + filename);
    Response.Charset = “”;

    // SetCacheability doesn’t seem to make a difference (see update)
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);  

    Response.ContentType = “application/vnd.xls”;

    System.IO.StringWriter stringWriter = new System.IO.StringWriter();
    System.Web.UI.HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

    // Replace all gridview controls with literals
    ClearControls(AccountGrid);

    // Throws exception: Control ‘ComputerGrid’ of type ‘GridView’
    // must be placed inside a form tag with runat=server.
    // ComputerGrid.RenderControl(htmlWrite);

    // Alternate to ComputerGrid.RenderControl above
    System.Web.UI.HtmlControls.HtmlForm form
        = new System.Web.UI.HtmlControls.HtmlForm();
    Controls.Add(form);
    form.Controls.Add(AccountGrid);
    form.RenderControl(htmlWriter);

    Response.Write(stringWriter.ToString());
    Response.End();
}

private void ClearControls(Control control)
{
    for (int i = control.Controls.Count - 1; i >= 0; i–)
    {
        ClearControls(control.Controls[i]);
    }

    if (!(control is TableCell))
    {
        if (control.GetType().GetProperty(“SelectedItem”) != null)
        {
            LiteralControl literal = new LiteralControl();
            control.Parent.Controls.Add(literal);
            try
            {
                literal.Text =
                    (string)control.GetType().GetProperty(“SelectedItem”).
                        GetValue(control, null);
            }
            catch
            {}
            control.Parent.Controls.Remove(control);
        }
        else if (control.GetType().GetProperty(“Text”) != null)
        {
            LiteralControl literal = new LiteralControl();
            control.Parent.Controls.Add(literal);
            literal.Text =
                (string)control.GetType().GetProperty(“Text”).
                    GetValue(control, null);
            control.Parent.Controls.Remove(control);
        }
    }
    return;
}
 

Update: 7/30/2008

I previously noted that SetCacheability doesn’t seem to make a difference.  Well, I was right…until I deployed my code to a site behind SSL.  As it turns out, in order for Internet Explorer to open documents in Office (or any out-of-process, ActiveX document server), Internet Explorer must save the file to the local cache directory and ask the associated application to load the file by using IPersistFile::Load.

http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&

If the file is not stored to disk, this operation fails. When Internet Explorer communicates with a secure Web site through SSL, Internet Explorer enforces any no-cache request. If the header or headers are present, Internet Explorer does not cache the file. Consequently, Office cannot open the file.

RESOLUTION: Web sites that want to allow this type of operation should remove the no-cache header or headers. In other words, comment out the following line of code particularly if you are running under SSL:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache); 

Additional Comments

Per Jinath Blog, if you are using an UpdatePanel, you may get a System.WebForms.PageRequestManagerParserErrorException exception.  The solution is to add a PostBackTrigger and give it’s ControlID as the excel export button’s ID or you can move your excel export button out side of the update panel.  I verified both options and they work great.  I ultimately went with the former option as such:

    ...
    </ContentTemplate>
    <Triggers>
        <asp:PostBackTrigger ControlID=”btnExport” />
    </Triggers>
</asp:UpdatePanel>

Per ASPAlliance, you may encounter issues a number of issues which require the following solution.  Check out the link (and the comments) for more details if you get stuck.  I only encountered #1 on the list.

  1. You may get an exception which states your Control ‘Grid’ of type ‘GridView’ must be placed inside a form tag with runat=server.  I overcame this by dynamically adding a form to the page and then the GridView to the form before RenderContent().  This solution came per the aforementioned post’s comments.
  2. You may need to included the following page directive: EnableEventValidation=”false”.  I didn’t need to include this directive.
  3. You may need Override the VerifyRenderingInServerForm Method.  I didn’t need to do so because I added my GridView control to a “mocked” form.
     

Per Dipal Choksi, one can format the spreadsheet results in a generic manner by replacing all controls within the GridView with Literals.  This is reflected in the ClearControls() method above.  My prior implementation merely cleaned up the links associated with the sort functionality tied to the sortable headers.  This solution tackles all cells.

Additional Reference: GridViewGuy 

kick it on DotNetKicks.com


C# Encryption / Decryption Helper Class

03

July

I have collected a reasonably good size library of C# helper files over the years.  The EncryptionHelper below is one of many which I plan to share.

using System;
using System.Security.Cryptography;
using System.Text;

namespace Common
{
    public static class EncryptionHelper
    {
        private const string cryptoKey = "cryptoKey";

        // The Initialization Vector for the DES encryption routine
        private static readonly byte[] IV =
            new byte[8] { 240, 3, 45, 29, 0, 76, 173, 59 };

        /// <summary>
        /// Encrypts provided string parameter
        /// </summary>
        public static string Encrypt(string s)
        {
            if (s == null || s.Length == 0) return string.Empty;

            string result = string.Empty;

            try
            {
                byte[] buffer = Encoding.ASCII.GetBytes(s);

                TripleDESCryptoServiceProvider des =
                    new TripleDESCryptoServiceProvider();

                MD5CryptoServiceProvider MD5 =
                    new MD5CryptoServiceProvider();

                des.Key =
                    MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(cryptoKey));

                des.IV = IV;
                result = Convert.ToBase64String(
                    des.CreateEncryptor().TransformFinalBlock(
                        buffer, 0, buffer.Length));
            }
            catch
            {
                throw;
            }

            return result;
        }

        /// <summary>
        /// Decrypts provided string parameter
        /// </summary>
        public static string Decrypt(string s)
        {
            if (s == null || s.Length == 0) return string.Empty;

            string result = string.Empty;

            try
            {
                byte[] buffer = Convert.FromBase64String(s);

                TripleDESCryptoServiceProvider des =
                    new TripleDESCryptoServiceProvider();

                MD5CryptoServiceProvider MD5 =
                    new MD5CryptoServiceProvider();

                des.Key =
                    MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(cryptoKey));

                des.IV = IV;

                result = Encoding.ASCII.GetString(
                    des.CreateDecryptor().TransformFinalBlock(
                    buffer, 0, buffer.Length));
            }
            catch
            {
                throw;
            }

            return result;
        }
    }
}

You may have noticed that my recent posts have been short and provide little more than featured code.   This is a new approach for me.  What do you think?  Should I continue to pepper in these quick code snippet posts with little commentary?

 

kick it on DotNetKicks.com


LinkButton Image

02

July

I am not a CSS expert, but the following technique can be used to easily apply an image next to virtually any link. 

First you need to define your CSS class which sets the background to a referenced image. 

.icon-cancel {
    background: url(../images/icons/cancel.gif) no-repeat left top;
    display:inline;
    padding-left:18px;
    margin-left: 10px;
    padding-right:10px;
}

Once defined, assign the class to your hyperlink.

<a href=”#” class=”icon-cancel”>Cancel</a>
 

You may need to play with padding and margin, but you will end up with something similar to the following result:

image 
 

I used this technique to pretty up a very plain GridView display by applying classes to my edit, update and cancel linkbuttons today.  All it took was the creation of a few more CSS classes and linkbutton class tag updates.  image

 
 
 
 
 
 
 
 
 
 
<asp:TemplateField ShowHeader=”False”>
    <EditItemTemplate>
        <asp:LinkButton ID=”LinkButton1″ runat=”server” CausesValidation=”True”
            CommandName=”Update” class=”icon-save” Text=”Update”></asp:LinkButton>
        <asp:LinkButton ID=”LinkButton2″ runat=”server” CausesValidation=”False”
            CommandName=”Cancel” class=”icon-cancel” Text=”Cancel”></asp:LinkButton>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:LinkButton ID=”LinkButton1″ runat=”server” CausesValidation=”False”
            CommandName=”Edit” class=”icon-edit” Text=”Edit”></asp:LinkButton>
    </ItemTemplate>
</asp:TemplateField>
 

kick it on DotNetKicks.com


Check Status of Windows Service

01

July

In the same vein as my last post on how to programmatically update a service startup type, here’s how one might determine if a service is currently stopped in C#:

using System.Management;
/// <summary>
/// This routine checks if the provided service is stopped.
/// </summary>
/// <param name="serviceName">Name of the service to be checked</param>
/// <param name="errorMsg">If applicable, error message assoicated with exception</param>
/// <returns>Stopped = true else false</returns>
public static bool IsServiceStopped(string serviceName, out string errorMsg)
{
    bool isStopped = false;
    errorMsg = string.Empty;

    string filter =
        String.Format("SELECT * FROM Win32_Service WHERE Name = ‘{0}’", serviceName);

    ManagementObjectSearcher query = new ManagementObjectSearcher(filter);

    // No match = stopped
    if (query == null) return false;

    try
    {
        ManagementObjectCollection services = query.Get();

        foreach (ManagementObject service in services)
        {
            string currentStatus = Convert.ToString(service["State"]);
            isStopped = (currentStatus.ToLower() == "stopped");
        }
    }
    catch (Exception ex)
    {
        errorMsg = ex.Message;
        throw;
    }

    return isStopped;
}

kick it on DotNetKicks.com


Update Service Startup Type

01

July

For the past six years I’ve been focused on web applications.  My current project, however, has me splitting time between the web and the desktop.  Today, I needed to programmatically toggle the Startup Type of my service between Manual and Automatic based on business conditions.   Here’s how I did it:

/// <summary>
/// This routine updates the start mode of the provided service.
/// </summary>
/// <param name="serviceName">Name of the service to be updated</param>
/// <param name="startMode">Manual or Automatic. This parameter could probably use
/// an enum.</param>
/// <param name="errorMsg">If applicable, error message assoicated with exception</param>
/// <returns>Success or failure.  False is returned if service is not found.</returns>
public bool ServiceStartModeUpdate(string serviceName, string startMode,
    out string errorMsg)
{
    uint success = 1;
    errorMsg = string.Empty;

    string filter =
        String.Format("SELECT * FROM Win32_Service WHERE Name = ‘{0}’", serviceName);

    ManagementObjectSearcher query = new ManagementObjectSearcher(filter);

    // No match = failed condition
    if (query == null) return false; 

    try
    {
        ManagementObjectCollection services = query.Get();

        foreach (ManagementObject service in services)
        {
            ManagementBaseObject inParams =
                service.GetMethodParameters("ChangeStartMode");
            inParams["startmode"] = startMode;

            ManagementBaseObject outParams =
                service.InvokeMethod("ChangeStartMode", inParams, null);
            success = Convert.ToUInt16(outParams.Properties["ReturnValue"].Value);
        }
    }
    catch (Exception ex)
    {
        errorMsg = ex.Message;
        throw;
    }

    return (success == 0);
}

As I’ve been doing a lot with services and windows applications lately, don’t be surprised in up coming posts start moving down this track.  Oh yes, I’ve done a lot with custom installers which I’m sure to write about as well.

kick it on DotNetKicks.com


Safe Cast for No Good Reason

10

June

I’m not sure I can come up with a good argument to ever use Safe Casting.  Per my earlier post, I’m not able to convert the result of the following Predicate, List<MachineProduct>, to a MachineProductCollection even though MachineProductCollection inherits from List<MachineProduct>.  

// Code complies and the invalid Cast results in
// machineProducts being set to null instead of an
// exception being thrown.
MachineProductCollection machineProducts =
    MachineProductList.FindAll(c => c.MachineID == MachineID)
    as MachineProductCollection;

As statement in the above comment, the invalid cast is essentially masked due to the Safe Cast or the convert using the "as" operator.  Alternative implementations, I believe, are more appropriate as an implicit conversion causes a pre-runtime, compilation error and a "traditional" cast throws an InvalidCastException at runtime, respectively:

// Compiler complains since it knows List<MachineProduct> can not
// be converted to MachineProductCollection
MachineProductCollection machineProducts =
        MachineProductList.FindAll(c => c.MachineID == MachineID);

// Code compiles but a runtime InvalidCastException is thrown
// since List<MachineProduct> can not be converted to
// MachineProductCollection
MachineProductCollection machineProducts = (MachineProductCollection)
        MachineProductList.FindAll(c => c.MachineID == MachineID);

I’m probably missing something but I can’t think of a scenario in which I would intentionally want to assign a null value if my cast is invalid.  Why "swallow" the exception and work with bad data?  It doesn’t make sense to me.

I’ve read that one should use the "is" operator in conjunction with the "as" operator.  Basically, this ensures the conversion is valid before it is executed, but what is the point.  Do more work to get the same lousy, invalid result?

// What is the point of this?
MachineProductCollection machineProducts = null;

if (MachineProductList.FindAll(c =>
    c.MachineID == MachineID) is MachineProductCollection)
{
    machineProducts = MachineProductList.FindAll(c => c.MachineID == MachineID)
        as MachineProductCollection;
}

Perhaps I should have taken more CS classes in college…

Additional References:

kick it on DotNetKicks.com


InvalidCastException Though Same Base Class

10

June

The following code throws an InvalidCastException.

public static MachineProductCollection MachineProductsForMachine(
    MachineProductCollection MachineProductList, int MachineID)
{
    return (MachineProductCollection)
        MachineProductList.FindAll(c => c.MachineID == MachineID);
} 

This surprises me since MachineProductCollection is merely a generic List of MachineProducts which is exactly FindAll() returns.  Here’s the full MachineProductCollection source code:

[Serializable]
public partial classMachineProductCollection :
        List<MachineProduct>
{
    public MachineProductCollection() { }
}

I resorted to the following which basically loops through the resulting List<MachineProduct> and adds them to my MachineProductCollection.  Obviously, I don’t like the required iteration. 

public static MachineProductCollection
    MachineProductForMachine(MachineProductCollection
    MachineProductList, int MachineID)
{
    MachineProductCollection result =
        new MachineProductCollection();

    foreach (MachineProduct machineProduct in
        MachineProductList.FindAll(c => c.MachineID == MachineID))
    {
        result.Add(machineProduct);
    }

    return result;
}

Documentation states an InvalidCastException is thrown when a failure occurs during an explicit reference conversion. Reference conversions are conversions from one reference type to another. While they may change the type of the reference, they never change the type or value of the conversion’s target. Casting objects from one type to another is a frequent cause for this exception.

Considering List<MachineProduct> is MachineProductCollection’s base, should this really be an InvalidCastException?

kick it on DotNetKicks.com


Custom Templates with SubSonic

09

June

Over the weekend, I found myself doing a lot of grunt work creating more than my fair share of data transfer objects which, for me, are nothing more than custom collections which contain very simple objects exposing public properties.  Simple, but cumbersome enough that I wanted to generate the classes.

I have been working with SubSonic for a few weeks now but I didn’t realize the tool could generate files based on custom/personalized templates.  It’s a good thing Jon Galloway still tolerates my stupid questions or I might still not know…

Here’s how it is done using the base SubSonic install (assumes Sonic.exe and the default templates can be found under c://program files/.)

  1. Make a copy of the default templates folder as found in C:\Program Files\SubSonic\SubSonic 2.0.3\src\SubSonic\CodeGeneration\Templates.  I named my copied folder "SimpleClassTemplates."
  2. Open the aspx files in Visual Studio and modify to your heart’s content.  For example, I wanted an alternate C# class template so I modified CS_ClassTemplate.aspx.
  3. I am going to assume you are already familiar with code generation with SubSonic.  I perimagesonally like to setup a Visual Studio External Tool to allow for quick, pre-configured regeneration.  Otherwise, the following can be ported over to the command line.  Here’s the External Tool setup instructions:
    • Tools > External Tools > Add
    • Title: SubSonic Classes
    • Command: C:\Program Files\SubSonic\SubSonic 2.0.3\SubCommander\sonic.exe
    • Arguments: generate /out Generated /namespace NAMESPACE /server SERVER/db DATABASE where NAMESPACE, SERVER and DATABASE are replaced accordingly.
    • Initial Directory: $(ProjectDir)
    • Check "Use Output window" and "Prompt for arguments."
    • Select Apply or OK
  4. Select the project which will contain the "Generated" folder and auto-generated files.  Select Tool > SubSonic Classes.
  5. Enjoy. 
kick it on DotNetKicks.com


C# Serializing Nullable Types

09

June

There’s a lot of information (including sample routines) on how to serialize/deserialize objects in C#.  Hunt down a couple of routines that accept generic types and add them to your personal utility class and reuse them forever.  Be aware, however, that there’s an issue with serializing nullable types. Basically it can’t be done if an object’s property is marked with an XmlAttribute.  You will need to mark the property as an XmlElement.

[XmlElement(IsNullable=true)]
public DateTime? MachineDateChange { get ; set ; }

And use some caution as the property datatype must match the IsNullable setting for the XmlElement markup.  Believe it or not, the following "type mismatch" will throw an exception when serializing since MachineDateChange, in the following case, isn’t actually nullable like it is above:

[XmlElement(IsNullable = true)]
public DateTime MachineDateChange { get; set; }

Here are a couple of good resources:

kick it on DotNetKicks.com


C# Coalesce Operator

09

June

My favorite TSQL Function is COALESCE which returns the first non-null expression among its arguments.  If all arguments are null, null is returned.  Here are a couple of simple examples:

declare @a varchar(25); set @a = null;
declare @b varchar(25); set @b = null;
declare @c varchar(25); set @c = ‘I am not null’;

select coalesce(@a, @b, @c);

————————-
I am not null            

(1 row(s) affected)

select coalesce(@a, @b);

————————-
NULL

(1 row(s) affected)

Coalesce can be really slick especially if you want to concatenate multiple rows into a single string.

As of .NET 2.0 we can use the C# Coalesce Operator.  The same concept applies — provided arguments are evaluated and the first non-null argument is returned.

RegistryKey regKey = Registry.LocalMachine.OpenSubKey(baseKey, true) ??
                     Registry.LocalMachine.CreateSubKey(baseKey);

Above you will notice "??" is the delimiter.  If the baseKey can’t be found, the first argument evaluates to null.  In turn, the second argument will create the baseKey and return the reference.  I’ve found this particular pattern (return reference if it exists, else create reference and return) to be most useful. 

The above code snippet is for demonstration purposes only.  It should be noted that the CreateSubKey function creates a new subkey or opens an existing subkey on its own.  Perhaps CreateSubKey uses a form of the Coalesce Operator itself…

kick it on DotNetKicks.com


Path.Combine() for URLs

08

June

You are familiar with System.IO.Path.Combine() method which combines two path strings and manages the trailing separator character (a.k.a. a backslash ("\")), right?  Here’s an example of what I am talking about:

System.IO.Path.Combine("C:\temp", "subdir\file.txt");// output = "c:\temp\subdir\file.txt"

Are you bored yet? :) 

Okay, pop quiz. In my current project, I need to download a file and I would like to effortlessly add-or-not-add-the-trailing-slash when building my URL.  I would think there would be a URL equivalent but I haven’t uncovered one.  Using Path.Combine() as-is gets me close although backslashes get mixed with my forward slashes:

string output = System.IO.Path.Combine("http://www.abc.com/msi", "app.msi");

// output = http://www.abc.com/msi\\app.msi

So, I threw in a replace which seems to work well although it smells really bad to me. (Hence this post.)  Below you will find my, um, findings.  Is there a better way or does using Replace() smell okay to you?

string pathWithEndingSlash = "http://www.abc.com/msi/";
string file = "app.msi";
string output = System.IO.Path.Combine(pathWithEndingSlash, file).Replace("\\", "/");
// output = http://www.abc.com/msi/app.msi

string pathWithoutEndingSlash = "http://www.abc.com/msi";
output = System.IO.Path.Combine(pathWithoutEndingSlash, file).Replace("\\", "/");
// output = http://www.abc.com/msi/app.msi

string pathEmpty = string.Empty;
output = System.IO.Path.Combine(pathEmpty, file).Replace("\\", "/");
// output = Returns app.msi

try
{
    string pathNull = null;
    output = System.IO.Path.Combine(pathNull, file).Replace("\\", "/");
}
catch
{
    // Throws exception as would same statement without the .Replace()
}

string fileEmpty = string.Empty;
output = System.IO.Path.Combine(pathWithoutEndingSlash, fileEmpty).Replace("\\", "/");
// output = http://www.abc.com/msi

try
{
    string fileNull = null;
    output = System.IO.Path.Combine(pathWithoutEndingSlash, fileNull).Replace("\\", "/");
}
catch
{
    // Throws exception as would same statement without the .Replace()
}
kick it on DotNetKicks.com


Copy/Paste Lost Due To UpdatePanel

25

May

I ran into a strange case this evening.  Rendered text can not be copied to the clipboard after posting back a page containing an UpdatePanel. 

Here’s a simple use case:

  1. User enters client name and clicks button to request phone number.
  2. Page posts back and displays phone number.
  3. User selects the phone number, CTRL+C and attempted to CTRL+V into their contact list.
  4. User gets frustrated because the phone number was selectable but apparently could not be copied.

One might assume only the phone number can’t be copied.  Maybe the changing of the text and visible properties of the associated ASP:Label control is to blame.  Well, that’s not the case.  ALL text on the page can no longer be copied after the postback. 

Basically, add an UpdatePanel to a page, postback and you can’t copy anything to the clipboard.  By the way, I discovered the problem while using FireFox 2.0. I tested against IE 7 and I wasn’t able to duplicate the experience.

Try out the most simplistic example I could come up with below.  It might surprise you.

<%@ Page Language="C#" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:UpdateProgress ID="UpdateProgress1" runat="server">
        <ProgressTemplate>
            <img id="Img1" runat="server" src="AjaxIndicator.gif"/>
        </ProgressTemplate>
    </asp:UpdateProgress>
    <asp:ScriptManager ID="scriptManager" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="updatePanel" runat="server">
        <ContentTemplate>
        <asp:Label ID="message" runat="server">
            This is asp:Label text inside the update panel
                and it can be selected and copied only
                before the postback but not after.</asp:Label>
        <br />
        <br />
            This is regular text inside the update panel
                and it acts the same.
        <br />
        <br />
        <asp:Button ID="button" runat="server" Text="Go" />
        </ContentTemplate>
    </asp:UpdatePanel>

    This text is outside of the update panel and
    it acts the same as well.

    </form>
</body>
</html>
kick it on DotNetKicks.com


Undo Functionality with a Limited Stack

07

January

After hours of discussions and documentation, we had a good understanding of the functional requirements.  The ask was for a very complex, intelligent and “AJAXy” web application which would give financial advisors the ability to rebalance their clients’ portfolios based on a specified investment objective.  Everyone was excited (especially me) until the final requirement was issued: “We would like the ability to undo actions.”

The request was reasonable.  If I were an advisor I would wish for this feature as well, but this was a web application with literally dozens of ways to extend, manipulate and delete data. I had concerns but I agree to evaluate and potentially prototype.  Before the meeting closed I was able to set the expectation that we would most likely need to limit the number of undos — after all we weren’t dealing with a web application with unlimited resources.

As it turned out, the implementation worked itself out nicely.  Rather than “logging” each action, I opted to store the state of the data AFTER each action.  For example, instead of being concerned about how a security was added to the client’s portfolio, I started caring only about the resulting new data item.  As form changes were made, I pushed a copy of the new state onto a “LimitedStack.”  When the undo action was triggered, I would then pop the previous state off the stack and update the form accordingly.  Finally, as the stack approach the maximum number of undos, the item in the first position would be removed in order to make room for the new item being push into the last position. 

At the moment, we are allowing for up to 6 undos.  Each undo is being managed within the LimitedStack in Session State.  I am concerned that we are effectively using ~6 times more memory to accommodate this requirement, but I’m hopeful that performance testing will ease my worries. 

I’ve include the LimitedStack logic below.  You will see it is using the LinkedList<T> as its base.

I also found the copying of the state (which was a collections of nested objec references) to be an interesting problem which needed solving.  I hope to comment about deep copying soon.

[Serializable()]
public class LimitedStack<T> : LinkedList<T>
{
    private int _maxItems;

    public int MaxItems
    {
        get { return _maxItems; }
        set
        {
            while (this.Count > value)
            {
                this.RemoveFirst();
            }
            _maxItems = value;
        }
    }

    public LimitedStack(int num)
    {
        _maxItems = num;
    }

    public T Peek()
    {
        return this.Last.Value;
    }

    public T Pop()
    {
        LinkedListNode<T> node = this.Last;
        this.RemoveLast();
        return node.Value;
    }

    public void Push(T value)
    {
        LinkedListNode<T> node = new LinkedListNode<T>(value);
        this.AddLast(node);

        if (this.Count > _maxItems)
        {
            this.RemoveFirst();
        }
    }
}


Brain Scratcher of the Day

07

September

We ran into the following issue two days ago.  In a nutshell, the “initialCategory” was not being selected in the Categories dropdown by default.  Yes, I recognize that the code itself may be written in fewer lines, but please only focus on the differences between the two code snippets below.  I haven’t had the time to research, but this code has been rolling around in my head ever since a developer presented the “fix” to me yesterday morning.  As far as I can tell, only syntax has changed.  I would expected the code to work in both case, to be honest, but the “before” code didn’t function correctly with our last release.

Any thoughts?

 

Before

for(int i=0;i<cboCategories.Items.Count;i++)
{
    if(initialCategory != string.Empty)
    {
        if(cboCategories.Items[i].Value.ToLower()==initialCategory.ToLower())
        {
            cboCategories.Items[i].Selected=true;
            break;
        }
    }
    else if(cboCategories.Items[i].Value==all)
    {
        cboCategories.Items[i].Selected=true;
        break;
    }
}

After

for(int i=0;i<cboCategories.Items.Count;i++)
{
    if(initialCategory != string.Empty)
    {
        if(cboCategories.Items[i].Value.ToLower()==initialCategory.ToLower())
        {
            //cboCategories.Items[i].Selected=true;
            cboCategories.SelectedIndex = i;
            break;
        }
    }
    else if(cboCategories.Items[i].Value==all)
    {
        //cboCategories.Items[i].Selected=true;
        cboCategories.SelectedIndex = i;
        break;
    }
}


Next Page »

CONTACT

RSS

ARCHIVES

READ BY TOPIC

LINKS

LINK ADS