Search This Blog

Tuesday, December 21, 2010

Custom Configuration Handler

I was going through a book about a different ways of reading configuration file and then I came across a scenario where it requires to get icon image url based on extensions of File. Of course there may be several ways of solving this issue but to me the most interesting one was to creating a section in the web.config for the extension's Image Url and a custom configuration section handler to read the same when used in an application. The code snippets are taken from the book but I made a solution to demonstrate its use in an actual scenario.


1) Lets say we plan to create the following mapping in xml to map a particular extension of file to Image Url.



               <unknownIcon imageUrl="Icons/unknown.gif" description="Unknown File Type"/>
<icon imageUrl="Icons/word.gif" description="Word Processing Document">
<ext>.DOC</ext>
<ext>.RTF</ext>
<ext>.TXT</ext>
</icon>
<icon imageUrl="Icons/excel.gif" description="Excel Document">
<ext>.XLS</ext>
<ext>.CSV</ext>
</icon>
<icon imageUrl="Icons/image.gif" description="Picture/Image">
<ext>.GIF</ext>
<ext>.TIFF</ext>
<ext>.JPG</ext>
<ext>.BMP</ext>
<ext>.PNG</ext>
</icon>
2) Let us create the Model class which will hold this data during run time, so I create a Class Library Project called "IconConfiguration" and name the newly added class as "IconConfigurationItem".



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace IconConfiguration
{
    public class IconConfigurationItem
    {
        private string _image;
        private string _description;
        private string _extension;


        public IconConfigurationItem(string image, string description, string extension)
        {
            this._image = image;
            this._description = description;
            this._extension = extension;
        }


        public string Image 
        { 
            get
            {
                return this._image;
            }
            set
            {
                this._image = value;
            }
        }
        public string Description 
        {
            get
            {
                return this._description;
            }
            set
            {
                this._description = value;
            }
        }
        public string Extension
        {
            get
            {
                return this._extension;
            }
            set
            {
                this._extension = value;
            }
        }
    }
}

3) The next step is to create a collection class which will hold each of these IconConfigurationItem. So I added another class to my Class Library Project and named it "IconConfigurationCollection". 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace IconConfiguration
{
    public class IconConfigurationCollection : CollectionBase
    {
        public IconConfigurationItem unknownIconInfo;
        private int getExtensionIndex(string extension)
        {
            int index = 0;
            for (index = 0; index < this.List.Count; index++)
            {
                IconConfigurationItem item = (IconConfigurationItem)this.List[index];
                if (item.Extension.Equals(extension.ToUpper().Trim()))
                    return index;
            }
            return -1;
        }
        public IconConfigurationItem getIconInfo(string extension)
        {
            int index = getExtensionIndex(extension);
            if (index == -1)
                return unknownIconInfo;
            else
                return (IconConfigurationItem)(this.List[index]);
        }
        public void Add(IconConfigurationItem obj)
        {
            this.List.Add(obj);
        }
    }
}

4) The very next step will be to create the Configuration Handler which will read the particular XML from my Web.config. It must inherit from IConfigurationSectionHandler and when you do that the intelligence will also write the method Create which needs to be implemented. My Configuration Handler class name is "IconConfigurationHandler".

using System.Configuration;
using System.Xml;
//<unknownIcon imageUrl="Icons/unknown.gif" description="Unknown File Type"/>
//<icon imageUrl="Icons/word.gif" description="Word Processing Document">
//    <ext>.DOC</ext>
//    <ext>.RTF</ext>
//    <ext>.TXT</ext>
//</icon>
//<icon imageUrl="Icons/excel.gif" description="Excel Document">
//    <ext>.XLS</ext>
//    <ext>.CSV</ext>
//</icon>
//<icon imageUrl="Icons/image.gif" description="Picture/Image">
//    <ext>.GIF</ext>
//    <ext>.TIFF</ext>
//    <ext>.JPG</ext>
//    <ext>.BMP</ext>
//    <ext>.PNG</ext>
//</icon>
namespace IconConfiguration
{
    class IconConfigurationHandler : IConfigurationSectionHandler
    {
        #region IConfigurationSectionHandler Members

