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

See descriptive Enitity Validation Errors in exception message

By default, Entity Validation Errors are not described in the DbEntityValidationException that is thrown.

If you want those displayed, here is how:

Locate your DbContext object in your project. Overload the SaveChanges() message as follows:

        public override int SaveChanges()
        {            
            try
            {
                return base.SaveChanges();
            }
            catch (DbEntityValidationException eve)
            {
                var errorMsg = new StringBuilder(eve.Message + Environment.NewLine);
                foreach (var validationResult in eve.EntityValidationErrors)
                {
                    foreach (var error in validationResult.ValidationErrors)
                    {
                        errorMsg.Append(validationResult.Entry.Entity + ": ");
                        errorMsg.Append(error.ErrorMessage + Environment.NewLine);
                    }
                }
                // Use the same exception type to avoid downstream bugs with code that catches this
                throw new DbEntityValidationException(errorMsg.ToString(), eve.EntityValidationErrors, eve);
            }
        }

I can see how the decision to not include them by default is good. Doing so could be an information disclosure security issue. However, if wrapped in a WCF service where the the entities are used as the DataContract or POCO objects, then there really isn’t much information additional information provided than what is in the wsdl.

An MVC DropDownListFor that supports all attributes

So I need a DropDownListFor that allows me to create any attribute for the select or option tags. Obviously the attributes for each option tag should come from a property in an object that is provided in a collection. I also eliminate the need of converting a collection of your custom object to a collection of SelectListItem.

Remember a DropDownList in HTML looks like this:

<select>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>

The current DropDownListFor uses list of SelectListItem objects to create the option tags. However, SelectListItem only supports the value attribute and the inner text (the text between the open option tag and the close option tag). Support for any attribute should be provided.

First, I create a model to hold the attribute data. It is a very small class with only five properties, but looks like a big class due to the extensive comments.

using System.Collections.Generic;

namespace LANDesk.Licensing.Wavelink.Models
{
    public class HtmlSelectListModel<T>
    {
        /// <summary>
        /// That collection of data elements from which to create a the select options.
        /// </summary>
        public IEnumerable<T> DataObjects { get; set; }

        /// <summary>
        /// Often there is an option on top called "--Select item--" that has an empty value.
        /// </summary>
        public string EmptyValueText { get; set; }

        /// <summary>
        /// A bool value that for whether EmptyValueText is used or not
        /// </summary>
        public bool ShouldUseEmptyValue
        {
            get { return !string.IsNullOrWhiteSpace(EmptyValueText); }
        }

        /// <summary>
        /// This will add attributes to the <select></select> html tag.
        /// The key is the attribute, the value is the value.
        /// For example:
        ///     SelectAttributes.add("id", "select-id-1");
        /// Would result in this html:
        ///     <select id="select-id-1"></select>
        /// </summary>
        public Dictionary<string, string> SelectAttributes
        {
            get { return _SelectAttributes ?? (_SelectAttributes = new Dictionary<string, string>()); }
            set { _SelectAttributes = value; }
        } private Dictionary<string, string> _SelectAttributes;

        /// <summary>
        /// This will add attributes to the <option></option> html tag in a select list.
        /// The key is the attribute, the value is the property on the object that contains the value.
        /// A list of objects will be used to create the options. Using reflection, the property with a
        /// name matching the value will be found. If the value is "Country" then a property name Country
        /// will be found using reflection. 
        /// 
        /// Note: If inner-text is used it will not be an attribute but will be the text between the
        ///       opening and closing tags.
        /// 
        /// For example:
        ///     OptionAttributes.add("value", "CountryTwoLetter");
        ///     OptionAttributes.add("innter-text", "Country");
        /// If the the list had to objects and the Country values were "United States" and "Canada",
        /// and the CountryTwoLetter values were "US" and "CA", then the result would be this html:
        ///     <option value="US">United States</option>
        ///     <option value="US">United States</option>
        /// 
        /// Html data-[name] attributes are supported here as well.
        /// </summary>
        public Dictionary<string, string> OptionAttributes
        {
            get { return _OptionAttributes ?? (_OptionAttributes = new Dictionary<string, string>()); }
            set { _OptionAttributes = value; }
        } private Dictionary<string, string> _OptionAttributes;
    }
}

Next add an extension method to HtmlHelper.

