Friday, April 11, 2008

Download HTTP Resource Without Browser

Today I saw a Silverlight video player that I liked. I wanted to see its source XAML. I got the link (http://www.asp.net/SilverlightPlayer/xaml/videoplayer.xaml). But when I put it into IE or FireFox, I got an error because the browser tries to load it using WPF. Anyway, I kept trying and couldn't figure out how to just download the xaml. If there is a shortcut (which I'm sure there is), I'd like to know.

In the meantime, I wrote a small console app that downloads some url and saves it to a local file. It's only a few lines. Create a new console app and use the following code:


class Program

{

static void Main(string[] args)

{

string uri = args[0];

string filePath = args[1];

byte[] bytes = (new WebClient()).DownloadData(args[0]);

File.WriteAllBytes(filePath, bytes);

}

}



That's it. Using that I was able to get my xaml. Gotta love that .net framework!

Friday, April 4, 2008

Unneccessay EventArgs

Disclaimer: I am not actually doing this now and it's just something to think about and is probably just an obsessive detail. While many say unnecessary or premature optimization is the root of all evil, still, as responsible programmers, we need to keep performance in mind whenever we do things. And while this example may be frivolous, it shows a pattern you can use in other, more important scenarios.

I'm sure you all would agree that the unnecessary creation of objects is not good. Wasting is something we should try to avoid. For example, wouldn't it strike you as wrong to create EventArgs objects for events that are never raised?

Take this code, which is a basic event to alert the application code when a user signs in. The event args gives the developer some more info about the user who logged in:


internal class SigninManager

{

public event EventHandler<SignedInEventArgs> SignedIn;

protected virtual void OnSignedIn(SignedInEventArgs e)

{

if (SignedIn != null)

SignedIn(this, e);

}

private void PerformSignIn()

{

//work work work

string userName = "blah";

//work work work

SignedInEventArgs args = new SignedInEventArgs() { UserName = userName };

OnSignedIn(args);

}

}

public class SignedInEventArgs: EventArgs

{

public string UserName { get; internal set; }

}



Note I'm using some C# 3 features, but this could be done with a prior version with not much work.

In OnSignedIn, you'll notice the event will never get invoked if Fooing is null. The event is only for informational purposes to outside code. If I wanted some feedback, such as a Handled property, things might be different. But I just want to tell application code that "hey, this person logged in."

If no outside code ever handles SignedIn, I am creating the SignedInEventArgs without ever using it. What I would prefer is that the event args get created only if they are needed. But I want to keep my code pretty much the same. I want to keep my OnSignedIn there so I can override it in a sub class. And I don't want to fool with event logic in PerformSignIn. What I need is "lazy instantiation", where the event args only get created if needed.

While there are several approaches, I have a pretty elegant one: use delegates. I will use lamda expressions in my code, although anonymous delegates would work fine. Check this out:

public delegate TEventArgs EventHandlerCreator<TEventArgs>();

internal class SigninManager

{

public event EventHandler<SignedInEventArgs> SignedIn;

protected virtual void OnSignedIn(EventHandlerCreator<SignedInEventArgs> argsDelegate)

{

if (SignedIn != null)

{

SignedIn(this, argsDelegate());

}

}

private void PerformSignIn()

{

//work work work

string userName = "blah";

//work work work

OnSignedIn( () => new SignedInEventArgs() { UserName = userName } );

}

}

public class SignedInEventArgs: EventArgs

{

public string UserName { get; internal set; }

}

Now, instead of passing the event args object I created, I pass a delegate that's able to create the args when invoked. So the OnSigningIn takes that delegate and only creates the args if the event is handled. If it is invoked a million times, we've saved a million objects :).

I think the code is pretty straightforward. Lamda expressions and generics make "lazy instantiation" something that's practical to acheive and maintain. Again, this could be applied to different, more meaningful situations. Regardless, it's pretty nice.

Friday, March 14, 2008

Converting Arrays to and from Delimited Strings

I figured .NET would have some strong built in support for creating delimited strings from a list or array. Turns out there's very little. For example, if you want to take an int[] and convert it to a string like 23134232233, you gotta write code.

Maybe the reason it's not there is because delimited strings can be error-prone, and serialization mechanisms support arrays. But let's forget about why, because sometimes you need to do this.

