Every once in a while we need to open a new window from our main page and we want to make sure it has the focus so the user does not keep on clicking the same "open" button creating multiple pages in the background.
It sounds simple but if you are using "Update Panels" so avoid the annoying refresh look in your page and then you want to open a new window, this can be challenging. Instead here is a way to do it. I used a mix of javascript and c# code.
In my client javascript I defined a function that calls the window.open and pass the proper parameters to declare the page i would like to open.
//script language="javascript"//
function ReportDetailPopup(xCaseNumber) {
var w = window.open("ReportUIDetail.aspx?ExternalCaseNumber=" + xCaseNumber);
}
//script//
Now in my codebehind i call the "RegisterStartupScript" function to call my javascript function and then i set the focus on the Page recently called.
protected void grdResults_SelectedIndexChanged(object sender, EventArgs e)
{
string externalCaseNumber = "";
externalCaseNumber = grdResults.SelectedDataKey.Value.ToString();
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "OpenNewWindow", "ReportDetailPopup('" + externalCaseNumber + "');", true);
Page.Focus();
}
I am certain that there are other ways to do it, but if you are entering the world of "update panels" you will find that many things don't work the way they should for obvious reasons. I will post more tricks to get the most out of update panels.
Friday, May 15, 2009
Custom Config file in a custom location?
Have you ever had the need to share some settings among different parts of your n-tier environment? Obviously yes! Well recently i was in need of using some type of file that will contain data that can be use in different components of my application without having to replicate the file/data inside and turn it into a maintenance nightmare. Many ideas were thrown around. At the end we agree on using a config file. Similar to the Web.config or the App.Config, but fully customize for our application.
There is a fairly simple way of doing this. First you will create your config file with the values you want.