using LANDesk.Licensing.Wavelink.Models;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace System.Web.Mvc
{
    public static class DrownDownListHelper
    {
        /// <summary>
        /// Adds increased attributed functionality to DropDownListFor.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <typeparam name="T">The type of object in a list.</typeparam>
        /// <param name="htmlHelper">The object this method attaches to.</param>
        /// <param name="expression">The object the selected value binds to.</param>
        /// <param name="listModel">The Model object for creating this list.</param>
        /// <returns>MvcHtmlString - Html for Razor pages.</returns>
        public static MvcHtmlString DropDownListWithAttributesFor<TModel, TProperty, T>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, HtmlSelectListModel<T> listModel)
        {
            var dropdown = new TagBuilder("select");
            foreach (var selectAttribute in listModel.SelectAttributes)
            {
                dropdown.Attributes.Add(selectAttribute.Key, selectAttribute.Value);
            }
            string currentValue = null;
            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            if (metadata != null && metadata.Model != null)
                currentValue = metadata.Model.ToString();

            var optionsBuilder = new StringBuilder();
            foreach (T item in listModel.DataObjects)
            {
                BuildOptionTags(listModel, optionsBuilder, item, currentValue);
            }
            if (string.IsNullOrWhiteSpace(currentValue) && listModel.ShouldUseEmptyValue)
            {
                optionsBuilder.Insert(0, "<option value=\"\">" + listModel.EmptyValueText + "</option>");
            }
            dropdown.InnerHtml = optionsBuilder.ToString();

            return new MvcHtmlString(dropdown.ToString(TagRenderMode.Normal));
        }

        internal static void BuildOptionTags<T>(HtmlSelectListModel<T> listModel, StringBuilder optionsBuilder, T item, string selectedValue)
        {
            var optionAttributes = GetOptionAttributes(listModel, item);
            string innerText = GetOptionInnerText(optionAttributes);

            if (optionsBuilder == null) { optionsBuilder = new StringBuilder(); }
            optionsBuilder.Append("<option ");
            bool defaultValueFound = false;
            foreach (var attribute in optionAttributes)
            {
                optionsBuilder.Append(string.Format("{0}=\"{1}\" ", attribute.Key, attribute.Value));
                if (attribute.Value == selectedValue)
                {
                    optionsBuilder.Append("selected=\"selected\" ");
                    defaultValueFound = true;
                }
            }
            optionsBuilder.Append(">" + innerText + "</option>");
        }

        internal static string GetOptionInnerText(IDictionary<string, string> optionAttributes)
        {
            string innerText;
            if (optionAttributes.TryGetValue("inner-text", out innerText))
            {
                optionAttributes.Remove("inner-text");
            }
            return innerText;
        }

        internal static Dictionary<string, string> GetOptionAttributes<T>(HtmlSelectListModel<T> listModel, T item)
        {
            var properties = item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => listModel.OptionAttributes.Values.Contains(p.Name));
            var optionAttributes = new Dictionary<string, string>();
            foreach (var p in properties)
            {
                var p1 = p;
                foreach (var oa in listModel.OptionAttributes.Where(oa => p1.Name == oa.Value))
                {
                    optionAttributes.Add(oa.Key, p.GetValue(item, null).ToString());
                }
            }
            return optionAttributes;
        }
    }
}

Now you can use this in an MVC razor cshtml page. You will need a using statement like this:
@using MyNamespace.Models

    <div class="form-group">
        @Html.LabelFor(model => model.Customer.State, new { @class = "control-label col-md-2", required = "required" })
        <div class="col-md-10">
            @Html.DropDownListFor2(model => model.Customer.State, 
                new HtmlSelectListModel<State>
                {
                    DataObjects = CountryManager.Instance.States,
                    EmptyValueText = "- Select a State -",
                    SelectAttributes = new Dictionary<string, string> { { "Id", "Customer_State" }, { "Name", "Customer.State" } },
                    OptionAttributes = new Dictionary<string, string>
                                        {
                                            { "value", "StateCode" }, { "inner-text", "StateName" }, { "data-country", "CountryCode" } 
                                        }
                }
            )
            @Html.ValidationMessageFor(model => model.Customer.State)
        </div>
    </div>

It will make some awesome html. It allows even for adding data-[name] attributes. I needed a data-country attribute, which is why I wrote this class.

