Archive for the ‘C# (C-Sharp)’ Category.

Splitting sentences in C# using Stanford.NLP

So I need to break some sentences up. I have a pretty cool regex that does this, however, I want to try out Stanford.NLP for this. Let’s check it out.

  1. Create a Visual Studio C# project.
    I chose a New Console Project and named it SentenceSplitter.
  2. Right-click on the project and choose “Manage NuGet Packages.
  3. Add the Stanford.NLP.CoreNLP nuget package.
  4. Add the following code to Program.cs (This is a variation of the code provide here: http://sergey-tihon.github.io/Stanford.NLP.NET/StanfordCoreNLP.html
    using edu.stanford.nlp.ling;
    using edu.stanford.nlp.pipeline;
    using java.util;
    using System;
    using System.IO;
    using Console = System.Console;
    
    namespace SentenceSplitter
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Path to the folder with models extracted from `stanford-corenlp-3.4-models.jar`
                var jarRoot = @"stanford-corenlp-3.4-models\";
    
                const string text = "I went or a run. Then I went to work. I had a good lunch meeting with a friend name John Jr. The commute home was pretty good.";
    
                // Annotation pipeline configuration
                var props = new Properties();
                props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref");
                props.setProperty("sutime.binders", "0");
    
                // We should change current directory, so StanfordCoreNLP could find all the model files automatically 
                var curDir = Environment.CurrentDirectory;
                Directory.SetCurrentDirectory(jarRoot);
                var pipeline = new StanfordCoreNLP(props);
                Directory.SetCurrentDirectory(curDir);
    
                // Annotation
                var annotation = new Annotation(text);
                pipeline.annotate(annotation);
    
                // these are all the sentences in this document
                // a CoreMap is essentially a Map that uses class objects as keys and has values with custom types
                var sentences = annotation.get(typeof(CoreAnnotations.SentencesAnnotation));
                if (sentences == null)
                {
                    return;
                }
                foreach (Annotation sentence in sentences as ArrayList)
                {
                    Console.WriteLine(sentence);
                }
            }
        }
    }
    

    Warning! If you try to run here, you will get the following exception: Unrecoverable error while loading a tagger model

    java.lang.RuntimeException was unhandled
      HResult=-2146233088
      Message=edu.stanford.nlp.io.RuntimeIOException: Unrecoverable error while loading a tagger model
      Source=stanford-corenlp-3.4
      StackTrace:
           at edu.stanford.nlp.pipeline.StanfordCoreNLP.4.create()
           at edu.stanford.nlp.pipeline.AnnotatorPool.get(String name)
           at edu.stanford.nlp.pipeline.StanfordCoreNLP.construct(Properties A_1, Boolean A_2)
           at edu.stanford.nlp.pipeline.StanfordCoreNLP..ctor(Properties props, Boolean enforceRequirements)
           at edu.stanford.nlp.pipeline.StanfordCoreNLP..ctor(Properties props)
           at SentenceSplitter.Program.Main(String[] args) in c:\Users\jbarneck\Documents\Projects\NLP\SentenceSplitter\SentenceSplitter\Program.cs:line 20
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: edu.stanford.nlp.io.RuntimeIOException
           HResult=-2146233088
           Message=Unrecoverable error while loading a tagger model
           Source=stanford-corenlp-3.4
           StackTrace:
                at edu.stanford.nlp.tagger.maxent.MaxentTagger.readModelAndInit(Properties config, String modelFileOrUrl, Boolean printLoading)
                at edu.stanford.nlp.tagger.maxent.MaxentTagger..ctor(String modelFile, Properties config, Boolean printLoading)
                at edu.stanford.nlp.tagger.maxent.MaxentTagger..ctor(String modelFile)
                at edu.stanford.nlp.pipeline.POSTaggerAnnotator.loadModel(String A_0, Boolean A_1)
                at edu.stanford.nlp.pipeline.POSTaggerAnnotator..ctor(String annotatorName, Properties props)
                at edu.stanford.nlp.pipeline.StanfordCoreNLP.4.create()
           InnerException: java.io.IOException
                HResult=-2146233088
                Message=Unable to resolve "edu/stanford/nlp/models/pos-tagger/english-left3words/english-left3words-distsim.tagger" as either class path, filename or URL
                Source=stanford-corenlp-3.4
                StackTrace:
                     at edu.stanford.nlp.io.IOUtils.getInputStreamFromURLOrClasspathOrFileSystem(String textFileOrUrl)
                     at edu.stanford.nlp.tagger.maxent.MaxentTagger.readModelAndInit(Properties config, String modelFileOrUrl, Boolean printLoading)
                InnerException: 
    
    
  5. Download the stanford-corenlp-full-3.4.x.zip file from here: http://nlp.stanford.edu/software/corenlp.shtml#Download
  6. Extract the stanford-corenlp-full-2014-6-16.x.zip.
    Note: Over time, as new versions come out, make sure the version you download matches the version of your NuGet package.
  7. Extract the stanford-corenlp-3.4-models.jar file to stanford-corenlp-3.4-models.
    I used 7zip to extract the jar file.
  8. Copy the stanford-corenlp-3.4-models folder to your Visual Studio project files.
    Note: This is one way to include the jar file in your project. Other ways might be a copy action or another good way would be to use an app.config appSetting. I chose this way because it makes all my files part of the project for this demo. I would probably use the app.config method in production.
  9. In Visual Studio, use ctrl + left click to  highlight the stanford-corenlp-3.4-models folder and all subfolders.
  10. Open Properties (Press F4), and change the namespace provider setting to false.
  11. In Visual Studio, use ctrl + left click to  highlight the files under the stanford-corenlp-3.4-models folder and all files in all subfolders.
  12. Open Properties (Press F4), and change the Build Action to Content and the Copy to Output Directory setting to Copy if newer.
  13. Run the code.

 

