Dynamically add User Control to other ASP.NET controls children list.

I wanted to dynamically add my user control as a child to another control.
I’ve used the code with new constructor, as I did for standard ASP.NET server controls and custom controls.

 Dim ctrlInstances As SearchAreasInstancesUsc = new SearchAreasInstancesUsc() ‘Incorrect
tCell.Controls.Add(ctrlInstances)

Then I found that declaratively defined( in ASCX markup) controls are not initialized and set to null.
Of course, I should LoadControl to allow ASP.NET to initialize all declarations.

Dim ctrlInstances As SearchAreasInstancesUsc = LoadControl(“SearchAreaInstancesUsc.ascx”‘correct
tCell.Controls.Add(ctrlInstances)

UPDATE: I strongly recommend to read a great atricle: TRULY Understanding Dynamic Controls  -Parts 1-4.
(See also related Rendering ASP.NET Controls out of order  and Rendering ASP.NET Controls out of place)

If you still need to use dynamic controls, some more examples are shown in Dynamically Created Controls: Dynamic Rows Sample (and Dynamically Created Controls in ASP.NET). 

Difference in HybridDictionary and Generic Dictionary Item behavior if the specified key is not found

In .Net 1.1 I’ve used HybridDictionary.Item and my code expected that if the specified key is not found, attempting to get it returns a null reference.
But in .Net 2.0  Generic Dictionary.Item  if the specified key is not found, a get operation throws a KeyNotFoundException  and I have to use Dictionary.TryGetValue  or check ContainsKey before calling Item.


 

Custom action condition to run for a new or upgraded product.

I have a custom action condition (in Visual Studio Web Setup Project) that I want  to run for installation of a new or upgraded product. I do not want to run it on repair (and also during uninstall).


First of all I tried “Not Installed” condition. But it doesn’t work for version upgrade. I’ve tried


Not Remove=”ALL” but it also doesn’t work for version upgrade( it seems that deleting previous version set the property Remove=”ALL”)


I’ve tried UPGRADINGPRODUCTCODE , but it is set for the previous version, not for the version being installed.


The article http://www.rsdn.ru/article/install/wininstaller2.xml (sorry, in Russian only) suggests to use IS_MAJOR_UPGRADE ,but the property is applicable for InstalledShield only.


Finally I found combination that is working:


(Not Installed) OR PREVIOUSVERSIONSINSTALLED
Note that brackets are important to evaluate NOT first and condition is case-sensitive).


PREVIOUSVERSIONSINSTALLED is not documented property, I found it when reading msi log and in a few posts(e.g. here: “If the search at the start of the install detects
an older version, it creates the PREVIOUSVERSIONSINSTALLED property,
case-sensitive.“ ).


NOTE: I found that custom action with condition
(Not Installed) OR PREVIOUSVERSIONSINSTALLED works on my development machine, but it was not invoked on my deployment machine until I changed target virtual directory. Mistery ???

Intermittent WebException “The remote name could not be resolved” -try a few times.

I’ve noticed that one of web services, that I am using sometimes(usually at the first attempt) returns WebException “The remote name could not be resolved”.
I’ve desided to include re-try code in my call and it made my application more reliable:

                // I beleive that it’s a good idea to re-try in case of “The remote name could not be resolved”


                for (int i = 0; i < 3; i++)


                {


                    try


                    {   //call web service


                        ds = ReadRssUrlAsDataSet(timeStart, url);


                        break;


                    }


                    catch (WebException exc)


                    {


                        if (exc.Message.Contains(“The remote name could not be resolved”))


                        {  DebugHelper.TracedLine(“Attempt “ + i.ToString() + ” failed.” +exc.Message);


                            continue;//try 3 times


                        }


                        throw;


                    }


                }

How to open web.config file from custom action installer class, located in DLL.


One of the readers of the my post “Using VS 2005 Web Setup Project with custom actions” asked how to pick web.config file. that is actually part of the web project, from custom action installer class located in a separate DLL.


 With an assumption that DLL with installer class located in the BIN folder of the web project , you can do the following:


Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim sConfigFileName As String FSHelperLib.AppSettingsHelper.GetConfigFileName(asm)


where  


        public static string GetConfigFileName(Assembly ExecutingAssembly)


        {


            string sPath = “”;


            { //root folder one level up from bin


                sPath = SystemHelper.GetWebRootFolder(ExecutingAssembly);


                sPath = sPath + @”web.config”;


}


            if (!File.Exists(sPath))


            {


                throw new FileNotFoundException(“Missing config file “ + sPath);


            }


            return sPath;


        }


 See also My SystemHelper class for GetWebRootFolder definition.



 

My SystemHelper class

I’ve posted a few code snippets and some people noticed that there are references to unresolved methods.I am using a few helper classes. This post describes my SystemHelper class:

 

namespace FSHelperLib

{

    using Iesi.Collections;

    using Microsoft.VisualBasic;

    using Microsoft.VisualBasic.CompilerServices;

    using Microsoft.Win32;

    using System;

      using System.IO;

    using System.Collections;

      using System.Diagnostics ;

      using System.Reflection;

    using System.Runtime.CompilerServices;

    using System.Web;

 

    public class SystemHelper

    {

        // Methods

        public SystemHelper()

        {

        }

 

        public static string AppTitle()