<select id="Customer_State" name="Customer.State">
    <option value="" >- Select a State -</option>
    <option value="AB" data-country="CA">Alberta</option>
    <option value="AK" data-country="US">Alaska</option>
    <option value="AL" data-country="US">Alabama</option>
    <option value="AR" data-country="US">Arkansas</option>
    <option value="AZ" data-country="US">Arizona</option>
    <option value="BC" data-country="CA">British Columbia</option>
    <option value="CA" data-country="US">California</option>
    <option value="CO" data-country="US">Colorado</option>
    <option value="CT" data-country="US">Connecticut</option>
    <option value="DC" data-country="US">District of Columbia</option>
    <option value="DE" data-country="US">Delaware</option>
    <option value="FL" data-country="US">Florida</option>
    ...
</select>

If you have any feedback, I would love to hear it. Please comment.

Authenticating to Salesforce with Silenium in C#

It is pretty easy to authenticate to Salesforce with Silenium in C#. Here are the steps.

  1. Add the following NuGET package to your project:
    Silenium WebDriver
  2. Use the following code:
        public static void LoginToSalesforce(string username, string password)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Url = "https://test.salesforce.com";
            driver.Navigate();
            var userNameTextBox = driver.FindElement(By.Id("username"));
            userNameTextBox.SendKeys(username);
            var passwordTextBox = driver.FindElement(By.Id("password"));
            passwordTextBox.SendKeys(password);
            var loginButton = driver.FindElement(By.Id("Login"));
            loginButton.Submit();
        }

Yes it is that easy.

EntityUpdater Generic helper for Entity Framework

So I am using Entity Framework (EF) more and more and I really like it. However, I’ve come across a problem when using WCF services and EF that doesn’t look to be perfectly solved.

Let me give you my use case.

I have many entities but in this case, let’s use Customer and CustomerSite. I am using that Entity as a POCO object for a WCF service as well. I have two Systems. SAP and a custom C# licensing system, which is where I am using WCF and EF.

Customer
– CustomerId
– CustomerName

Customer Site
– CustomerSiteId
– CustomerId
– SiteName
– Address1
– Address2
– State
– Country
– Zip
– Website
– SapCustomerId

Let’s say that someone changes the Address for a customer in SAP. A post is made with the new Address. I tried a couple of built in Entity Framework methods, but I’ve been unable to figure out how the front end client can update a single property without first querying over WCF for the existing values and having the client side update the changed values. To me, this seems to be a broken process. The client has to query the current object, which results in a call that has to traverse over the wire to the WCF service, then to the database through EF, then back to WCF and back over the wire to the client. Then logic has to exist on the client to update the appropriate fields. The client now needs a lot of logic it otherwise shouldn’t need.

If the client wants to update only one field, Address1, the client should be able to send an update request that contains only CustomerSiteId and Address1 with everything else should be left blank.

However, the logic to do this work on the server side seems difficult if not impossible without some data from the client. WCF gets in the way. The object is created by the WCF service and every field exists in the object and none of the fields are marked as “updated” or not. If only one field is changed, the other fields are default values in the instantiated object. How can the server know which fields are updated?

Well, if the client is sending a change and the change is not a default value, then we can ignore updates for properties that use default values. However, what if we want to change to a default value? What if, for example, the default value of Address2 is null. What if you want to change the database value back to null?

What if I want to update all the address fields but leave the CustomerId the same?

  1. Write a separate WCF method every time there is a field that might be updated by itself.

    Yeah, this is nightmare. It isn’t really a solution.

  2. Write a method that any WCF service can call that takes in an Entity Type, an Id and a list of property names, and their corresponding values.

    While this would work, it breaks the idea of using the Poco object. The ability to use a simple entity object is nice. Breaking away from the Entity object to a generic object like this seems the wrong thing to do. It would work, though. It would need client code to convert entities to this new object type that has an Id and a property value dictionary. Also, now the code is not clear. Instead of calling UpdateCustomer(customer), I would call UpdateEntity(myObject), which just isn’t as clear or as readable.

  3. Have a single generic method on the server that any WCF service method could call. The method would loop through the entity object and if a property’s value is default or null, that value isn’t updated.

    I like this because the logic is on the server. I can have UpdateCustomer and UpdateCustomerSite and each can call this method easily. The one problem, what if I want to set the value to null? This wouldn’t work.

  4. Have my WCF methods on the WCF server that takes in an IEnumerable of changed property names, then have generic code to loop through the Entity and mark the appropriate properties as “Changed”.

    I like this too, but if I only change one property to an actual value, I would really like to avoid creating the IEnumerable.

  5. Have both methods 3 and 4 above.

    This is what I am going with.