Note: At first I tried to just load the model file. That doesn’t work. I got an exception. I had to set the @jarpath as shown above. I needed to copy all the contents of the jar file.

Results

Notice that I through it curve ball by ending a sentence with Jr. It still figured it out.

I went or a run. Then I went to work. I had a good lunch meeting with a friend name John Jr. The commute home was pretty good.

However, I just tried this paragraph and it did NOT detect the break after the first sentence.

Exit Room A. Turn right. Go down the hall to the first door. Enter Room B.

I am pretty sure this second failure is due to the similarity in string with a legitimate first name, middle initial, last name.

Jared A. Barneck
Room A. Turn

Now the question is, how do I train it to not make such mistakes?

Aspx CheckBoxList Alternative that allows for the OnCheckedChanged event

My team had to edit an older apsx website and add a list of CheckBoxes, which are actually html <input type="checkbox"/> tags.  We assumed that CheckBoxList would be perfect for our task. We assumed wrong.

I wrote desktop apps for years and now that I am writing web apps, I am using MVC and Razor, so I missed the aspx days. However, having to work on legacy aspx applications is catching me up.

My use case for list of CheckBoxes

Really, my use case is simple. There are icons that should show up for some products. We wanted to store a map between products and the icons in the database. On the product page, we want a list of the icons with a checkbox by each list item. This would allow the person who creates new products to select which icons to show on a product download page.

  1. Get a list of option from a database and display that list as html checkboxes.
  2. Checking a checkbox should add a row to a database table.
  3. Unchecking a checkbox should remove that row from a database table.

CheckBoxList Fails

So what I needed was an OnClick event which is actually called OnCheckedChanged in an asp:Checkbox. Well, it turns out that the CheckBoxList control doesn’t support the OnCheckedChanged event per CheckBox. The CheckBoxList doesn’t have any type of OnClick method. Instead, there is an OnSelectedIndexChanged event. But OnSelectedIndexChanged doesn’t even tell you which CheckBox was clicked. If a CheckBox is checked, then in the OnSelectedIndexChanged event, the SelectedItem equals the clicked item, however, if the CheckBox is unchecked, the SelectedItem was a completely different CheckBox that is checked.

So to me, this made the CheckBoxList control not usable. So I set out to replicate a CheckBoxList in a way that supports OnCheckedChanged.

Repeater with CheckBox for ItemTemplate

I ended up using the Repeater control with an ItemTemplate containing a CheckBox. Using this method worked pretty much flawlessly. It leaves me to wonder, why was CheckBoxList created in the first place if a Repeater with a CheckBox in the template works perfectly well.

Here is my code:

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CheckBoxListExample._Default" %>

<%@ Import Namespace="CheckBoxListExample" %>
<%@ Import Namespace="CheckBoxListExample.Models" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <div>
        <asp:Repeater ID="Repeater1" runat="server">
            <ItemTemplate>
                <asp:CheckBox ID="cb1" runat="server" AutoPostBack="true" OnCheckedChanged="RepeaterCheckBoxChanged"
                    Text="<%# ((CheckBoxViewModel)Container.DataItem).Name %>"
                    Checked="<%# ((CheckBoxViewModel)Container.DataItem).IsChecked %>" />
            </ItemTemplate>
        </asp:Repeater>
    </div>
</asp:Content>
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using CheckBoxListExample.Models;

namespace CheckBoxListExample
{
    public partial class _Default : Page
    {
        private List<CheckBoxViewModel> _ViewModels;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                var _ViewModels = new List<CheckBoxViewModel>
                {
                    new CheckBoxViewModel {Name = "Test1", IsChecked = true},
                    new CheckBoxViewModel {Name = "Test2"},
                    new CheckBoxViewModel {Name = "Test3"}
                };
                Repeater1.DataSource = _ViewModels;
                Repeater1.DataBind();
            }
        }

        protected void RepeaterCheckBoxChanged(object sender, EventArgs e)
        {
            var cb = sender as CheckBox;
            if (cb == null) return;
            if (cb.Checked)
            {
                // Insert
            }
            else
            {
                // Delete
            }
        }
    }
}
namespace CheckBoxListExample.Models
{
    public class CheckBoxViewModel
    {
        public string Name { get; set; }
        public bool IsChecked { get; set; }
    }
}

Why to use string.format() over concatenation (Real world experience)

So today I was working on reverse engineering some old code. I will strip this down and remove proprietary info but still let you see the bug. This is a post for newbies but experienced coders might get a laugh out of this as well.