        public object Create(object parent, object configContext, System.Xml.XmlNode section)
        {
            IconConfigurationCollection returnObject = new IconConfigurationCollection();
            IconConfigurationItem configItem;

            XmlNodeList iconNodelist = section.SelectNodes("icon");
            XmlNodeList extensionNodeList;
            //XmlNode iconNode;
            //XmlNode extensionNode;

            foreach(XmlNode iconNode in iconNodelist) 
            {
                extensionNodeList = iconNode.SelectNodes("ext");
                foreach (XmlNode extensionNode in extensionNodeList)
                {
                    configItem = new IconConfigurationItem(
                        iconNode.Attributes.GetNamedItem("imageUrl").Value,
                        iconNode.Attributes.GetNamedItem("description").Value,
                        extensionNode.InnerText);
                    returnObject.Add(configItem);
                }
            }
            //Acquire and Process the Unknown Icon Node
            XmlNode unknownIconNode = section.SelectSingleNode("unknownIcon");
            if (unknownIconNode != null)
            {
                returnObject.unknownIconInfo = new IconConfigurationItem(
                    unknownIconNode.Attributes.GetNamedItem("imageUrl").Value,
                    unknownIconNode.Attributes.GetNamedItem("description").Value,
                  string.Empty);
            }
            return returnObject;
        }

        #endregion
    }
}

All it does is select icon and unknownIcon nodes from the custom section that we will add in the web.config and makes an object of type IconConfigurationItem and adds it to the Collection IconConfugurationCollection and returns the collection object.

5) We are almost done with the Library class, only the last thing which the Config.cs file/class which will read the web.config from the web project. But before writing this part, we can actually add a website to our solution and also add the custom section in the web.config, so we have a better idea of which section we will read before writing the config.cs file.

So I crated a Website and added a Page called "IconConfigHandler.aspx" and in the web.config, I added a section as

<!--Section for Custom Configuration Handler to pick up-->
<section name="IconConfig" type="IconConfiguration.IconConfigurationHandler, IconConfiguration"/> 

Note : The <configSections> element must be the first item defined in the <configuration> section. If you place any other elements in the <configuration> section before the <configSections> element, you will receive a compilation error.

So, This must be under configSections tag and the type is having a syntax like 
type="Namespace.Type, assembly". Now that we have added the new section name so we can added our mapping xml as in point (1) under the new section name i.e. "iconConfig", so it will read like the following

       <IconConfig>
<unknownIcon imageUrl="Icons/unknown.gif" description="Unknown File Type"/>
<icon imageUrl="Icons/word.gif" description="Word Processing Document">
<ext>.DOC</ext>
<ext>.RTF</ext>
<ext>.TXT</ext>
</icon>
<icon imageUrl="Icons/excel.gif" description="Excel Document">
<ext>.XLS</ext>
<ext>.CSV</ext>
</icon>
<icon imageUrl="Icons/image.gif" description="Picture/Image">
<ext>.GIF</ext>
<ext>.TIFF</ext>
<ext>.JPG</ext>
<ext>.BMP</ext>
<ext>.PNG</ext>
</icon>
</IconConfig>

This must be placed outside the <configSections> tag.

6) So we now write the Config class to read the above config

using System;
using System.Web;
using System.Collections.Generic;
using System.Configuration;

namespace IconConfiguration
{
    public static class Config
    {
        private const string sectionName = "IconConfig";
        private const string normalText = "normalRead";
        private static IconConfigurationCollection _iconData;
        public static IconConfigurationCollection IconData 
        { 
            get
            {
                if (_iconData == null)
                {
                    _iconData = (IconConfigurationCollection)ConfigurationManager.GetSection(sectionName);
                }
                return _iconData;
            }
        }
        public static string AppConfigData
        {
            get
            {
                return ConfigurationManager.AppSettings[normalText].ToString();
            }
        }
    }

}

*I have added a property called "AppConfigData" just to make sure that if I want to read without the custom section handler things are ok or not and that we will see shortly.

7) Next in the Webpage of the website I added a Textbox for entering the extension and a button, on click of which it will get the appropriate Image Url and also 2 lables, one to display the fetched url of the extension and the other one to read from App Settings without using the custom section handler. The code behind reads something like this as follows

