Creating composite controls using Html Designer.

In the current architecture od our application I have to use composite controls to implement significant amount of HTML UI.
It will not be good to load child user controls into parent composite control(but technically probably still possible).

I’ve followed the approach described in David Ebbo’s Turning an ascx user control into a redistributable custom control blog post (and in MSDN article).
However if you want to  modify the control, process of Publish and copy DLL may be annoyed.
I’ve decided to take generated user control as starting point and after this to do modifications manually.In particular  I needed to pass parameters to my  composite control.
I’ve just used Reflector’s  FileDisassembler add-in to get source of composite control and made changes manually.
However if I need to do significant HTML changes, I will haveto do the same User Control to custom control process again.

It seems that K. Scott Allen’s  approach in Using MSBuild and ILMerge to Package User Controls For Reuse post required less work in change/build/debug cycle. Unfortunately the article has XML snippets corrupted.  But the thread  has build file example.  I am going to try it.

When I searched for a solution, I found out of the topic, but useful post LoadControl a UserControl – *and* pass in Constructor Parameters .

Unit Testing in .Net Notes.

Some time ago I posted my Unit Testing ASP.NET Applications  notes. This post is to put togeter a few links that I found useful about general Unit testing frameworks.
MbUnit vs. NUnit Vs. Team System Unit Testing – Choosing a unit test framework

NUnit vs Team System Unit Test

In our solutions we are using both NUnit and VSTS Unit testing. I like VSTS for the ability to generate test stubs code. But our build server has only VS Professional installed, that doesn’t allow to include VSTS projects to release builds(it will be available in VS 2008 Pro).  
I am using TestDriven.NET  and specific  test harnesses to debug new/modified development code.

I want to consider How to run tests in a build without test metadata files and test lists.    

My DateTimeHelper class

Previously I’ve posted a few Helper Classes . This post describes my DateTimeHelper class.

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.VisualBasic.CompilerServices;

using Microsoft.VisualBasic;