Here is the error code:

var contract = CustomerId + ProductGroupId + EndDate.ToString("yy-MM");

Now, imagine these values:

CustomerId = 12345
ProductId = 4
Date = 8/7/2014

A new developer would assume that this would return the following:

12345415-08

They would be wrong. See, CustomerId and ProductGroupId are integers. So they don’t concatenate as strings, they add as integers. The real value is this:

1234915-08

12345 + 4 = 12349. This is math, not string concatenation.

How would a developer resolve this bug? There are two solutions:

  • Use ToString() and concatenation (DO NOT USE!)
  • Use string.Concat() (USE FOR SIMPLE CONCATENATION OR PERFORMANCE!)
  • Use string.Format() (USE FOR CONCATENATION WITH FORMATTING!)

Here is the another interesting fact. I know exactly when this bug was introduced into the system. This code was written by the developer using the first solution. The developer had originally added .ToString() to the end of these objects. The developer didn’t write buggy code. He wrote code that worked.

The code used to look like this:

var contract = CustomerId.ToString() + ProductGroupId.ToString() + EndDate.ToString("yy-MM");

So what happened? If a developer didn’t break this code, who did?

I’ll tell you what happened and who did it. Resharper.

Today, developers aren’t the only ones messing with our code. We use tools that are pretty awesome to do masses of code automation for us. One of these tools is Resharper. Well, Resharper detected the ToString() methods as “Redundant Code.” Oh, in this case, it wasn’t redundant code.

The only reason I found this bug is because I was rewriting this piece of code and had to reconstruct a ContractId and I began reverse engineering this code. I noticed that the first part of the ContractId was the CustomerId up until a few months ago. After that, it seemed to be slightly off. I was able to check source from back then and see the difference and see why this bug started. Sure enough, when resharper cleaned up my redundant code, it removed the ToString() methods.

However, while this is a Resharper bug, let’s not jump so fast to blaming Resharper. I’ll submit a bug to them, but are they really at fault? I say not completely. Why? Because the developer chose to use ToString() and concatenation instead of string.Format(). This was the wrong choice. Always use string.format(). This has been preached by many, but just as many don’t listen.

What would have happened if the developer had followed the best practice to use string.Format() or string.Concat?

var contract = string.Concat(CustomerId, ProductGroupId, EndDate.ToString("yy-MM"));

or

var contract = string.Format("{0}{1}{2}", CustomerId, ProductGroupId, EndDate.ToString("yy-MM");

The bug would never had occurred. With either string.Concat() or string.Format(). In those uses, the ToString() methods really would be redundant. With or without them, the code acts the same.

But surely avoiding a Resharper bug isn’t the only reason to use string.Concat or string.Format()? Of course there are more reasons. This error was due to the ambiguous + operator. Using string.Format() or string.Concat() eliminates such ambiguities. Also, with string.Format(), the developer’s intentions are much more clear. The format decided upon is explicitly included. When I type “{0}{1}{2}”, there is no question about what the intended format is. This is why I chose string.Format() for this piece of code. It is self-documenting and unambiguous.

Conclusion

Best practices are best  practices for a reason. Use them. Using string.Format() is always preferable to string concatenation.

P.S. This old project also could have alerted us to this error if anyone would have bothered to write a Unit Test. But this code was buried deep in a method that itself was hundreds of lines long. Following the 100/10 rule and testing would have alerted us when Resharper introduced this error.

Removing the namespace from the ConnectionString name in the web.config

So we are working on moving a legacy web site to MVC4.  Yes, it is my first time doing this.  I encountered an annoying issue that I thought worth blogging about.

Ok, so I have a DLL that is pretty much nothing more than a TableAdapter. (Yes, I wish this legacy project was using Entity Framework, but alas, it is not). I have a config file and the connectionstring name has a the mode horrible namespace.

  <connectionStrings>
    <add name="Company.Division.Feature.DataAccessLayer.MyConnectionString" connectionString="Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUser;Password=MyPasswd" providerName="System.Data.SqlClient" />
    <add name="MyConnectionString" connectionString="Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUser;Password=MyPasswd" providerName="System.Data.SqlClient" />
  </connectionStrings>

Seriously: Company.Division.Feature.DataAccessLayer.MyConnectionString.

Yes, the same connection string is listed twice, once with the namespace and once without.

Why? Well, because all throughout the code, the original authors make call this:

ConfigurationManager.ConnectionStrings["WavelinkLMConnectionString"].ConnectionString

I would like to get rid of one of these configuration settings. Obviously to me, it makes sense to get rid of the long one.

So why doesn’t my TableAdapter library project use the shorter table adapter. Well, I figured that out. Because it is in the Settings file and the Settings file looks for the value using the namespace.

Look at this Settings.Designer.cs file

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.18051
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Company.Division.Feature.DataAccessLayer.Properties {
    
    
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
        
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
        
        public static Settings Default {
            get {
                return defaultInstance;
            }
        }
        
        [global::System.Configuration.ApplicationScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
        [global::System.Configuration.DefaultSettingValueAttribute("Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUser;Password=MyPasswd")]
        public string MyConnectionString{
            get {
                return ((string)(this["MyConnectionString"]));
            }
        }
    }
}

OK, so every single TableAdapter requires this value, so I can’t remove it. I could change it but then everytime the settings regenerated this file, I would have to recreate teh change. Not a good idea.

Hooray for partial classes! To fix this, I removed this setting and put it in a separate partial class. In fact, I learned that in the Settings UI, you can click View Code and it will create this file for you. But for me it created in the project root and not under the Properties solution folder, so I had to move it under Properties myself.

using System.Configuration;
using System.Diagnostics;

namespace Company.Division.Feature.DataAccessLayer.Properties
{
    internal sealed partial class Settings
    {
        [ApplicationScopedSetting]
        [DebuggerNonUserCode]
        [SpecialSetting(SpecialSetting.ConnectionString)]
        [global::System.Configuration.DefaultSettingValueAttribute("Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUser;Password=MyPasswd")]
        public string MyConnectionString
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString))
                    this["MyConnectionString"] = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
                return (string)this["MyConnectionString"];
            }
        }
    }
}