I created this class to help me with this.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Reflection;

namespace LANDesk.Licensing.Wavelink.Database
{
    public class EntityUpdater<T> where T : class
    {
        /// <summary>
        /// Updates the value of all properties with a value other than null or the default value for the class type. 
        /// </summary>
        /// <param name="entity">The entity to update</param>
        /// <param name="entry">A DbEntityEntry<T> entry object to mark which propeties are modified.</param>
        public void Update(T entity, DbEntityEntry<T> entry)
        {
            var props = from propertyInfo in entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(pi => !Attribute.IsDefined(pi, typeof(NotMappedAttribute)))
                        let val = propertyInfo.GetValue(entity, null)
                        where !IsNullOrDefault(val) && !IsCollection(val)
                        select propertyInfo;
            foreach (var pi in props)
            {
                entry.Property(pi.Name).IsModified = true;
            }
        }

        /// <summary>
        /// Updates the value of any property in the updatedPropertyNames list. 
        /// </summary>
        /// <param name="entity">The entity to update</param>
        /// <param name="updatedPropertyNames">The list of properties to update.</param>
        /// <param name="entry">A DbEntityEntry<T> entry object to mark which propeties are modified.</param>
        public void Update(T entity, IEnumerable<string> updatedPropertyNames, DbEntityEntry<CustomerSite> entry)
        {
            var propInfoCollection = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var pi in from pi in propInfoCollection
                               from updatedPropertyName in updatedPropertyNames
                               where pi.Name.Equals(updatedPropertyName, StringComparison.CurrentCultureIgnoreCase)
                               select pi)
            {
                entry.Property(pi.Name).IsModified = true;
            }
        }

        /// <summary>
        /// Checks if any object is null or the default value for the class type. 
        /// </summary>
        /// <typeparam name="TT">The object class</typeparam>
        /// <param name="argument">The object to test for null or default.</param>
        /// <returns></returns>
        public static bool IsNullOrDefault<TT>(TT argument)
        {
            // deal with normal scenarios
            if (argument == null) return true;
            if (Equals(argument, default(TT))) return true;

            // deal with non-null nullables
            Type methodType = typeof(TT);
            if (Nullable.GetUnderlyingType(methodType) != null) return false;

            // deal with boxed value types
            Type argumentType = argument.GetType();
            if (argumentType.IsValueType && argumentType != methodType)
            {
                object obj = Activator.CreateInstance(argument.GetType());
                return obj.Equals(argument);
            }

            return false;
        }

        /// <summary>
        /// Check if an object is a collection. This is to use to ignore complex types.
        /// </summary>
        /// <typeparam name="TT">The object class</typeparam>
        /// <param name="obj">The object to test.</param>
        /// <returns></returns>
        public static bool IsCollection<TT>(TT obj)
        {
            return obj.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICollection<>));
        }
    }
}

Now, I can use this class in my separate WCF services as follows.

        /// <summary>
        /// Updates the value of all properties with a value other than null or the default value for the type.
        /// Any property that is not set to a value other than null or default is ignored.
        /// </summary>
        /// <param name="customerSite">The customerSite entity to update</param>
        public int UpdateSiteSimple(CustomerSite customerSite)
        {
            UpdateSite(customerSite, null);
        }

        /// <summary>
        /// Updates the value of any property in the customerSite contained in the updatedPropertyNames list. 
        /// The values of any properties not in the updatedPropertyNames list are ignored.
        /// </summary>
        /// <param name="customerSite">The customerSite entity to update</param>
        /// <param name="updatedPropertyNames">The list of properties to update.</param>
        public int UpdateSite(CustomerSite customerSite, IEnumerable<string> updatedPropertyNames)
        {
            if (customerSite == null) { throw new Exception("The customerSite cannot be null"); }

            using (var db = new MyDbContext())
            {
                db.CustomerSites.Attach(customerSite);
                var entry = db.Entry(customerSite);
                var updater = new EntityUpdater<CustomerSite>();
                if (updatedPropertyNames == null || !updatedPropertyNames.Any())
                    updater.Update(customerSite, entry);
                else
                    updater.Update(customerSite, updatedPropertyNames, entry);
                db.SaveChanges();
            }
            return customerSite.CustomerSiteId;
        }

If you like this code and find it useful please comment.

Currently, it ignores complex types and won’t update them. I could see attempting to update complex properties in the future.

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!");
        }
    }
}