        { //       ‘From http://www.dotnet247.com/247reference/msgs/15/78041.aspx

            if (SystemHelper.IsWebApplication())

            {

                char[] chArray1 = new char[1] { ‘/’ } ;

                return HttpContext.Current.Request.ApplicationPath.TrimStart(chArray1); //’returns name like “/vLearning”

            }

//                ‘or sProductName = Process.GetCurrentProcess().ProcessName

//            ‘ or Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName)

            Assembly asm = Assembly.GetEntryAssembly();

                  if(asm==null) //if called from NUnit Debugger

                  {asm = Assembly.GetExecutingAssembly();

                  }

            return AssemblyTitle( asm);

        }

            public static string AssemblyTitle(Assembly asm)

            { //       ‘From http://www.dotnet247.com/247reference/msgs/15/78041.aspx

                  AssemblyTitleAttribute attribute1 = (AssemblyTitleAttribute) Attribute.GetCustomAttribute(asm, typeof(AssemblyTitleAttribute));

                  //        ‘Application.ProductName is not working in Dll

                  //        ‘Assembly.GetEntryAssembly().FullName not reliable ?? see http://weblogs.asp.net/asanto/posts/26710.aspx

                  string sRet=attribute1.Title;

                  if (DataHelper.IsNullOrEmpty( sRet))

                  {sRet= asm.GetName().Name;

                  }

                  return sRet ;

            }

            ///

            /// Reads from table, decrypts and check  as valid date and integers

            ///

            ///
Assembly.GetExecutingAssembly()

            ///

            public static string GetAssemblyVersion(Assembly asm)

            {

                  FileVersionInfo info1 = FileVersionInfo.GetVersionInfo(asm.Location);

                  return info1.ProductVersion;

            }

 

 

        public static bool IsWebApplication()

        { //’http://groups.google.com.au/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=ebVausWRBHA.1408%40tkmsftngp05

                  //issue: it will return wrong answer if called from async thread running from Web

                  //try to check some System.AppDomain.CurrentDomain properties

            bool bIsASP = true;

            if (Information.IsNothing(HttpContext.Current))

            {

                bIsASP = false;

            }

            return bIsASP;

        }

            public static string GetWebRootFolder(Assembly ExecutableAssembly)

            {

                  //Debug.Assert(IsWebApplication()); can be called frm installer or tester

                  string sPath = ExecutableAssembly.Location;

                  //remove assembly name

                  sPath = sPath.Remove(sPath.LastIndexOf(@””), Strings.Len(sPath) – sPath.LastIndexOf(@””));

                  //remove BIN folder name

            if((sPath.ToUpper().EndsWith(@”BIN”)) )//15/6/2006

            {

                sPath = sPath.Remove(sPath.LastIndexOf(@””), Strings.Len(sPath) – sPath.LastIndexOf(@””));

            }

                  Debug.Assert(Directory.Exists(sPath));

                  //Debug.Assert(sPath==System.AppDomain.CurrentDomain.BaseDirectory);//can be called frm installer or tester

                  return sPath;

            }

 

            //’Addition to math.Max

            public static object Max(Array elements)

        {

            object oRet=null;

            SortedSet set1 = new SortedSet(elements);

            IEnumerator enumerator1 = set1.GetEnumerator();

            while (enumerator1.MoveNext())

            {

                oRet = RuntimeHelpers.GetObjectValue(enumerator1.Current);

            }

            return oRet;

        }

            ///

            /// Creates a COM object given it’s ProgID.

            ///

            ///
The ProgID to create

            /// The newly created object, or null on failure.

            //from http://www.novicksoftware.com/TipsAndTricks/tip-csharp-create-com-object-by-progid.htm

            public static object COMCreateObject (string sProgID)

            {

                  // We get the type using just the ProgID

                  Type oType = Type.GetTypeFromProgID (sProgID);

                  if (oType != null)

                  {                            

                        return Activator.CreateInstance(oType);

                  }

                 

                  return null;

            }

            public static void LateSet(         object o,               Type objType,                 string name,      string Value)

            {

                  object[] objArray1 = new object[1] { Value } ;

                  LateBinding.LateSet(o , null, name, objArray1, null);

            }

 

 

            //’Addition to math.Min

        public static object Min(Array elements)

        {

            object oRet=null;

            SortedSet set1 = new SortedSet(elements);

            IEnumerator enumerator1 = set1.GetEnumerator();

            while (enumerator1.MoveNext())

            {

                oRet = RuntimeHelpers.GetObjectValue(enumerator1.Current);

                break;

            }

            return oRet;

        }

 //See DateTime.Compare

        public static DateTime Min(DateTime t1, DateTime t2)

        {

            if (DateTime.Compare(t1, t2) > 0)

            {

                return t2;

            }

            return t1;

        }

 

 

     }

}

 

 


.Net SQL Parser

I had a requirement to parse SQL string, in particular with CONTAINS(column_list) and modify SELECT column list.
I’ve found two most promising implementations General SQL Parser from   http://www.sqlparser.com/  and SharpHSQL from http://www.c-sharpcorner.com/database/SharpHSQL.asp article.
General SQL Parser has quite qood API, but it doesn’t have open source and doesn’t recognize contains with column_list.


SharpHSQL is a early C# port of the HSQL Database Engine which has a source code, but also doesn’t  recognize CONTAINS(column_list) and additionally doesn’t re-construct SQL from previously parsed SQL string. I’ve tried to add the functionality that I wanted,but it wasn’t easy.


Finally I gave up with SharpHSQL code and used a few RegEx pattern to modify SQL  as I needed. Unfortunately the code is not bullet-prove and will not work if sub-queries will be used in SELECT columns list.


Recently I  was pointed to GOLD Parser Engine, which I didn’t research yet.