I write a few simple, yet flexible methods for accomplishing this. I used arrays, although another version of the methods could be created for IEnumerables or ICollections or whatever. For my situation, I needed only arrays so I looked past my abstraction apprehensions and just did it.

One interesting thing was that in certain situations I needed custom code to convert each item to and from its string. So my methods allow for that using a delegate. And to accomodate for all array types and for type safety, I used generic methods. So this is a cute way to blend those two features that have been around since C# 2.0.


 

        /// <summary>

        /// Takes a delimited string and returns an array of items that were converted to the type specified.  Individual value conversions

        /// are done by using the type converter ConvertFromInvariantString method.

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="value"></param>

        /// <param name="separator"></param>

        /// <returns></returns>

        public static T[] ConvertDelimitedStringToArray<T>(string value, string separator)

        {

            TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));

            Func<T, string> itemConversionHandler = delegate(string itemText)

            {

                return (T)converter.ConvertFromInvariantString(itemText);

            };

 

            return ConvertDelimitedStringToArray(value, separator, itemConversionHandler);

        }

 

        /// <summary>

        /// Takes a delimited string and returns an array of items that were converted to the type specified.

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="value"></param>

        /// <param name="separator"></param>

        /// <param name="itemConversionHandler">The delegate that converts each string item into the target type.</param>

        /// <returns></returns>

        public static T[] ConvertDelimitedStringToArray<T>(string value, string separator, Func<T,string> itemConversionHandler)

        {

            if (string.IsNullOrEmpty(value))

                return null;

 

            string[] pieces = value.Split(new string[]{separator},StringSplitOptions.None);

            T[] result = new T[pieces.Length];

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

            {

                result[i] = itemConversionHandler(pieces[i]);

            }

            return result;

        }

 

 

        /// <summary>

        /// Takes an array of items and converts it to a delimited string with the separator.  Individual value conversions

        /// are done by using the type converter ConvertToInvariantString method.

        /// </summary>

        public static string ConvertArrayToDelimitedString<T>(T[] value, string separator)

        {

            TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));

            Func<string, T> itemConversionHandler = delegate(T item)

            {

                return converter.ConvertToInvariantString(item);

            };

 

            return ConvertArrayToDelimitedString(value, separator, itemConversionHandler);

        }

 

        /// <summary>

        /// Takes an array of items and converts it to a delimited string with the separator and conversion handler provided.

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="value"></param>

        /// <param name="separator"></param>

        /// <param name="itemConversionHandler">The delegate that converts each item into a piece of text.</param>

        /// <returns></returns>

        public static string ConvertArrayToDelimitedString<T>(T[] value, string separator, Func<string,T> itemConversionHandler)

        {

            if (value == null || value.Length == 0)

                return null;

 

            string[] textPieces = new string[value.Length];

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

            {

                textPieces[i] = itemConversionHandler(value[i]);

            }

            return string.Join(separator, textPieces);

        }



If you have .NET 3.5 (I think), the Func delegate is already there. If not, you can just define it yourself:

/// <summary>

/// A delegate to a methd that returns some TReturn value and has 1 parameter.

/// </summary>

/// <typeparam name="TReturn">The type of object the method returns.</typeparam>

/// <typeparam name="TParam1">The type of the first method parameter.</typeparam>

/// <returns></returns>

internal delegate TReturn Func<TReturn, TParam1>(TParam1 param1);


That's all you need, really. To demonstrate, check out the code below:

            //create some ints and make them pipe separated

            int[] ids = new int[] { 1, 2, 3, 4 };

            string delimitedList = ConvertArrayToDelimitedString<int>(ids, "|");

            ids = ConvertDelimitedStringToArray(delimitedList, "|");//and back again

 

            //now I take some dates and put only their day in a list

            DateTime[] dates = new DateTime[] { DateTime.Parse("2/29/1980"), DateTime.Parse("3/1/1980"), DateTime.Parse("3/5/1998") };

            //my own 'custom' (albeit useless) conversion code to convert each date to have its parts separated by -

            delimitedList = ConvertArrayToDelimitedString<DateTime>(dates, "|",

                delegate(DateTime item)

                {

                    return item.ToString("MM-DD-YY");//forgive me if my format string is not right

                }//note: I could have declared the delegate in a variable above, but kept it here to confuse people and hopefully make them think I am some kind of wizard (don't you love guys like that?)

            );