As you can see, I just check if the value is set in the config file without the namespace. If it is, I set the setting to that value.

And that is it! I now can make my config have a single connection string and I don’t have to include the namespace!

  <connectionStrings>
    <add name="MyConnectionString" connectionString="Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUser;Password=MyPasswd" providerName="System.Data.SqlClient" />
  </connectionStrings>

How a software developer can learn communication?

Here is how a software developer can learn to communicate with their coworkers and avoid being extrovert.

How a software engineer can learn to improve communication

Above is an image so you can pin it.

Below is code so you can copy it.

namespace Communication
{
    public class Improve
    {
        public void ImproveCommunication(bool INeedToTalkToAPersonAboutWork, bool IKnowAboutThisPersonOrTheirFamily)
        {
            if (INeedToTalkToAPersonAboutWork)
            {
                Knowledge newKnowledgeAboutPerson;
                if (IKnowAboutThisPersonOrTheirFamily)
                {
                    DoCommentOnSomethingIAlreadyKnowAboutThisPersonOrTheirFamily();
                    newKnowledgeAboutPerson = Listen();
                }
                else
                {
                    AskFindOutQuestion();
                    newKnowledgeAboutPerson = Listen();
                }

                StoreInMemoryDatabase(newKnowledgeAboutPerson);

            }
            TalkToPersonAboutWork();
        }

        public void DoCommentOnSomethingIAlreadyKnowAboutThisPersonOrTheirFamily()
        {
        }

        public void AskFindOutQuestion()
        {
        }

        public Knowledge Listen()
        {
            return new Knowledge();
        }

        public void StoreInMemoryDatabase(Knowledge newKnowledge)
        {
        }

        public void TalkToPersonAboutWork()
        {
        }
    }

    public class Knowledge
    {
    }
}

Log4Net Example

One of my pet peeves of third party libraries is that they are often not intuitive. I have always held off on using Log4Net because it was not intuitive to use. Well, it is just such a well-known and often-used library that it is impossible to be a C# developer without being familiar with this library.

You don’t always get what you want from a 3rd party library. I want a simple way to put a single line in code and be done. For example, a line of code that says: “Give me a log in the same directory as my exe file and name it the same as my .exe file with the .log extension appended. ILog log = Log4Net.SimpleFileLogger(Assembly.GetExecutingAssembly().Location + “.log”);

Step 1 – Create a new project

  1. Create a new Console Application project in Visual Studio. I named mine Log4Net.Example.
  2. Right-click on the Solution and choose Manage NuGET Packages for Solution.
  3. Click Online and search for Log4Net.
  4. Click Install and install the project for your poject.
  5. Close NuGET Package Manager.