protected void btnShowIcon_Click(object sender, EventArgs e)
    {
        string extension = txtEntension.Text.Trim();

        lblResult.Text = ((IconConfigurationItem)Config.IconData.getIconInfo(extension)).Image;
        lblRes.Text = Config.AppConfigData;
    }

Oh Boy ! It works just as expected.

Wednesday, November 24, 2010

Remote Desktop Connection as an Admin

You might have come across situations where you need to connect to a remote desktop and some other users are holding sessions and the total number has exceeded and the mstsc command will not allow further sessions to the remote desktop of the server.

One easy way to kick one user out will be to use the following command to login

%SystemRoot%\system32\mstsc.exe /admin

and then type ur username and password to get in.

Friday, November 19, 2010

Try Catch block in a Transaction

We can use TRY catch blocks from SQL Server 2005 onwards and can rollback a transaction if there were any errors. Please see the example below


BEGIN TRY
 SET XACT_ABORT ON -- Will rollback on any errors
 BEGIN TRANSACTION    -- Start the transaction
   DELETE FROM Mytable
WHERE id = 'something'
   -- If we reach here, success!
   COMMIT
END TRY
BEGIN CATCH
  -- Whoops, there was an error
  IF @@TRANCOUNT > 0
     ROLLBACK

  -- Raise an error with the details of the exception
  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
         @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

Friday, November 12, 2010

Checking data in database before going for any inserts

We commonly encounter a scenario where we have to check if a data is already there in table before going for any insertions. So here is a quick query for this purpose

please note that i wrote this query keeping Sql Server in mind.

IF NOT EXISTS ( SELECT TOP 1 [NAME] FROM myTable WHERE [Name] = 'check_name' )
BEGIN

INSERT INTO myTable
           ([Name]
           ,[Description]
           )
     VALUES
           ('check_name'
           ,'test'
           )
END

Tuesday, October 26, 2010

Passing array of parameters to UDF/Stored Proc in SQL Server

With the beautiful XML support from SQL Server 2005 onwards, passing multiple values to Stored Procedure or User Defined Function has never been so easy. Please see the sample code


-- Pass all employeeId or other information together
-- in a sincle call of the stored procedure

DECLARE @x xml, @EMPID INT
SELECT @x =
  N'<Root>
      <Employee empId="1"/>
    </Root>'
SELECT E.EMPLOYEEID FROM TBLEMP E   
JOIN @x.nodes('Root/Employee') AS T(Item)
ON E.EMPLOYEEID = T.Item.value('@empId', 'int')

-- Writting the stored procedure

CREATE PROCEDURE SP_EMPLOYEES @ids xml AS
   SELECT E.EMPLOYEEID, E.MANAGERID, E.NAME
   FROM   TBLEMP E
   JOIN   @ids.nodes('/Root/Employee') AS T(Item)
     ON   E.EMPLOYEEID = T.Item.value('@num', 'int')
go

-- Test the procedure with the following
EXEC SP_EMPLOYEES N'<Root><Employee num="1"/><Employee num="2"/>
                             <Employee num="3"/><Employee num="4"/></Root>'

Searching for a text on SQL Server (PL SQL Style)

Hi those coming from a PL SQL background will be knowing of a very common functionality which enables you to search for a particular text through PL SQL Dev tool on a particular text. Now if you try to look for a same type of a feature on SQL Server Management Studio, there is none.


The work around is the following stored procedure.
SELECT OBJECT_NAME(id)
FROM syscomments
WHERE [text] LIKE '%foobar%'
AND OBJECTPROPERTY(id, 'IsProcedure') = 1
GROUP BY OBJECT_NAME(id)

So if you want to search for a text like foobar in all procedures used in the database, the query would look like something above. If the same thing has to be searched in a function then the parameter "IsProcedure" has to be changed to "IsFunction".


This tip will particularly important if you are associated with support and enhancement kind of activity and need to find say "How many times a particular table name is used in a procedure or a function".

Introduction

Hi,

My name is Kaushik and I am an ASP.NET developer working in the Greater Chicago Area. I have created this blog so that I can refer to the resolutions that could gather or find out while doing my day to day activities. Nothing is impossible to implement through software and at the same time its not possible to know everything, so a good reference is a key to quick resolutions to complicated/simple tasks.