Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Contents tagged with C#

  • Dump the Module keyword in VB.NET!

    Though I'm mainly a C# developer, I now and then get exposed to some VB.NET stuff. No, this is not going to be a C# vs. VB.NET debate. We've seen enough heated arguments and flame wars on that topic over the years.

    Something about VB.NET Console applications created in Visual Studio.NET (all versions), bugs me though: the dreaded Module keyword. The default skeleton for a Console app in VB.NET looks like this:

    Module Module1
        Sub Main()
        End Sub
    End Module


    Whilst under the hood, a module is simply a class with static members and a private default constructor to prevent instantiation, I don't think its use should be promoted like that. And I really wonder why MS hasn't changed the default Console app skeleton to look as follows:

    Class Program
        Shared Sub Main()
        End Sub
    End Class


    In my opinion, the Module keyword shouldn't have even existed in VB.NET. It's one of the reasons why a lot of VB.NET code I've seen simply gets dumped in a Module, and Object Oriented Programming goes out the window. Of course, there's nothing stopping you coding like that in VB.NET without using the Module keyword, or even in C# for that matter. But it is a step in the right direction in trying to get developers to think about object oriented class design first (static/shared vs. instance members etc), before shoving anything and everything in a Module.

  • Generic Parse method on Enum - a solution

    David Findley writes about how he wishes we had a generic Parse method on the Enum class in .NET 2.0.

    Though I agree in principle, it's actually quite trivial to create a generic static class with a Parse method, which alleviates some of the pain.

    Here's my stab at it:

        public static class EnumUtil<T>
        {
            public static T Parse(string s)
            {
                return (T)Enum.Parse(typeof(T), s);
            }
        }


    Say we have the following enum:

        public enum Color
        {
            Black,
            White,
            Blue,
            Red,
            Green
        }

    We can now simply use the generic EnumUtil class as follows:

    Color c = EnumUtil<Color>.Parse("Black");

    I feel that this helper method doesn't actually warrant a class in its own right, so you may want to add it to one of your Util classes (if you happen to have a generic one!) instead.

  • ArraySegment Structure - what were they thinking?

    From the MSDN docs:
    ArraySegment is a wrapper around an array that delimits a range of elements in that array. Multiple ArraySegment instances can refer to the same original array and can overlap.

    Turns out this structure doesn't even deserve the definition 'wrapper'. It simply takes the array, offset and number of elements in your segment, and sets a few properties accordingly.

    Subsequently when you want to iterate over the items in your ArraySegment, you still need to use a combination of Offset and Count to achieve this. How is this different from not creating an ArraySegment and define your Offset in-situ as well as the number of elements?

    I was expecting to be able to do something like this:

    ArraySegment<string> seg = new ArraySegment<string>(new string[] { "John","Jack","Jill","Joe"},1,2);
    // Access first item in segment
    string first = seg[0];
    // Iterate through ArraySegment
    foreach (string s in seg)
    {
        Console.WriteLine(s);
    }


    Turns out you can't. There's no indexer for ArraySegment and no enumerator. You have to access the .Array property and use .Count and .Offset as passed to the constructor. What is the point of that!?

    So I rolled my own generic DelimitedArray class which does exactly that. See the inline code below.

        public class DelimitedArray<T>
        {
            public DelimitedArray(T[] array, int offset, int count)
            {
                this._array = array;
                this._offset = offset;
                this._count = count;
            }

            private int _offset;
            private T[] _array;

            private int _count;
            public int Count
            {
                get { return this._count; }
            }

            public T this[int index]
            {
                get
                {
                    int idx = this._offset + index;
                    if (idx > this.Count - 1 || idx<0)
                    {
                        throw new IndexOutOfRangeException("Index '" + idx + "' was outside the bounds of the array.");
                    }
                    return this._array[idx];
                }
            }

            public IEnumerator<T> GetEnumerator()
            {
                for (int i = this._offset; i < this._offset + this.Count; i++)
                {
                    yield return this._array[i];
                }
            }
        }


    Hope this is of use to someone.

  • ASP.NET 1.1 server control for <link> - enabling relative URL paths using tilde "~"

    Here's a simple - but useful Link webcontrol class that supports the "~" tilde syntax for relative paths for the href attribute of the <link> element.

    [DefaultProperty("Text"),ToolboxData("<{0}:Link runat=server Href=\"\" Rel=\"Stylesheet\" Type=\"text/css\"></{0}:Link>")]
    public class Link : System.Web.UI.WebControls.WebControl
    {
        private string _href;

        public string Href
        {
            get { return _href; }
            set { _href = value; }
        }

        protected override void Render(HtmlTextWriter output)
        {
            output.WriteBeginTag("link");
            output.WriteAttribute("href",base.ResolveUrl(this.Href));
            foreach (string key in this.Attributes.Keys)
            {
                output.WriteAttribute(key,this.Attributes[key]);
            }
            output.Write(HtmlTextWriter.TagRightChar);
            output.WriteEndTag("link");
        }
    }

    You can then simply drop it in the <head> section of your page (provided you've used the Register directive to register the assembly):

    <cc1:Link id="Link1" runat="server" Type="text/css" Rel="Stylesheet" Href="~/my.css" myattribute="Whatever"></cc1:Link>

    The reason I had to roll my own is that when you add runat="server" for the <link> element, it turns into a HtmlGenericControl instance on the server, which is obviously used for numerous HTML elements, and as such no specific path resolve mechanism is applied to any of its attributes, since the attributes are different per HTML element.

    Hope it helps someone out.

  • Public available data - FREE screenscraping or pay for API

    Been working on a semi-commercial pet project of mine, for which I need a data feed.

    A decent enough subset of this data feed is publicly available from this content provider's main website. However, the full dataset (though I won't need all that) is available through an HTTP GET XML API... For a flat fee of over 500 dollars per year.

    What would you do? 1) Roll it yourself in about 20 lines of .NET code (using HttpWebRequest & Regex's) and scrape it; 2) Pay for the API...?

    Needless to say, I went for 1)...even for just the fun.

  • Why don't we see any patches for Visual Studio .NET? (2002, 2003, 2005...)

    Frans has mentioned this on numerous occasions I believe, and this topic has reared its ugly head once again. Dan Fernandez' post back in March 2004, doesn't really address the reasoning behind it.

    Personally, I really don't see the difficulty for Microsoft in releasing publicly available patches or hotfixes for VS.NET. It happens for the .NET framework, all OS'es and Office products, why not for VS.NET?

    At the lowest level, it's only shuffling around a few bits and bytes for the affected binary files. Even with the different VS.NET product versions, they could release a patch for each version if needs be.

    Anyone care to comment on the reasoning behind this?

  • Possible Bug : HttpPost and class name conflicts

    A colleague and friend of mine run into some very odd web service behaviour on ASP.NET 1.1. Anyone who can shed some light on this, please leave a comment. I have pasted his exact text describing the problem below.

    --
    Included below is a minimal web-service implementation to recreate a problem
    I've encountered in a web service that has methods returning classes with the
    same local name (but in different namespaces).

    If only the SoapHttp protocol is enabled in the web.config, everything works
    as expected - with the different "Something" classes being serialized in to
    different XML namespaces as defined by the ResponseNamespace property of the
    SoapDocumentMethod attributes.

    However - if HttpPost or HttpPostLocalhost are enabled (the latter being
    enabled by default), and I browse to the asmx file in IE, I get this error :

    Types NsProblem.B.Something and NsProblem.A.Something both use the XML type
    name, Something, from namespace http://example/NsProblem/. Use XML attributes
    to specify a unique XML name and/or namespace for the type.

    If I un-comment both of the "XmlRoot" elements I get this error

    The XML element named 'Something' from namespace 'http://example/NsProblem/'
    references distinct types NsProblem.A.Something and NsProblem.B.Something.
    Use XML attributes to specify another XML name or namespace for the element
    or types.

    Now for the really strange bit : leave one XmlRoot attribute commented, and
    the other not, and it works!

    When it is working, the example responses (on whatever.asmx?op=GetArrayA)
    don't appear to tbe any difference!

    (aside: I also tried setting the responses to be different using Xml
    Serialization attributes, i.e. putting [return: XmlElement(... )] on the
    methods, but like the SoapDocumentMethod attribute this only seemed to change
    the response for the Soap method - making no difference to the HTTP POST
    response)

    Various workarounds are available
     - disable (remove) "HttpPost" and "HttpPostLocalhost" in web.config
     - Rename the classes (making the namespaces redundant)
    but I would prefer to be able to keep the class names as they are, and keep
    the HttpPostLocalhost enabled for testing / debugging purposes - and I
    anticipate needing to support 3 or more classes with the same local-name
    across different namespaces.

    ---- Minimal test case ----

    <%@ WebService Language="c#" Class="NsProblem.XmlTestSvc" %>
    using System;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml.Serialization;

    namespace NsProblem.A
    {
    //    [XmlRoot(Namespace="AAAA")]
        public class Something { }
    }

    namespace NsProblem.B
    {
    //    [XmlRoot(Namespace="BBBB")]
        public class Something { }
    }

    namespace NsProblem
    {
        [WebService(Description="Conflicting name problem example",
    Namespace="http://example/NsProblem/")]
        public class XmlTestSvc : System.Web.Services.WebService
        {
            [WebMethod]
            [SoapDocumentMethod(ResponseNamespace="http://example/NsProblem/A")]
            public NsProblem.A.Something[] GetArrayA() { return null; }
           
            [WebMethod]
            [SoapDocumentMethod(ResponseNamespace="http://example/NsProblem/B")]
            public NsProblem.B.Something[] GetArrayB() { return null; }
        }
    }

  • MD5 or SHA1 hashing - the easy way

    This is a typical example of a static method which IMHO is in the wrong namespace.

    If you're looking to use an MD5 or SHA1 hashing algorithm to hash passwords, a lot of people would start looking in the System.Security.Cryptography namespace. But the System.Web.Security namespace offers us the FormsAuthentication.HashPasswordForStoringInConfigFile() static method:

    string pwhash = FormsAuthentication.HashPasswordForStoringInConfigFile(password, "md5");

    The second parameter can be either "md5" or "sha1".

    As far as I'm concerned, simple hashing and enrypt and decryption methods (static) should've been in System.Security.Cryptography in the first place.

    What do you think?