Step 2 – Logging to the console window

  1. Add references to log4Net and log4Net.Config.
    (Note: I don’t know why they have the first character in log4Net namespace lowercase. That goes against most C# coding guidelines. Perhaps this is because it is a port of a java logger?)
  2. Add a member variable or property for your log.
  3. Add a line of log.
// Step 1 - Add references to log4Net and Log
using log4net;
using log4net.Config;

namespace Log4Net.Example
{
    class Program
    {
        // Step 1 - Create a variable to hold your log
        static ILog Log = LogManager.GetLogger("MyApp.log");

        static void Main(string[] args)
        {
            // Step 2 - Run this method. Why? Because the documentation says so. I know, this is NOT INTUITIVE.
            BasicConfigurator.Configure();

            // Step 3 - Log to the console
            Log.Debug("Hello, log!");
        }
    }
}

Step 3 – Log to a file

  1. Add references to log4Net assemblies and other needed assemblies.
  2. Create a variable to hold your log.
  3. Create and configure a FileAppender object.
  4. Configure log4Net to use the FileAppender.
  5. Add a line to log to the file.
// Step 1 - Add references to log4Net assemblies and other needed assemblies
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Layout;
using System.Reflection;
using System.Text;

namespace Log4Net.Example
{
    class Program
    {
        // Step 2 - Create a variable to hold your log
        static ILog Log = LogManager.GetLogger(Assembly.GetExecutingAssembly().Location + ".log");

        private static void Main()
        {
            // Step 3 - Create and configure a FileAppender object
            var appender = new FileAppender()
            {
                Layout = new SimpleLayout(),
                File = Assembly.GetExecutingAssembly().Location + ".log",
                Encoding = Encoding.UTF8,
                AppendToFile = true,
                LockingModel = new FileAppender.MinimalLock()
            };
            appender.ActivateOptions();

            // Step 4 - Configure log4Net to use the FileAppender
            BasicConfigurator.Configure(appender);

            // Step 5 - Log to the file
            Log.Debug("Hello, log!");
        }
    }
}

Step 4 – Improving the log file

So the easiest way to improve the log is to add date and timestamps to each entry and the log level. This can be done by switching from a SimpleLayout to a PatternLayout as shown:

// Step 1 - Add references to log4Net assemblies and other needed assemblies
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Layout;
using System.Reflection;
using System.Text;

namespace Log4Net.Example
{
    class Program
    {
        // Step 2 - Create a variable to hold your log
        static ILog Log = LogManager.GetLogger(Assembly.GetExecutingAssembly().Location + ".log");

        private static void Main()
        {
            // Step 3 - Create and configure a FileAppender object
            var appender = new FileAppender()
            {
                Layout = new PatternLayout("%date (%p) %message%newline"),
                File = Assembly.GetExecutingAssembly().Location + ".log",
                Encoding = Encoding.UTF8,
                AppendToFile = true,
                LockingModel = new FileAppender.MinimalLock()
            };
            appender.ActivateOptions();

            // Step 4 - Configure log4Net to use the FileAppender
            BasicConfigurator.Configure(appender);

            // Step 5 - Log to the file
            Log.Debug("Hello, log!");
        }
    }
}

How to write your first C# Unit Test with Visual Studio?

Visual Studio makes Unit Testing easy by bundling a Unit Test framework into it.

Imagine you have a string extension method as shown below and you wanted to unit test it.

using System;

namespace ConsoleApplication1
{
    public static class StringExtensions
    {
        public static bool IsPrimaryColor(this string inString)
        {
            string[] primaryColors = { "Red", "Yellow", "Blue" };
            foreach (var color in primaryColors)
            {
                if (inString.Equals(color, StringComparison.CurrentCultureIgnoreCase))
                    return true;
            }
            return false;
        }
    }
}

Creating a Unit Test project to test this method is very easy.

Step 1 – Create a C# Unit Test Project

  1. In Visual Studio (assuming you already have a project open), click on the Solution and choose Add new project.
  2. Select Templates | Visual C# | Test from the menu on the left.
  3. Select Unit Test Project.
  4. Enter a name for the project.
    Note: Use a good name convention, such as naming the test project the same as the project it tests but with “Tests” at the end.  For example if you have a project called MyProject you would name your test project MyProjectTests. No, it isn’t rocket science. We like to keep it simple.
  5. Click OK.

Step 2 – Give your Unit Test project a reference to the project to test

  1. Right-click on References under the newly created Unit Test project and choose Add reference.
  2. Select Solution from the right.
  3. Add the project you plan to test as a reference.

Step 3 – Create your C# test class and first test method

  1. A test class was already created by default called UnitTest1.cs. Feel free to rename it to an appropriate name.
    Note: Use a good name convention, such as naming the test class the same as the class it tests but with “Tests” at the end.  For example if you have an object called MyObject you would name your test project MyObjectTests.
  2. Add a using statement to reference the namespace of the class you plan to test.
  3. Rename the first Test method. You can’t miss it. It has the [TestMethod] attribute.
    Note: Use a good name convention, such as naming the test method so clearly that you know what it is testing just by the name. For example, StringExtensionIsBlueAPrimaryColorTest().
  4. Add code to make your first test. It is recommended you create your method using the Arrange, Act, Assert pattern.
  5. Add additional test methods as needed.
    using ConsoleApplication1;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace StringExtensionTests
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void StringExtensionIsBlueAPrimaryColorTest()
            {
                // Arrange
                string color = "Blue";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsRedAPrimaryColorTest()
            {
                // Arrange
                string color = "Red";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsYellowAPrimaryColorTest()
            {
                // Arrange
                string color = "Yellow";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsBlackAPrimaryColorTest()
            {
                // Arrange
                string color = "Black";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = false;
                Assert.AreEqual(expected, actual);
            }
        }
    }
    

You have now created your first Unit Test. Go ahead and run it. You should be able to run it in Visual Studio starting with VS 2012. If you have an earlier version, you can run tests using other tools.

Thorough Unit Testing

OK. Now let’s think about what tests would be valid that we don’t have? Here are a few:

  • Case insensitive. All the following strings should return true: Red, red, rEd.
  • What if the string is blank? Null? Junk characters?

Now you write additional unit tests to test this method.

Note: It is too bad that Visual Studio’s MSTest doesn’t support Row tests. NUnit does support Row tests. With Row tests, the above Unit Test code would involve a single method that passing in multiple string values.

How to query a SQL database in C# using TableAdapters

Visual Studio has some great features to help you access the database and create objects for your database. You could manually create a connection string and manually create objects that represent the data in your database described here: How to query a SQL database in C#?. This article can show you how Visual Studio can do this for you.

So how is it done? By adding a Data Source.

Imagine you have a simple database for authentication with these tables:

User
- Id INT AUTOINCREMENT
- UserName VARCHAR(100)
- Password VARCHAR(MAX)
- Salt VARCHAR(MAX)

Person
- Id INT AUTOINCREMENT
- FirstName VARCHAR(255)
- LastName VARCHAR(255)
- Birthdate DATETIME
- UserId int FK to User.Id

Now imagine that you want to query these tables and use the data in your application.

Step 1 – Create a Visual Studio Project

  1. In visual studio create a new C# Console Application project.
  2. Once you have the project created, click on Project | Add New Data Source.
  3. Select Database and click Next.
  4. Select DataSet and click Next.
  5. Click New Connection and follow the wizard to connect to your database.
  6. Make sure that Yes, save the connection as is checked and give your saved connection a name and click Next.
  7. Click the checkbox next to Tables and click Finish.

This adds the following files to your project (the names might be slightly different on yours):

  • AuthDataSet.xsd
  • AuthDataSet.Designer.cs
  • AuthDataSet.xsc
  • AuthDataSet.xss

This code will add table adapters to your project. This basically does a lot of work for you and can save you a lot of potential development time.

Step 2 – Query a SQL Database using the Table Adapter

Now you can get the data from either of your tables with one line of code:

using System;
using System.Data;
using TableAdapterExample.AuthDataSetTableAdapters;

namespace TableAdapterExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Query the database (select * from Person) into a DataTable
            AuthDataSet.PersonDataTable table = new PersonTableAdapter().GetData();

            // Print out the table as proof.
            PrintDataTable(table);
        }

        /// How to print a DataTable
        private static void PrintDataTable(AuthDataSet.PersonDataTable table)
        {
            foreach (DataRow row in table.Rows)
            {
                foreach (DataColumn col in table.Columns)
                {
                    Console.Write(row[col].ToString().Trim() + " ");
                }
                Console.WriteLine();
            }
        }
    }
}