Thursday, February 21, 2008

Convert percent string to double

In .NET, it's easy to convert a number to a percentage:


double value = .45;
string formatted = value.ToString("p", CultureInfo.CurrentUICulture);



No big deal. Comes out as "45.00 %" for many cultures. It's similar for the others, which things like 4"5,00 % ". Always multiplies the number by 100. Easy.

But converting it back to a double isn't so easy. double.Parse and TryParse don't work with percentages. After looking on the web for a while, I didn't find a good solution. I needed it to work for all cultures and be pretty forgiving in the input it allowed. So here's my solution:


        static double ConvertPercentageToDouble(string formattedNumber)

        {

            return ConvertPercentageToDouble(formattedNumber,CultureInfo.CurrentCulture);

        }

 

        static double ConvertPercentageToDouble(string formattedNumber, System.Globalization.CultureInfo cultureInfo)

        {

            if (string.IsNullOrEmpty(formattedNumber))

                throw new ArgumentNullException("formattedNumber");

 

            formattedNumber = formattedNumber.Replace(cultureInfo.NumberFormat.PercentSymbol, string.Empty);

 

            double value = double.Parse(formattedNumber, NumberStyles.Any, cultureInfo);

            if (value != 0)

                value /= 100.0;

 

            return value;

        }

Looking good, no?

Monday, January 28, 2008

South Florida Code Camp

If you a nerd in the South Florida area this Saturday, 2/2/08, go check out the South Florida Code Camp. It's like a mini Tech-Ed, where volunteers are presenting on various topics in the realm of modern Microsoft development. It's totally free. I am presenting on Script#, a C#->JavaScript compiler.

http://codecamp08.fladotnet.com/
Check out the agenda for a list of the various tasty talks.

Tuesday, December 18, 2007

SharePoint Quirks Mode? Booooooo!

To understand my plight, you need to understand DOCTYPE. Basically, long ago IE and others agreed to certain standards and behavior. That was a huge step for standards, and played a big role in making today's modern AJAX components possible. When they did it, they needed to preserve backwards compatibility. So, HTML pages need to include the DOCTYPE at the top, which basically indicates the version of HTML the browser behaves for. It's simple, and most modern pages include it. In fact, it's included in all new ASPX pages in Visual Studio by default:

< ! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >


If you don't have that line, browsers will go into Quirks Mode, where all the old idiosynchrasies are present. In Grid FX, we have popups and perform certain layout operations that Quirks Mode chokes on. No big deal, because we just told people to add that above line at the top of the page, which they should be doing anyway. So you'd think a very major web-based portal system like SharePoint would surely include it, right? Nope!

SharePoint, even the latest version, doesn't include that line. And if you do in fact include it, all of SharePoint's menus go wacky, because they have designed the system around all that screwed up old crap. Seriously? This is pathetic. Really pathetic.

Even controls written under ASP.NET AJAX won't work, because some don't behave correctly in Quirks Mode. Why would you worry about that when it's been many years since they changed the browsers? Can't they just change SharePoint? Yeah, sure. Best of luck.

What really sucks is that we need to have Grid FX work in SharePoint. People have already been asking about it. So now I gotta go through everything and make it work in Quirks Mode. I'm going to fly to Redmond, poop in a bag, light it, and set it on the step of the SharePoint building.

Thursday, December 13, 2007

Found my first silly coding mistake in the .NET framework

One thing I need to do to get Grid FX working in Visual Studio 2008 is to render all style attributes inline, as opposed to the embedded css classes that it was currently doing. Anyway, I spent the better part of my day changing the system (for the better in my opinion, which makes me happy). No real problems until I got a strange IndexOutOfRangeException when I called HtmlTextWriter.AddStyleAttribute more than 20 times. The HtmlTextWriter does just what its name implies - it writes the HTML for the control. The style attribute and value were perfectly valid. I couldn't find anything wrong on my side.

A while ago I used a Reflector add-in to decompile most of the .NET framework DLLs. This really comes in handy when I need to know what's really going on inside the framework. So I pulled up the method in question and found the following code (omitting the irrelevant parts):