using System.Diagnostics;

 

    public static class DateTimeHelper

    {

 

        public static DateTime DateAndTime(DateTime dateValue, DateTime timeValue)

        {

            DateTime time2;

            time2 = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, timeValue.Hour, timeValue.Minute, timeValue.Second);

            return time2;

        }

 

        public static DateTime DateEndOfDay(DateTime dateValue)

        {

            return DateTimeHelper.DateAndTime(dateValue, DateType.FromString(“23:59”));

        }

        public static DateTime DateStartOfDay(DateTime dateValue)

        {

            return DateTimeHelper.DateAndTime(dateValue, DateType.FromString(“00:00”));

        }

        //        ‘Not used

        //        ‘Public Shared Function TimeAsAccessDate(ByVal Value As Date) As Date

        //        ‘    Const DateOrigAccess As Date = #1/1/1900#

        //        ‘    If Value < DateOrigAccess Then

        //        ‘        Value = DateOrigAccess + ” ” + Value

        //        ‘    End If

        //        ‘    Return (Value)

        //        ‘End Function

        public static string FormatDateTimeSQL(DateTime Value)

        {

            return DataHelper.Quoted(Strings.Format(Value, “yyyy-MM-dd HH:mm:ss”));

        }

 

        public static string FormatDateTimeSQL(DateTime dateValue, DateTime timeValue)

        {

            return DataHelper.Quoted(Strings.Format(dateValue, “yyyy-MM-dd “) + Strings.Format(timeValue, “HH:mm:ss”));

        }

        public static string TimeConvertSQL(DateTime Value)

        {

            return (” CONVERT(VARCHAR, “ + DataHelper.Quoted(Strings.Format(Value, “HH:mm:ss”)) + “,108)”);

        }

        public static string DateConvertSQL(DateTime Value)

        {

            //        ‘Using Convert is not good because indexes are not used see http://www.databasejournal.com/features/mssql/print.php/10894_2209321_3.

            return (” CONVERT(DATETIME, “ + DateTimeHelper.DateFormatSQL(Value) + ” , 102) “);

        }

 

        public static string DateFormatSQL(DateTime Value)

        {

            return DataHelper.Quoted(Strings.Format(Value, “yyyy-MM-dd”));

        }

        public static string SQLBetweenDates(string Field, DateTime FromDate, DateTime ToDate)

        {

            string str = “[“ + Field + “] “ + SQLBetweenDates(FromDate, ToDate);

            return str;

        }

        public static string SQLBetweenDates(DateTime FromDate, DateTime ToDate)

        {

            string str = “BETWEEN  “ + DateConvertSQL(FromDate) + ” AND “ + FormatDateTimeSQL(DateEndOfDay(ToDate));

            return str;

        }

 

        public static DateTime YYYYMMDDToDate(long day)

        {

            DateTime time3;

            object obj1 = day.ToString();

            time3 = new DateTime(IntegerType.FromString(Strings.Left(StringType.FromObject(obj1), 4)), IntegerType.FromString(Strings.Mid(StringType.FromObject(obj1), 5, 2)), IntegerType.FromString(Strings.Mid(StringType.FromObject(obj1), 7, 2)));

            return time3;

        }

        public static DateTime HHMMSSToTime(long time)

        {

            DateTime time3;

            object obj1 = time.ToString();

            time3 = new DateTime(0x6d9, 1, 1, IntegerType.FromString(Strings.Left(StringType.FromObject(obj1), 2)), IntegerType.FromString(Strings.Mid(StringType.FromObject(obj1), 3, 2)), IntegerType.FromString(Strings.Mid(StringType.FromObject(obj1), 5, 2)));

            return time3;

        }

 

 

        /// <summary>

        /// DateTime string support relative date format e.g. “-1day 20:00” means yesterday at 20:00

        /// </summary>

        /// <param name=”sDateTime”></param>

        /// <returns></returns>

        public static DateTime ParseRelativeDateTime(string sDateTime)

        {

            DateTime retDateTime;

            if (DateTime.TryParse(sDateTime, out retDateTime) != true)

            {//support relative date format e.g. “-1day 20:00” means yesterday at 20:00

                string[] sDateTimeParts = sDateTime.Split(new char[] { ‘ ‘ }, StringSplitOptions.RemoveEmptyEntries);

                if (sDateTimeParts.Length != 2)

                {

                    throw new ArgumentException(String.Format(“DateTime format {0} is not recognized “, sDateTime));

                }

                string sRelativeDays = sDateTimeParts[0].Trim();

 

                string sUnitKey = “day”;// //todo support month and other

                if (!sRelativeDays.ToLower().EndsWith(sUnitKey))

                {

                    throw new ArgumentException(String.Format(“DateTime format {0} is not recognized “, sDateTime));

                }

                sRelativeDays = sRelativeDays.Replace(sUnitKey, “”);

                int nDays;

                if (int.TryParse(sRelativeDays, out nDays) != true)

                {

                    throw new ArgumentException(String.Format(“Unable to parse relative days {1} from DateTime {0}  “, sDateTime, sRelativeDays));

                }

                TimeSpan tsDays = new TimeSpan(nDays, 0, 0, 0);

                retDateTime = DateTime.Today.Add(tsDays);

                Debug.Assert(retDateTime.Minute == 0);

                Debug.Assert(retDateTime.Hour == 0);

                Debug.Assert(retDateTime.Second == 0);

 

                string sTime = sDateTimeParts[1].Trim();

                DateTime timeOfDay;

                if (DateTime.TryParse(sTime, out timeOfDay) != true)

                {

                    throw new ArgumentException(String.Format(“Unable to parse time {1} from DateTime {0} “, sDateTime, sTime));

                }

                retDateTime = new DateTime(retDateTime.Year, retDateTime.Month, retDateTime.Day, timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);

            }

            return retDateTime;

        }

        public static bool IsDayOfWeekInRange(DayOfWeek dayOfWeek, DateTime dateFrom, DateTime dateTo, bool bExcludeEndDate)

        {

            DateTime tempDate = dateFrom;

            //            if(dateFrom> dateTo){ throw new ArgumentException(String.Format(“dateFrom {0} must be less or equal than dateTo {1}”,dateFrom,  dateTo)};

            DateTime dateEnd = bExcludeEndDate ? dateTo.AddDays(-1) : dateTo;

            while (tempDate <= dateEnd)

            {

                if (tempDate.DayOfWeek == dayOfWeek)

                    return true;

                tempDate = tempDate.AddDays(1);

            }

            return false;

        }

 

        #region  next day of week functions

 

        //from http://forums.asp.net/p/873363/883549.aspx      

        /// <summary>

        /// Gets the next occurence of future day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        /// <param name=”dayOfWeek”>Next Day of week to find.</param>

        public static DateTime GetNextOccurenceOfDay(DateTime value, DayOfWeek dayOfWeek)

        {

            return GetNextOccurenceOfDay(value, dayOfWeek, false);

        }

        public static DateTime GetNextOccurenceOfDay(DateTime value, DayOfWeek dayOfWeek, bool bIncludeStartDay)

        {

            //TODO add ClosestDay that should start formprovided day

            int daysToAdd = dayOfWeek – value.DayOfWeek;

            int nMinDifference = bIncludeStartDay ? 0 : 1;

            if (daysToAdd < nMinDifference)

            {

                daysToAdd += 7;

            }

            return value.AddDays(daysToAdd);

 

            //DateTime tempDate = value.AddDays(1);

            //while (tempDate.DayOfWeek != dayOfWeek)

            //{

            //    tempDate = tempDate.AddDays(1);

            //}

            //return tempDate;

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime NextMonday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Monday);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime NextWednesday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Wednesday);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime NextFriday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Friday);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime NextSunday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Sunday);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime NextSaturday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Saturday);

        }

        public static DateTime NextTuesday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Tuesday);

        }

 

        public static DateTime ClosestMonday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Monday, true);

        }

        public static DateTime ClosestTuesday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Tuesday, true);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime ClosestWednesday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Wednesday, true);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime ClosestFriday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Friday, true);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime ClosestSaturday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Saturday, true);

        }

        /// <summary>

        /// Gets the next occurence of speified day.

        /// </summary>

        /// <param name=”value”>DateTime value to start with.</param>

        public static DateTime ClosestSunday(DateTime value)

        {

            return GetNextOccurenceOfDay(value, DayOfWeek.Sunday, true);

        }

 

 

        #endregion  //next/closest day of week functions

 

 

 

    }