Hope that helps you.

ASP.NET, JavaScript, and HTML Element ID attributes

Today I had to fix some legacy code. It is ASP.NET code and it has both ASP.NET elements and ASP.NET Controls. The plan was to replace a large portion of code behind with JavaScript. The ASP.NET code needed to be a UserControl that could appear twice on the same page. This created some problems:

  1. ASP.NET creates some html controls but changes the id and the name attributes. While it is possible to run the web page and see what the attributes will be changed to and then use those strings statically in JavaScript, the JavaScript could easily break with slight changes to the ASP.NET code. This is not scalable or maintainable.
  2. ASP.NET does NOT rename the the id or the name attributes for normal HTML tags. First, that is a consistency issue. Second it is an issue using the same control multiple times. Third, if you want to get the value of a form element, doing so uses the name attribute and so each form element needs a separate name.

So lets explain the is problem with a real world scenario.

Lets say you have the following requirements:

  1. Create a UserControl, called PersonControl, that accepts person’s basic info: First name, Last name, and Birthdate.
  2. The form also has a button and it should only be enabled if all three fields are populated.
  3. The Birthdate should use JQuery’s DateTimePicker.
  4. The First name and Last name should be ASP.NET text boxes.

Now imagine the site already exists and you have to add this requirement:

  1. A web page should exist that has multiple PersonControls showing: for example: Employee, Emergency Contact.

The problem with ASP.NET, JavaScript, and HTML Element ID attributes