protected virtual void AddStyleAttribute(string name, string value...

{

if (this._styleList == null)

{

this._styleList = new RenderStyle[20];

}

else if (this._styleCount > this._styleList.Length)

{

RenderStyle[] styleArray1 = new RenderStyle[this._styleList.Length * 2];

Array.Copy(this._styleList, styleArray1, this._styleList.Length);

this._styleList = styleArray1;

}

this._styleList[this._styleCount] = style1;

this._styleCount++;

}



It fails on call #21 (and 41 and 61, etc) because the person who wrote it made a very simple mistake. The line "this._styleCount > this._styleList.Length" should have used >=. Wow, such a simple error. Oddly, the AddAttribute method had pretty much the exact same code without that mistake.

It's kinda scary because you would think that if you go that route of writing code to expand an array size that you would test the limits, especially if you hardcode 20 as the initial limit. Bad coding, maybe, but it's the weak testing that I blame.

I would like to point out that you probably won't ever hit this bug because you really shouldn't use a ton of inline attributes. We do it only at design time, because the css attributes from Grid's Palette and Motif can be many, mainly because they are split into individual styles (padding-top/left/right, border-top-width, etc) rather than composite attributes like padding, border, etc. So I guess we could be the first ones to ever render more than 20 style attributes. Good thing I use external style sheets at runtime and don't have to deal with the inline style mess.

Well shit, what do I do now? I suppose I could write them and point it out. But that won't do much good because the libraries can't change. So I tried some ideas and had some luck...

I used reflection to increment the "_styleCount" field when that exception occurs. This will cause the next call to AddStyleAttribute to actually run the code to double the array size, because "this._styleCount > this._styleList.Length" will evaluate to true. This is a little dangerous because the array would have an empty element, and I could get another exception down the line. Thankfully that didn't happen, because the object in the array is a struct called RenderStyle, and is never null...and the code to write out the attributes checks against a null key or value.

So I wrote some helper methods and stuck them in a utils class. Here they are. Calling these AddStyleAttribute methods instead of the writer's AddStyle attribute would be smart. Using these calls will bypass that error. I would have preferred to use C# 3.0 extension methods instead, but I can't because we compile Grid FX off framework 2.0. Oh well, this is good enough.

///

/// Calls the HtmlTextWriter's AddStyleAttribute method, bypassing an exception that will occur after the 20th call. Th

///

public static void AddStyleAttribute(HtmlTextWriter writer, HtmlTextWriterStyle key, string value)

{

try

{

writer.AddStyleAttribute(key, value);

}

catch (IndexOutOfRangeException e)

{

IncrementHtmlTextWriterStyleCountField(writer);

writer.AddStyleAttribute(key, value);

}

}

///

/// Calls the HtmlTextWriter's AddStyleAttribute method, bypassing an exception that will occur after the 20th call. Th

///

public static void AddStyleAttribute(HtmlTextWriter writer, string name, string value)

{

try

{

writer.AddStyleAttribute(name, value);

}

catch (IndexOutOfRangeException e)

{

IncrementHtmlTextWriterStyleCountField(writer);

writer.AddStyleAttribute(name, value);

}

}

///

/// Increments the HtmlTextWriter's _styleCount field. Used to bypass a bug in the framework where IndexOutOfRangeException is thrown on the 21st, 41st, 81st, etc call to AddStyleAttribute.

///

private static void IncrementHtmlTextWriterStyleCountField(HtmlTextWriter writer)

{

//as an optimization, get the FieldInfo lazily and cache it for subsequent hits, since the lookup is the major piece of work.

//a double check locking technique is used to be thread safe but only use locking if the FieldInfo hasn't been cached.

if (m_htmlTextWriter_styleCountInfo == null)

{

lock (m_htmlTextWriter_styleCountLockObj)

{

//check again for null in case two threads entered the above if block and the first one exited the critical section

if (m_htmlTextWriter_styleCountInfo == null)

{

m_htmlTextWriter_styleCountInfo = typeof(HtmlTextWriter).GetField("_styleCount", BindingFlags.Instance | BindingFlags.NonPublic);

}

}

}

int currValue = (int)m_htmlTextWriter_styleCountInfo.GetValue(writer);

m_htmlTextWriter_styleCountInfo.SetValue(writer, currValue + 1);

}

static FieldInfo m_htmlTextWriter_styleCountInfo;

static object m_htmlTextWriter_styleCountLockObj = new object();



See ya.