Generic function to removeDuplicates from Generic List

        //created based on http://www.kirupa.com/net/removingDuplicates2.htm

        //Why it is not in .Net Framework yet? Why HashSet<T> is only in Orcas(http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx)

        public static List<GenericType> removeDuplicates<GenericType>(List<GenericType> inputList)

        {

            Dictionary<GenericType, int> uniqueStore = new Dictionary<GenericType, int>();

            List<GenericType> finalList = new List<GenericType>();

 

            foreach (GenericType currValue in inputList)

            {

                if (!uniqueStore.ContainsKey(currValue))

                {

                    uniqueStore.Add(currValue, 0);

                    finalList.Add(currValue);

                }

            }

            return finalList;

        }

 

Alternative solution is to use List.RemoveAll(Predicate<T>) -(misleading name for the function, that allow to remove only specified by Predicate)

 

Dynamic URL Web Service URL is not loaded from applicationSettings section in Console application

I have a class library DLL, that has client web services reference. The reference is dynamic and in generated app.config the URL is listed inside <applicationSettings>.
I am using the class from web Application(WAP) and by copying <..Properties.Settings> to web.config I am able to change the URL just by modifying value in web.config(I even wrote helper class to Update Dynamic Web reference URLs Diring Installation in Visual Studio 2005). The approach is well described in
How to share dynamic URLs across multiple Web Application Projects  post.

I recently tried to call the same client web services class from windows console application. I copied the same section <..Properties.Settings> to console’s app.config, but URL, specified in config file, is ignored, and application uses default hardcoded value.

I tried a few things without success. The troubleshooting is very annoying because  if the corresponding setting in config file not found, .Net infrastructure doesn’t report any warning, but just uses default vaue.  I ended up by writing extra code to read URL from app.settings and explicitely assign URL to web service with the code similar to the following:

service.Url = ConfigurationSettings.AppSettings[“WebServiceUrl”];

It seems that other peoople also sometimes have problems  in setting dynamic URL(for example see Dynamic URL Behavior & Configuration  thread).

Do not cache Web ListItems

In our ASP.NET application we have DropDownLists with standard values from reference data(e.g list of Countries).
And we used Cache to avoid re-loading them from the database. The function was like the following:
            private void LoadItems()
            {
                  ListItem[] cachedItems;
                  cachedItems = GetAppCacheItems();
                  if (cachedItems == null)
                  {
                        //Load the reference data from the database omitted for simplicity
                        SetAppCacheItems(cachedItems);
                  }
                  Items.Clear();
                  Items.AddRange(cachedItems);
            }
 And this method worked for a long time. Unfortunately, some users complained that sometimes combo-boxes showed values, different from what they selected. Delelopers tried to reproduce the problem on the development machines without success.
I’ve wrote Watin test case trying to reproduce the problem, and it helped me to find the cause.
ListItem includes Selected  property and keeping it in a cache effectilely shares the selection between all users. If one user selected AU as country, but other user selected US at the same time, the  first user can see US as his selection.
 
I had to change code to recreate ListItems for each request.
 
It is still a good idea to keep returned from database data as Dataset or other collection in a cache(For example see Peter A. Bromberg’s article VB.Net: Database/xml enabled, self-cacheing, TooltipDropDownList ServerControl orMichael Thomas‘s Custom auto-bound Drop Down List post).
 

I was surprize to find, that Core C# and .NET  by Stephen C. Perry recommends to cache ListItemCollection, which will cause the bug. 

Helper Classes that I am using.

I’ve posted a few helper classes, that I’ve created by myself or based on some others source code.
There are also a few classes from other authors, that I am using in my applications without or with minor changes.

Below I will list the  links to their classes:

Configuration:
C#/.NET Command Line Arguments Parser(by the way, it was the first class in C#, that I included to VB solution)

Custom app.config  -load configuration settings from an external file(alternatively see Reading a config section from an external file in ASP.NET 2.0)

ADO.NET  helpers:

Export Data to CSV ( Excel ), C# Samples (alternatively

C# class library for exporting data to CSV/Excel file – The CodeProject could be used)

ASP.NET

Common Web Page Class Library – Part 2 By Eric Woodruff – Detecting changes in data controls in ASP.NET web forms
(Consider to use Dirty Panel Extender (ASP.NET AJAX) – The Code Project  instead)

To manipulate with URI/URL I am using my own UriHelper class as well as UrlUtils class, downoaded from Mono(some early version can be viewed here). I’ve just changed class to public,and commented references to internal methods.

I’ve noticed that some of my  helper classes are not searched by Google, that II hope that these links will help Google to crawl it:
DataBinderHelper class..
My StreamHelper class
My ArrayHelper class.