So let’s build this project using a single control and static id and name attributes and see how it works. Later we will see what we need to do to get this working with multiple PersonControls.

  1. Open Visual Studio and create a new ASP.NET Empty Web Application.
  2. Add JQuery and JQuery-UI. Do this as follows:
    1. Right-click on the project and choose Manage NuGet Packages.
    2. In the Manage NuGet Packages window, on the left, click Online.
    3. On the right, in the search field, type JQuery.
    4. Install JQuery and JQuery UI.
  3. Create new Web Form called PersonForm.
  4. Add the following into your PersonForm.aspx file:
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PersonForm.aspx.cs" Inherits="AspAndJavaScriptExample.PersonForm" %>
    
    <%@ Register Src="~/PersonControl.ascx" TagPrefix="uc1" TagName="PersonControl" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>ASP.NET, JavaScript, and HTML id Attributes</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <h2>Employee</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
            </div>
            <%--<div>
                <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
            </div>--%>
        </form>
    </body>
    </html>
    
  5. Create a new Web User Control called PersonControl.
  6. Add the following into your PersonControl.ascx file:
    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PersonControl.ascx.cs" Inherits="AspAndJavaScriptExample.PersonControl" %>
    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PersonControl.ascx.cs" Inherits="AspAndJavaScriptExample.PersonControl" %>
    <link href="Content/themes/base/minified/jquery.ui.datepicker.min.css" rel="stylesheet" />
    <script src="scripts/jquery-2.0.0.min.js"></script>
    <script src="scripts/jquery-ui-1.10.3.min.js"></script>
    <script src="scripts/ButtonManager.js"></script>
    <script>
        $(function () {
            $(".datepicker").datepicker();
        });
    </script>
    
    <div style="border: solid; padding: 2px">
        First name:
        <asp:TextBox ID="FirstName" runat="server"></asp:TextBox><br />
        Last name:
        <asp:TextBox ID="LastName" runat="server"></asp:TextBox><br />
        Birthdate:
        <input type="text" name="BirthDate" id="BirthDate" class="datepicker" /><br />
        <asp:Button ID="SubmitPerson" runat="server" Text="Submit" OnClick="SubmitPerson_Click" />
    </div>
    
  7. Add the following button SubmitPerson_Click method into your PersonControl.ascx file:
            protected void SubmitPerson_Click(object sender, EventArgs e)
            {   // Put break point here            
                var firstName = FirstName.Text;
                var laststName = LastName.Text;
                var birthdate = Request.Form["Birthdate"];
            }
    
  8. Now add this ButtonManager.js file.
    jQuery(document).ready(function () { 
        $("#PersonControlEmployee_FirstName").bind("propertychange keyup input paste", setButtonState);
        $("#PersonControlEmployee_LastName").bind("propertychange keyup input paste", setButtonState);
        $("#BirthDate").change(setButtonState);
        setButtonState();
    });
    
    var setButtonState = function () {
        if (!areValuesPopulated())
            $("#PersonControlEmployee_SubmitPerson").attr("disabled", "disabled");
        else
            $("#PersonControlEmployee_SubmitPerson").removeAttr("disabled");
    }
    
    var areValuesPopulated = function () {
        return $("#PersonControlEmployee_FirstName").val() != ""
             && $("#PersonControlEmployee_LastName").val() != ""
             && $("#BirthDate").datepicker().val() != "";
    }
    
  9. Now run the project and look at the source code of the html. It looks as follows:
    
    
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head><title>
    	ASP.NET, JavaScript, and HTML id Attributes
    </title></head>
    <body>
        <form method="post" action="PersonForm.aspx" id="form1">
    <div class="aspNetHidden">
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="nkizDAjcAtd96A9EOpli0xdG3n6zTXVaM/5t2fmcAI5+LPQ6OzzIV2wUpisxoUTMFxIKkUwKDY4Xk36/NouRsiE81gq5z3Ch/tz3DlxJW9g=" />
    </div>
    
    <div class="aspNetHidden">
    
    	<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="XCB0fxwKvdqEXpUBaICUtf6EzkAvBeahq0bywZekyukCuzvGVagqOnVHUWFHF2Cycd2xkg/UhNh/B3qNqabkBI+Flj52GkM3p6SF5eL/M4SnnfwmFBjWVOaTZ+IlwMvkR1bGuMxomyeJJ5HaU1FXWSYDYHVtgM9tdsVi31EireM=" />
    </div>
            <div>
                <h2>Employee</h2>
                
    <link href="Content/themes/base/minified/jquery.ui.datepicker.min.css" rel="stylesheet" />
    <script src="scripts/jquery-2.0.0.min.js"></script>
    <script src="scripts/jquery-ui-1.10.3.min.js"></script>
    <script src="scripts/ButtonManager.js"></script>
    <script>
        $(function () {
            $(".datepicker").datepicker();
        });
    </script>
    
    <div style="border: solid; padding: 2px">
        First name:
        <input name="PersonControlEmployee$FirstName" type="text" id="PersonControlEmployee_FirstName" /><br />
        Last name:
        <input name="PersonControlEmployee$LastName" type="text" id="PersonControlEmployee_LastName" /><br />
        Birthdate:
        <input type="text" name="BirthDate" id="BirthDate" class="datepicker" /><br />
        <input type="submit" name="PersonControlEmployee$SubmitPerson" value="Submit" id="PersonControlEmployee_SubmitPerson" />
    </div>
    
            </div>
            
        </form>
    </body>
    </html>
    

Problems

  1. Notice the id and name attributes on the tags. The ASP.NET controls have been altered by ASP.NET with a prefix. This is not the problem. This is good. If the control is used multiple times, then this keeps the id and name attributes unique and they are supposed to be unique. However, the problem is, if the id is changed in this line . . .
    <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
    

    . . . then id and name attributes in the child control will change. Since we are using those values statically in the ManageButton.js, any such change also breaks in the javascript. Also, we aren’t using a master page, but if you decided to add a master page, that add an additional prefix, which would create different id and name attributes, again causing the javascript to break. In fact, any such nesting change will change the id and name attributes breaking the javascript.

  2. The control that is not an ASP.NET control, the JQuery datepicker control, did not have the same modifications made to the Birthdate. So this tag won’t work if the control is used multiple times.

Do you want to see the problem?

Update your form in PersonForm.aspx to include multiple controls.

    <form id="form1" runat="server">
        <div>
            <h2>Employee</h2>
            <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
        </div>
        <div>
            <h2>Emergency Contact</h2>
            <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
        </div>
    </form>

Now give it try. See the problems? Ok. So now you have a simulation of the problematic code that I faced today.

Solution to ASP.NET, JavaScript, and HTML Element ID attributes