I called this file “DBSettings.config” and I place it in the same directory as all of my assemblies (dlls) the actual “bin” folder.
Secondly, I created a project called “Controller” with a class called “ConfigurationSettings.cs” Here is the code for this file.
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
namespace MyNamespace.Controller
{
public class ConfigurationSettings
{
private const string APPSETTINGS_SECTION_NAME = "appSettings";
private const string CONFIG_SECTIONS_PATH = "/configuration/configSections";
private const string CONFIG_SECTIONS_GROUP_PATH = "sectionGroup";
private const string CONFIG_SECTION_PATH = "section";
private static Assembly _callingAssembly = null;
private ConfigurationSettings()
{
}
public static object GetConfig(string sectionName, string configFileName)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configFileName);
IConfigurationSectionHandler handler = GetHandler(sectionName, xmlDoc);
object config = null;
if (sectionName == APPSETTINGS_SECTION_NAME)
{
config = GetAppSettingsFileHandler(sectionName, handler, xmlDoc);
}
else
{
XmlNode node = xmlDoc.SelectSingleNode("//" + sectionName);
config = handler.Create(null, null, node);
}
return config;
}
public static object GetConfig(string sectionName)
{
Assembly asm = Assembly.GetCallingAssembly();
if (_callingAssembly != null && _callingAssembly != asm)
{
asm = _callingAssembly;
}
string filePath = Path.GetDirectoryName(asm.Location);
string asmName = Path.GetFileName(asm.Location);
string configFileName = Path.Combine(filePath, asmName + ".config");
return GetConfig(sectionName, configFileName);
}
public static NameValueCollection AppSettingsLocationDefined(string configFileName)
{
NameValueCollection appSettings = (NameValueCollection)ConfigurationSettings.GetConfig(APPSETTINGS_SECTION_NAME, configFileName);
if (appSettings == null)
{
appSettings = new NameValueCollection();
}
return appSettings;
}
public static NameValueCollection AppSettings
{
get
{
//Store the calling assembly because we are about to call ourselves
_callingAssembly = Assembly.GetCallingAssembly();
NameValueCollection appSettings = (NameValueCollection)ConfigurationSettings.GetConfig(APPSETTINGS_SECTION_NAME);
if (appSettings == null)
{
appSettings = new NameValueCollection();
}
return appSettings;
}
}
protected static IConfigurationSectionHandler GetHandler(string sectionName, XmlDocument xmlDoc)
{
IConfigurationSectionHandler handler = null;
if (sectionName == APPSETTINGS_SECTION_NAME)
{
handler = new NameValueSectionHandler();
return handler;
}
string[] sections = sectionName.Split('/');
string sectionGroup = string.Empty;
string section = string.Empty;
string xPath = string.Empty;
//see if we have a section group that we have to go through
if (sections.Length > 1)
{
sectionGroup = sections[0];
section = sections[1];
xPath = string.Format(CONFIG_SECTIONS_PATH + "/" +
CONFIG_SECTIONS_GROUP_PATH + "[@name='" + sectionGroup + "']/" +
CONFIG_SECTION_PATH + "[@name='" + section + "']");
}
else
{
section = sections[0];
xPath = string.Format(CONFIG_SECTIONS_PATH + "/" +
CONFIG_SECTION_PATH + "[@name='" + section + "']");
}
XmlNode node = xmlDoc.SelectSingleNode(xPath);
string typeName = node.Attributes["type", ""].Value;
if (typeName == null || typeName.Length == 0)
return handler;
Type handlerType = Type.GetType(typeName);
handler = (IConfigurationSectionHandler)Activator.CreateInstance(handlerType);
return handler;
}
protected static object GetAppSettingsFileHandler(string sectionName, IConfigurationSectionHandler parentHandler, XmlDocument xmlDoc)
{
object handler = null;
XmlNode node = xmlDoc.SelectSingleNode("//" + sectionName);
XmlAttribute att = (XmlAttribute)node.Attributes.RemoveNamedItem("file");
if (att == null || att.Value == null || att.Value.Length == 0)
{
return parentHandler.Create(null, null, node);
}
else
{
string fileName = att.Value;
string dir = Path.GetDirectoryName(fileName);
string fullName = Path.Combine(dir, fileName);
XmlDocument xmlDoc2 = new XmlDocument();
xmlDoc2.Load(fullName);
object parent = parentHandler.Create(null, null, node);
IConfigurationSectionHandler h = new NameValueSectionHandler();
handler = h.Create(parent, null, xmlDoc2.DocumentElement);
}
return handler;
}
}
}
Finally I created another project within the solution called “Controller.Database” with a class called
“LoadData.cs” This class contains all of the DB calls with sprocs and query calls, but the important part
is the actual connection string. I am including the part that bring the connection string from the customize config file. It is important to remember that you need to reference the IO and the Reflection assemblies in order to get it to read the proper values.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Threading;
using System.ComponentModel;
using MyNamespace.Controller;
using System.IO;
using System.Reflection;
namespace MyNamespace.Controller.Database
{
public class DataAccessManager
{
private const int DEFAULT_MAPPING_SERVICETYPE = 0;
#region Connection String
public static string ConnectionString
{
get
{
//Retrieving the location of the assembly file.
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
//Appending the custom config file name.
appPath = Path.Combine(appPath, "DBSettings.config");
return ConfigurationSettings.AppSettingsLocationDefined(appPath)["ConnectionString"].ToString();
}
}
#endregion
...more code that makes specific calls to get data to different components accros the application.
From this point on you can call the ConnectionString static string from the LoadData.cs and the rest will
be taken care of.
The way we implemented this code allowed us to not include any db connection objects in the UI by
referencing only the components that are in charge of gathering the data.
There is a fairly simple way of doing this. First you will create your config file with the values you want.
I called this file “DBSettings.config” and I place it in the same directory as all of my assemblies (dlls) the actual “bin” folder.
Secondly, I created a project called “Controller” with a class called “ConfigurationSettings.cs” Here is the code for this file.
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
namespace MyNamespace.Controller
{
public class ConfigurationSettings
{
private const string APPSETTINGS_SECTION_NAME = "appSettings";
private const string CONFIG_SECTIONS_PATH = "/configuration/configSections";
private const string CONFIG_SECTIONS_GROUP_PATH = "sectionGroup";
private const string CONFIG_SECTION_PATH = "section";
private static Assembly _callingAssembly = null;
private ConfigurationSettings()
{
}
public static object GetConfig(string sectionName, string configFileName)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configFileName);
IConfigurationSectionHandler handler = GetHandler(sectionName, xmlDoc);
object config = null;
if (sectionName == APPSETTINGS_SECTION_NAME)
{
config = GetAppSettingsFileHandler(sectionName, handler, xmlDoc);
}
else
{
XmlNode node = xmlDoc.SelectSingleNode("//" + sectionName);
config = handler.Create(null, null, node);
}
return config;
}
public static object GetConfig(string sectionName)
{
Assembly asm = Assembly.GetCallingAssembly();
if (_callingAssembly != null && _callingAssembly != asm)
{
asm = _callingAssembly;
}
string filePath = Path.GetDirectoryName(asm.Location);
string asmName = Path.GetFileName(asm.Location);
string configFileName = Path.Combine(filePath, asmName + ".config");
return GetConfig(sectionName, configFileName);
}
public static NameValueCollection AppSettingsLocationDefined(string configFileName)
{
NameValueCollection appSettings = (NameValueCollection)ConfigurationSettings.GetConfig(APPSETTINGS_SECTION_NAME, configFileName);
if (appSettings == null)
{
appSettings = new NameValueCollection();
}
return appSettings;
}
public static NameValueCollection AppSettings
{
get
{
//Store the calling assembly because we are about to call ourselves
_callingAssembly = Assembly.GetCallingAssembly();
NameValueCollection appSettings = (NameValueCollection)ConfigurationSettings.GetConfig(APPSETTINGS_SECTION_NAME);
if (appSettings == null)
{
appSettings = new NameValueCollection();
}
return appSettings;
}
}
protected static IConfigurationSectionHandler GetHandler(string sectionName, XmlDocument xmlDoc)
{
IConfigurationSectionHandler handler = null;
if (sectionName == APPSETTINGS_SECTION_NAME)
{
handler = new NameValueSectionHandler();
return handler;
}
string[] sections = sectionName.Split('/');
string sectionGroup = string.Empty;
string section = string.Empty;
string xPath = string.Empty;
//see if we have a section group that we have to go through
if (sections.Length > 1)
{
sectionGroup = sections[0];
section = sections[1];
xPath = string.Format(CONFIG_SECTIONS_PATH + "/" +
CONFIG_SECTIONS_GROUP_PATH + "[@name='" + sectionGroup + "']/" +
CONFIG_SECTION_PATH + "[@name='" + section + "']");
}
else
{
section = sections[0];
xPath = string.Format(CONFIG_SECTIONS_PATH + "/" +
CONFIG_SECTION_PATH + "[@name='" + section + "']");
}
XmlNode node = xmlDoc.SelectSingleNode(xPath);
string typeName = node.Attributes["type", ""].Value;
if (typeName == null || typeName.Length == 0)
return handler;
Type handlerType = Type.GetType(typeName);
handler = (IConfigurationSectionHandler)Activator.CreateInstance(handlerType);
return handler;
}
protected static object GetAppSettingsFileHandler(string sectionName, IConfigurationSectionHandler parentHandler, XmlDocument xmlDoc)
{
object handler = null;
XmlNode node = xmlDoc.SelectSingleNode("//" + sectionName);
XmlAttribute att = (XmlAttribute)node.Attributes.RemoveNamedItem("file");
if (att == null || att.Value == null || att.Value.Length == 0)
{
return parentHandler.Create(null, null, node);
}
else
{
string fileName = att.Value;
string dir = Path.GetDirectoryName(fileName);
string fullName = Path.Combine(dir, fileName);
XmlDocument xmlDoc2 = new XmlDocument();
xmlDoc2.Load(fullName);
object parent = parentHandler.Create(null, null, node);
IConfigurationSectionHandler h = new NameValueSectionHandler();
handler = h.Create(parent, null, xmlDoc2.DocumentElement);
}
return handler;
}
}
}
Finally I created another project within the solution called “Controller.Database” with a class called
“LoadData.cs” This class contains all of the DB calls with sprocs and query calls, but the important part
is the actual connection string. I am including the part that bring the connection string from the customize config file. It is important to remember that you need to reference the IO and the Reflection assemblies in order to get it to read the proper values.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Threading;
using System.ComponentModel;
using MyNamespace.Controller;
using System.IO;
using System.Reflection;
namespace MyNamespace.Controller.Database
{
public class DataAccessManager
{
private const int DEFAULT_MAPPING_SERVICETYPE = 0;
#region Connection String
public static string ConnectionString
{
get
{
//Retrieving the location of the assembly file.
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
//Appending the custom config file name.
appPath = Path.Combine(appPath, "DBSettings.config");
return ConfigurationSettings.AppSettingsLocationDefined(appPath)["ConnectionString"].ToString();
}
}
#endregion
...more code that makes specific calls to get data to different components accros the application.
From this point on you can call the ConnectionString static string from the LoadData.cs and the rest will
be taken care of.
The way we implemented this code allowed us to not include any db connection objects in the UI by
referencing only the components that are in charge of gathering the data.
Subscribe to:
Posts (Atom)