So we are going to fix this in parts. We are going to use a variable in the ASP.NET control called ClientID, that is basically the prefix used.

  1. Fix html elements to use the same prefix as the ASP.NET controls
  2. Fix the javascript to receive the ClientID as a parameter
  3. Fix the datepicker attributes

    First, let’s fix the ASP.NET and HTML so that all the id and name attributes are consistently changed.

    Change the datepicker line and add some code so it will have the same prefix as ASP.NET created html controls.

    <input type="text" name="<%=ClientID%>$BirthDate" id="<%=ClientID%>_BirthDate" class="datepicker" /><br />
    

    Pass the prefix into the JavaScript

    1. In the PersonControl.ascx file, add a little snippet of JavaScript code to pass the ClientID into the JavaScript files.
      <script>
          $(function () {
              $(".datepicker").datepicker();
          });
          jQuery(document).ready(function () {
              startManagingButton("<%=ClientID%>");
          });
      </script>
      
    2. Now update your JavaScript file to use that ClientID as the prefix. Notice, this is used in the events. I created a simple buildId method that I use throughout now.
      var startManagingButton = function (inIdPrefix) {
          $(buildId(inIdPrefix, "_FirstName")).bind("propertychange keyup input paste", inIdPrefix, setButtonState);
          $(buildId(inIdPrefix, "_LastName")).bind("propertychange keyup input paste", inIdPrefix, setButtonState);
          $(buildId(inIdPrefix, "_BirthDate")).change(inIdPrefix, setButtonState);
          setButtonState(inIdPrefix);
      }
      
      var setButtonState = function (inIdPrefix) {
          if (inIdPrefix.data)
              inIdPrefix = inIdPrefix.data;
          
          if ($(buildId(inIdPrefix, "_FirstName")).val() == "" || $(buildId(inIdPrefix, "_LastName")).val() == "" || $(buildId(inIdPrefix, "_BirthDate")).val() == "")
              $(buildId(inIdPrefix, "_SubmitPerson")).attr("disabled", "disabled");
          else
              $(buildId(inIdPrefix, "_SubmitPerson")).removeAttr("disabled");
      };
      
      var buildId = function (inIdPrefix, idSuffix) {
          return "#" + inIdPrefix + idSuffix;
      };
      

      Now no matter how you update or move this web page, the Id values always work.

    Use the ClientID in ASP.NET SubmitPerson_Click method

    Update the code to look as follows:

        protected void SubmitPerson_Click(object sender, EventArgs e)
        {   // Put break point here            
            var firstName = FirstName.Text;
            var laststName = LastName.Text;
            var birthdate = Request.Form[ClientID + "$Birthdate"];
        }
    

    Using the PersonControl multiple times

    Now everything should be working and you should be able to include as many instances of your control in your web page as you want.

    Update your form in PersonForm.aspx to include many of these controls.

        <form id="form1" runat="server">
            <div>
                <h2>Employee</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
            </div>
            <div>
                <h2>Spouse</h2>
                <uc1:PersonControl runat="server" ID="PersonControlSpouse" />
            </div>
            <div>
                <h2>Emergency Contact</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
            </div>
        </form>
    

    Now give it try. All instances of the PersonControl are now working. The dynamic id and name attributes are not a problem as we are handling them; in fact, they are part of the ultimate solution to make the control reusable.

    Conclusion

    ASP.NET, JavaScript, and HTML Element ID attributes can all be used to work together to make a nice cohesive application.

    If you have a better solution, please post a comment and let me know.

    Downloads

    Here is the project in both states:

    AspAndJavaScriptExample-problematic.zip

    AspAndJavaScriptExample-working.zip

    Bugs

    Now the only bug I can find is on clicking submit the JQuery datepicker field is cleared. I’ll try to fix that and post the solution in another post.

How to create an excel spreadsheet with C#?

I needed to create an Excel spread sheet in C# and I didn’t want to reinvent the wheel.

I found this awesome project: https://closedxml.codeplex.com

I already had a DataTable that I wanted to export in ASP.NET to an Excel file and download. I created an extension method for the DataTable.

    public static class CloseXMLHelper
    {
        public static XLWorkbook ToExcel(this DataTable inDataTable)
        {
            var wb = new XLWorkbook();
            var dataTable = inDataTable;

            // Add a DataTable as a worksheet
            wb.Worksheets.Add(dataTable);
            return wb;
        }
    }

Then I just followed the documentation on the project for allowing a user to download the excel file. I already had the myDataTable variable in the below snippet. If you are wondering how to create a DataTable from a database, see this post: How to query a SQL database in C#?

    var httpResponse = Response;
    httpResponse.Clear();
    httpResponse.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    httpResponse.AddHeader("content-disposition", "attachment;filename=\"HelloWorld.xlsx\"");

    // Flush the workbook to the Response.OutputStream
    using (var memoryStream = new MemoryStream())
    {
        dataset.Tables[0].ToExcel().SaveAs(memoryStream);
        memoryStream.WriteTo(httpResponse.OutputStream);
        memoryStream.Close();
    }

    httpResponse.End();

It doesn’t get much more simple than this.