Saturday, December 29, 2012

how to show Google Static Map using javascript

We often use Google Static Map to show office location or shop location. Moreover, it is in wide use to display the direction from one place to another. This post will explain you the simple way how to use Javascript for displaying dynamic Google Map using Google Static Maps API V2.
Google Static Map using Javascript
First, it needs the following script in <head> tag.
<script type="text/javascript">
    var position = new Object();
    function showPosition(position) {
        var latlon = position.latitude + "," + position.longitude;
        var imgUrl = "http://maps.googleapis.com/maps/api/staticmap?center=" +
            latlon + "&zoom=16&size=500x400&sensor=false";
        document.getElementById("mapholder").innerHTML = "<img src='" + imgUrl + "' />";
    }
    window.onload = function () {
        position.latitude = 13.745674;
        position.longitude = 100.53422;
        showPosition(position);
    }
    function showMap() {
        position.latitude = document.getElementById("txtLat").value;
        position.longitude = document.getElementById("txtLon").value;
        showPosition(position);
    }
</script>
Secondly, create the image container and controls in <body> tag as below:
<form id="form1" runat="server">
    <div id="mapholder">
    </div>
    <div>
        <asp:Label ID="Label1" runat="server" Text="Latitude :"></asp:Label>
        <asp:TextBox ID="txtLat" runat="server" Text="13.715236" ClientIDMode="Static"></asp:TextBox><br />
        <asp:Label ID="Label2" runat="server" Text="Longitude:"></asp:Label>
        <asp:TextBox ID="txtLon" runat="server" Text="100.591233" ClientIDMode="AutoID"></asp:TextBox><br />
        <asp:Button ID="Button1" runat="server" Text="Show Map" onclientclick="showMap();return false;" />
    </div>
</form>
That's it. When it run, it shows one location and then press "Show Map" button to see another place.
This post is the last one for this year. See you next year. Thank.

Sunday, November 18, 2012

How to update web.config in Web Setup Project

The Web Setup Project is the window installer that allow user to run the setup file and steps through a wizard to install the web application or web site so that the files for a Web Setup Projects are installed into a Virtual Root directory on Web servers.
To deploy a Web application to a Web server, it is easy to create a Web Setup project, build it, copy it to the Web server , and run the installer to install the application on the server using the settings defined in your Web Setup project. Let's start here step by step.

I assume that you have one solution project and one web application already.Let's say, web.config for Web Application look like as below:
<connectionStrings>
    -----
    <add name="NorthwindEntities"
         connectionString="metadata=res://*/NorthwindModel.csdl|res://*/NorthwindModel.ssdl|res://*/NorthwindModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=[ServerName];Initial Catalog=[DBName];Persist Security Info=True;User ID=[UserName];Password=[Password];MultipleActiveResultSets=True&quot;"
         providerName="System.Data.EntityClient" />
</connectionStrings>
<system.serviceModel>
    -----
    <client>
      <endpoint address="http://localhost:3961/Service1.svc" binding="basicHttpBinding"
       bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference.IService1"
       name="BasicHttpBinding_IService1" />
      <endpoint address="http://localhost:3961/Service1.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService11" contract="ServiceReference2.IService1"
        name="BasicHttpBinding_IService11" />
    </client>
</system.serviceModel>
Web Setup Installer will update the above configuration section during installation.

First, create a new web setup project
  1. On the File menu, point to Add Project, and then click New Project.
  2. In the resulting Add New Project dialog box, select the Setup and Deployment Projects folder.
  3. Choose Web Setup Project and type WebAppSetup in the Name box as below:

Second, create an installer class for custom action
  1. On the File menu, click New Project.
  2. In the New Project dialog box, select Visual C# Projects in the Project Type pane, and then choose Class Library in the Templates pane. In the Name box, type UpdateWebconfig.
  3. On the Project menu, click Add New Item.
  4. In the Add New Item dialog box, choose Installer Class. In the Name box, type Installer1.cs.
In Installer1.cs, it needs the following namespace for web configuration and virtual directory.


Develop the "Installer1.cs" as show below:
using System;
using System.Configuration;
using System.Configuration.Install;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.DirectoryServices;
using System.Web.Configuration;
using System.Windows.Forms;
using System.Collections;
using System.ServiceModel.Configuration;
namespace UpdatingWebconfig
{
    [RunInstaller(true)]
    public partial class Installer1 : System.Configuration.Install.Installer
    {
        public Installer1()
        {
            InitializeComponent();
        }
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            try
            {
                // Retrieve configuration settings           
                string targetSite = Context.Parameters["targetsite"];
                string targetVDir = Context.Parameters["targetvdir"];
                string targetDirectory = Context.Parameters["targetdir"];
                string serverName = Context.Parameters["serverName"];
                string dbName = Context.Parameters["databaseName"];
                string userName = Context.Parameters["userName"];
                string password = Context.Parameters["password"];
                string serviceUrl1 = Context.Parameters["serviceUrl1"];
                string serviceUrl2 = Context.Parameters["serviceUrl2"];
                if (serverName.Length < 1)
                    throw new InstallException("Please provide server name!");
                if (targetSite == null)
                    throw new InstallException("IIS Site Name Not Specified!");
                if (targetSite.StartsWith("/LM/"))
                    targetSite = targetSite.Substring(4);
              
                // Retrieve "Friendly Site Name" from IIS for TargetSite
                DirectoryEntry entry = new DirectoryEntry("IIS://LocalHost/" + targetSite);
                string friendlySiteName = entry.Properties["ServerComment"].Value.ToString();
                // Open Application's Web.Config           
                Configuration config = WebConfigurationManager.OpenWebConfiguration("/" + targetVDir, friendlySiteName);
                UpdateConnectionString(serverName, dbName, userName, password, config);
                UpdateEndPoint(serviceUrl1, serviceUrl2, config);
                // Persist web.config settings           
                config.Save();
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                if (ex.InnerException != null)
                    msg = ex.InnerException.ToString();
                MessageBox.Show(msg);
            }

        }
        //Method to update the connectionstring to your web.config:
        private static void UpdateConnectionString(string serverName, string dbName,
            string userName, string password, Configuration config)
        {
            ConnectionStringSettingsCollection settings = config.ConnectionStrings.ConnectionStrings;
            ConnectionStringSettings connSetting = settings["NorthwindEntities"];
            if (connSetting != null)
            {
                string strConn = connSetting.ConnectionString;
                strConn = strConn.Replace("[ServerName]", serverName);
                strConn = strConn.Replace("[DBName]", dbName);
                strConn = strConn.Replace("[UserName]", userName);
                strConn = strConn.Replace("[Password]", password);
                connSetting.ConnectionString = strConn;
            } 
        }
        //Method to update the endpoints to your web.config:
        private static void UpdateEndPoint(string serviceUrl1, string serviceUrl2, Configuration config)
        {
            ClientSection clientSection = config.GetSection("system.serviceModel/client") as ClientSection;
            Uri uriOutput;
            foreach (ChannelEndpointElement endpoint in clientSection.Endpoints)
            {
                switch (endpoint.Name)
                {
                    case "BasicHttpBinding_IService1":
                        {
                            if (Uri.TryCreate(serviceUrl1, UriKind.RelativeOrAbsolute, out uriOutput))
                                endpoint.Address = uriOutput;

                        }
                        break;
                    case "BasicHttpBinding_IService11":
                        {
                            if (Uri.TryCreate(serviceUrl2, UriKind.RelativeOrAbsolute, out uriOutput))
                                endpoint.Address = uriOutput;

                        }
                        break;
                }
            }
        }
    }
}
That's it for class library.
Go WebAppSetup project and add Project Output by right click on project > Add > Project Output.


In the Add Project Output Group dialog box, select Primary output and Content Files for the WebApp project as below:

Go File System Editor by right click on msi project > View > File System.
In the File System Editor, select the Web Application Folder. On the Action menu, click Add, and then click Project Output as follow:
  

In the Add Project Output Group dialog box, select Primary output for the UpdateWebconfig project as below:

Now, we create custom UI dialog for accepting user input such as db connection info and WCF url. Go User Interface Editor by right click on msi project > View > User Interface.

In the User Interface Editor, select Start node under Install. On the Action menu, choose Add Dialog.
In the Add Dialog dialog box, select the Textboxes (A) dialog, then click OK.
On the Action menu, choose Move Up. Repeat until the Textboxes (A) dialog is above the Installation Folder node and changes its Properties as below:
See Database Connection Dialog in wizard step
For Textboxes (B), do the same way like above setps.
See WCF Information Dialog in wizard step

Go Custom Actions Editor by right click on msi project > View > Custom Actions.
There are four folders named Install, Commit, Rollback, Uninstall. We need to add custom action for Install folder. Right click on Install folder, select Add Custom Action as below:

In Select Item in Project dialog, Click Web Application Folder to get in. Select Primary output from UpdateWebconfig (Active) and click OK.

You will see Primary output from UpdateWebconfig (Active) section under the Install folder and change CustomActionData property to the following string:
/targetdir="[TARGETDIR]\" /targetvdir="[TARGETVDIR]" /targetsite="[TARGETSITE]" /serverName="[SERVERNAME]" /databaseName="[DBNAME]" /userName="[USERNAME]" /password="[PASSWORD]" /serviceUrl1="[WCF1]" /serviceUrl2="[WCF2]" 

Now, you have finished Web Setup Project and build it. To test it, we can right-click on the web setup project within the solution explorer and select the “Install” menu and follow by wizard as below:


Database Connection Dialog

WCF Information Dialog



Note : If your project is Web Site, this Web Setup Project install the web application on target server including source files (.cs files). If you may want to just deploy your pre-compiled application to the server, you need to create Web Deployment Project for MSI installer package. I hope this article is useful for this case.

Sunday, October 21, 2012

Creating and Restoring SQL Server 2008 Database in Setup project

Windows Installer deployment allows you to create installer packages to be distributed to users; the user runs the setup file and steps through a wizard to install the application. This is done by adding a Setup project to your solution; when built, it creates a setup file that you distribute to users; the user runs the setup file and steps through a wizard to install the application.
There are five types of deployment projects: Merge Module Project, Setup Project, Web Setup Project, and Cab Project. The Setup Wizard is provided to step you through the process of creating deployment projects.This step-by-step article explains how to create a setup package in the Visual Studio .NET development environment for creating database on target server.

I assume that you have one solution project and "Northwind" database backup file already.

First, create a new setup project
  1. On the File menu, point to Add Project, and then click New Project.
  2. In the resulting Add New Project dialog box, select the Setup and Deployment Projects folder.
  3. Choose Setup Project for a standard setup as below:

Second, create an installer class for custom action
  1. On the File menu, click New Project.
  2. In the New Project dialog box, select Visual C# Projects in the Project Type pane, and then choose Class Library in the Templates pane. In the Name box, type CreatingDB.
  3. On the Project menu, click Add New Item.
  4. In the Add New Item dialog box, choose Installer Class. In the Name box, type Installer1.cs.
In Installer1.cs, it needs Microsoft.SqlServer.Management.Smo namespace contains classes that represent the core SQL Server Database Engine objects that include instances, databases, tables, stored procedures, and views. You will have to import the following four files to access all of the classes in the Microsoft.SqlServer.Management.Smo namespace.
  •     Microsoft.SqlServer.ConnectionInfo
  •     Microsoft.SqlServer.Management.Sdk.Sfc
  •     Microsoft.SqlServer.Smo
  •     Microsoft.SqlServer.SmoExtended
You can find these .dll files at C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies location.
Create one folder "DLL" in "CreatingDB" class library and copy the above four dll files. Then add these assemblies to your project as reference as well as System.Windows.Forms as shown below:

Develop the "Installer1.cs" as show below:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Data.SqlClient;
using System.IO;
using System.Security.AccessControl;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System.Collections.Specialized;

[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
    public Installer1()
    {
        InitializeComponent();
    }

    public void RestoreDatabase(String databaseName, String backupFilePath, String serverName,
        String userName, String password, String dataFilePath, String dbLogicalName)
    {
        // Create Restore instance
        Restore sqlRestore = new Restore();
        // Point to database
        BackupDeviceItem deviceItem = new BackupDeviceItem(backupFilePath, DeviceType.File);
        sqlRestore.Devices.Add(deviceItem);
        sqlRestore.Database = databaseName;
        // Connect to DB Server
        ServerConnection connection;
        if (userName == "") // for Windows Authentication
        {
            SqlConnection sqlCon = new SqlConnection(@"Data Source=" + serverName + @"; Integrated Security=True;");
            connection = new ServerConnection(sqlCon);
        }
        else // for Server Authentication
            connection = new ServerConnection(serverName, userName, password);
        // Restoring
        Server sqlServer = new Server(connection);
        sqlRestore.Action = RestoreActionType.Database;
        String dataFileLocation = dataFilePath + databaseName + ".mdf";
        String logFileLocation = dataFilePath + databaseName + "_Log.ldf";
        sqlRestore.RelocateFiles.Add(new RelocateFile(dbLogicalName, dataFileLocation));
        sqlRestore.RelocateFiles.Add(new RelocateFile(dbLogicalName + "_log", logFileLocation));
        sqlRestore.ReplaceDatabase = true;
        sqlRestore.PercentCompleteNotification = 10;
        try
        {
            sqlRestore.SqlRestore(sqlServer);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.InnerException.ToString());
        }
        //it dont need to attach when logical name and file name is the same ,and file location is MS SQL Server Data filepath.
        AttachDatabase(databaseName, connection, dataFileLocation, logFileLocation);
        Database db = sqlServer.Databases[databaseName];
        db.SetOnline();
        sqlServer.Refresh();
    }

    public void AttachDatabase(String databaseName, ServerConnection connection, 
        String dataFileLocation, string logFileLocation)
    {
        Server SqlServer = new Server(connection);
        StringCollection DatabaseFilesCollection = new StringCollection();
        DatabaseFilesCollection.Add(dataFileLocation);
        DatabaseFilesCollection.Add(logFileLocation);
        try
        {
            SqlServer.AttachDatabase(databaseName, DatabaseFilesCollection);
        }
        catch (Microsoft.SqlServer.Management.Smo.SmoException ex)
        {
            //it throw error when logical name and physical file name is the same,
            //and they are in default MS SQL Server Data file path.
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.InnerException.ToString());
        }
    }

    public override void Commit(System.Collections.IDictionary savedState)
    {
        // Required permission
        try
        {
            DirectorySecurity dirSec = Directory.GetAccessControl(Context.Parameters["TargetDir"]);
            FileSystemAccessRule fsar = new FileSystemAccessRule
            (@"NT AUTHORITY\NETWORK SERVICE"
            , FileSystemRights.FullControl
            , InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
            , PropagationFlags.None
            , AccessControlType.Allow);
            dirSec.AddAccessRule(fsar);
            Directory.SetAccessControl(Context.Parameters["TargetDir"], dirSec);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        // Parameters that comes from setup project (CreatingDBSetup) 
        RestoreDatabase(Context.Parameters["databaseName"].ToString(), Context.Parameters["backupFilePath"].ToString(), 
            Context.Parameters["serverName"].ToString(), Context.Parameters["userName"].ToString(), Context.Parameters["password"].ToString(), Context.Parameters
        ["dataFilePath"].ToString(), Context.Parameters["dbLogicalName"].ToString());
        
        base.Commit(savedState);
    }
}
That's it for class library. Build it. Now, it need to use above created class library in "CreatingDBSetup" msi.
Go File System Editor by right click on msi project > View > File System.
In the File System Editor, select the Application Folder. On the Action menu, click Add, and then click Project Output as follow:

In the Add Project Output Group dialog box, select Primary output for the CreatingDB project as below:

Required dependencies are loaded automatically as you see in the below picture. Now, we should add database backup file. Right click on empty area in panel, select Add - File.

In Add Files dialog, select backup file "Northwind" and click Open.

Now, we create custom installation dialog for accepting user input such as server name and db connection info. Go User Interface Editor by right click on msi project > View > User Interface.

In the User Interface Editor, select Start node under Install. On the Action menu, choose Add Dialog.
In the Add Dialog dialog box, select the Textboxes (A) dialog, then click OK.
On the Action menu, choose Move Up. Repeat until the Textboxes (A) dialog is above the Installation Folder node and changes its Properties as below:
See Server Information Dialog for ouput
For Textboxes (B), do the same way like above setps.

See Database Connection Dialog for output

Go Custom Actions Editor by right click on msi project > View > Custom Actions.
There are four folders named Install, Commit, Rollback, Uninstall. We need to add custom action for each folder. Right click on Install folder, select Add Custom Action as below:

In Select Item in Project dialog, Click Application Folder to get in. Select Primary output from CreatingDB (Active) and click OK. Do the same steps for other folder.

You will see Primary output from CreatingDB (Active) section under the Install and other folders as shown below image. Click each section and change CustomActionData property to the following string:
/TargetDir="[TARGETDIR]\" /databaseName="[DBNAME]" /backupFilePath="[TARGETDIR]Northwind.bak" /serverName="[SERVERNAME]" /userName="[USERNAME]" /password="[PASSWORD]" /dataFilePath="[DBLOC]\\" /dbLogicalName="Northwind"

Now, you finished developing Setup Project and Build and Install it. You will see the following wizards step by step.

Server Information Dialog
Database Connecton Dialog




Reference Article is here.

Sunday, September 30, 2012

How to save web site configuration data in Xml file instead of web.config.

We often use web.config file to keep the site configuration data. In this case, there is draw back since it need to restart the application when we change web.config file everytimes, and it don't affect the current running transaction. There is a simple way to solve it out that is XML file to save web site configuration data when we don't want to use Database for that. Perhaps we should consider what would happen if we use XML file for sensitive data concerned with security risk. Anyway, let's start here.
First, create xml file "site-config.xml" in "App_Data" folder as below:
<?xml version="1.0"?>
<SiteSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SiteName>Aspmemo.net</SiteName>
  <SiteVersion>1.0</SiteVersion>
  <SiteEmailAddress>sithuwin@aspmemo.net</SiteEmailAddress>
</SiteSettings>
Second, create "SiteSettings.cs" as follows:
using System.IO;
using System.Text;
using System.Xml.Serialization;

public class SiteSettings
{
    private const string XmlConfigFile = "~/App_Data/site-config.xml";
    private string _siteName;
    private string _siteVersion;
    private string _siteEmail;

    public string SiteName
    {
        get
        {
            return _siteName;
        }
        set
        {
            lock (this)
            {
                _siteName = value;
            }
        }
    }
    public string SiteVersion
    {
        get
        {
            return _siteVersion;
        }
        set
        {
            lock (this)
            {
                _siteVersion = value;
            }
        }
    }
    public string SiteEmailAddress
    {
        get
        {
            return _siteEmail;
        }
        set
        {
            lock (this)
            {
                _siteEmail = value;
            }
        }
    }
    public string SiteEmailFromField
    {
        get
        {
            return String.Format("{0} <{1}>", _siteName, _siteEmail);
        }
    }
    public static SiteSettings LoadFromConfiguration()
    {
        SiteSettings s = LoadFromXml();

        if (s == null)
        {
            s = new SiteSettings();
            //s.StorePhotosInDatabase = false;
            //s.ServerPhotoUploadDirectory = "Upload";
            s.SiteName = "Aspmemo";
            s.SiteVersion = "1.0";
            s.SiteEmailAddress = "sithuwin@aspmemo.net";
            SaveToXml(s);

        }
        return s;
    }
    public static SiteSettings GetSharedSettings()
    {
        return SiteHttpApplication.SiteApplicationSettings;
    }
    public static bool UpdateSettings(SiteSettings newSettings)
    {
        // write settings to code or db
        // update Application-wide settings, only over-writing settings that users should edit
        lock (SiteHttpApplication.SiteApplicationSettings)
        {
            // Site Name
            SiteHttpApplication.SiteApplicationSettings.SiteName = newSettings.SiteName;
            // Site Version
            SiteHttpApplication.SiteApplicationSettings.SiteVersion = newSettings.SiteVersion;
            // Contact Email Address for Site
            SiteHttpApplication.SiteApplicationSettings.SiteEmailAddress = newSettings.SiteEmailAddress;
            // Serialize to Xml Config File
            return SaveToXml(SiteHttpApplication.SiteApplicationSettings);
        }
    }
    private static SiteSettings LoadFromXml()
    {
        SiteSettings settings = null;
        HttpContext context = HttpContext.Current;
        if (context != null)
        {
            string configPath = context.Server.MapPath(XmlConfigFile);
            XmlSerializer xml = null;
            FileStream fs = null;
            bool success = false;
            int numAttempts = 0;

            while (!success && numAttempts < 2)
            {
                try
                {
                    numAttempts++;
                    xml = new XmlSerializer(typeof(SiteSettings));
                    fs = new FileStream(configPath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                    settings = xml.Deserialize(fs) as SiteSettings;
                    success = true;
                }
                catch (Exception x)
                {
                    // if an exception is thrown, there might have been a sharing violation;
                    // we wait and try again (max: two attempts)
                    success = false;
                    System.Threading.Thread.Sleep(1000);
                    if (numAttempts == 2)
                        throw new Exception("The Site Configuration could not be loaded.", x);
                }
            }
            if (fs != null)
                fs.Close();
        }
        return settings;
    }
    public string GetXml()
    {
        StringBuilder result = new StringBuilder();
        StringWriter s = new StringWriter(result);
        try
        {
            XmlSerializer xml = new XmlSerializer(typeof(SiteSettings));
            xml.Serialize(s, this);
        }
        finally
        {
            s.Close();
        }
        return result.ToString();
    }
    private static bool SaveToXml(SiteSettings settings)
    {
        if (settings == null)
            return false;
        HttpContext context = HttpContext.Current;
        if (context == null)
            return false;

        string configPath = context.Server.MapPath(XmlConfigFile);
        XmlSerializer xml = null;
        System.IO.FileStream fs = null;
        bool success = false;
        int numAttempts = 0;

        while (!success && numAttempts < 2)
        {
            try
            {
                numAttempts++;
                xml = new XmlSerializer(typeof(SiteSettings));
                fs = new FileStream(configPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
                xml.Serialize(fs, settings);
                success = true;
            }
            catch
            {
                // if an exception is thrown, there might have been a sharing violation;
                // we wait and try again (max: two attempts)
                success = false;
                System.Threading.Thread.Sleep(1000);
            }
        }
        if (fs != null)
            fs.Close();
        return success;
    }
}
Third, create "SiteHttpApplication.cs" as the custom base class for applications:
public class SiteHttpApplication : HttpApplication
{
 private static object _settingsLock = new object();
 private static SiteSettings _settings;

 public static SiteSettings SiteApplicationSettings
 {
  get
  {
   if (_settings == null)
    SiteApplicationSettings = SiteSettings.LoadFromConfiguration();
   return _settings;
  }
  set
  {
   if (value == null)
    throw new ArgumentNullException("SiteApplicationSettings cannot be set to null");
   lock (_settingsLock)
   {
    _settings = value;
   }
  }
 }
 public void Application_Start(Object sender, EventArgs e)
 {
  // set-up Settings
  SiteHttpApplication.SiteApplicationSettings = SiteSettings.LoadFromConfiguration();
 }
}
Then, create our "SiteHttpApplication" object in "Global.asax" file.
void Application_Start(object sender, EventArgs e)
{
 // Code that runs on application startup
 SiteHttpApplication siteHttp = new SiteHttpApplication();
 siteHttp.Application_Start(sender, e);
}
Finally, create UI for accessing the xml data as below:
<form id="form1" runat="server">
<div>
    <asp:Panel ID="UpdateErrorPanel" runat="server" Visible="False" EnableViewState="False">
        <p>
            <strong>There was an error writing to the Settings file<br />
                App_Data\site-config.xml.</strong><br />
            Please make sure that the ASP.NET process has write-access to the file.</p>
        <p>
            The textbox below contains the XML equivalent of the Site Settings you saved. You
            can copy it and update the file manually.</p>
        <asp:TextBox ID="SettingsXmlTextBox" runat="server" TextMode="multiLine" Rows="10"
            Width="100%"></asp:TextBox>
    </asp:Panel>
    <fieldset>
        <asp:FormView ID="SettingsFormView" runat="server" DataSourceID="SettingsDataSource"
            DefaultMode="Edit">
            <EditItemTemplate>
                SiteName:
                <asp:TextBox ID="SiteNameTextBox" runat="server" Text='<%# Bind("SiteName") %>' />
                <br />
                SiteVersion:
                <asp:TextBox ID="SiteVersionTextBox" runat="server" Text='<%# Bind("SiteVersion") %>' />
                <br />
                SiteEmailAddress:
                <asp:TextBox ID="SiteEmailAddressTextBox" runat="server" Text='<%# Bind("SiteEmailAddress") %>' />
                <br />
                <br />
                <asp:Button ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
                    Text="Update" />
                &nbsp;<asp:Button ID="UpdateCancelButton" runat="server" CausesValidation="False"
                    CommandName="Cancel" Text="Cancel" />
            </EditItemTemplate>
        </asp:FormView>
        <asp:ObjectDataSource ID="SettingsDataSource" runat="server" TypeName="SiteSettings"
            SelectMethod="GetSharedSettings" UpdateMethod="UpdateSettings" OnUpdated="SettingsDataSource_Updated"
            DataObjectTypeName="SiteSettings"></asp:ObjectDataSource>
    </fieldset>
</div>
</form>
UI will appear as below:
In code-behind, it need to handle the unsuccessful action in OnUpdated event of ObjectDataSource.
protected void SettingsDataSource_Updated(object sender, ObjectDataSourceStatusEventArgs e)
{
      try
      {
            // the UpdateSettings methods returns a boolean success value
            bool updateSuccess = false;
            if (e.ReturnValue != null && e.ReturnValue is bool)
                updateSuccess = (bool)e.ReturnValue;

            if (!updateSuccess)
            {
                 // we failed to save the settings to the settings file
                 // but we can output its Xml equivalent for manual saving:
                 SiteSettings s = SiteSettings.GetSharedSettings();
                 SettingsXmlTextBox.Text = s.GetXml();
                 UpdateErrorPanel.Visible = true;
            }
       }
       catch (Exception ex)
       {
                
       }
}
That's it. Run the application and see the result. Right now, you can access the site configuration data on the fly and can update immediately.


If you got error such as "The type [Class] is ambiguous.", Please see here.

Saturday, September 15, 2012

How to read image properties (Metadata) in asp.net

Some image files contain metadata that you can read to determine features of the image. For example, a digital photograph might contain metadata that you can read to determine the make, model of the camera used to capture the image and Date taken. With GDI+, you can read existing metadata, and you can also write new metadata to image files. This tutorial show you how to take the image date taken in asp.net.
Image Property Date Taken
 Copy the following server control to <form> tag.
 <asp:Label ID="label1" runat="server" Text =""></asp:Label>
In code-behind, look like as below
protected void Page_Load(object sender, EventArgs e)
{
    string path = @"G:\test.jpg"; //your image physical path here
    label1.Text = TakenDate(System.Drawing.Image.FromFile(path)).ToString();

}
public DateTime TakenDate(System.Drawing.Image img)
{
    DateTime dt = DateTime.MinValue;
    try
    {
        int DateTakenValue = 0x9003; // 36867
        if (img != null && img.PropertyIdList.Contains(DateTakenValue))
        {
            string dateTakenTag = System.Text.Encoding.UTF8.GetString(img.GetPropertyItem(DateTakenValue).Value);
            string[] parts = dateTakenTag.Split(':', ' ');
            int year = int.Parse(parts[0]);
            int month = int.Parse(parts[1]);
            int day = int.Parse(parts[2]);
            int hour = int.Parse(parts[3]);
            int minute = int.Parse(parts[4]);
            int second = int.Parse(parts[5]);
            dt = new DateTime(year, month, day, hour, minute, second);
        }
    }
    catch (Exception ex)
    {
    }
    return dt;
}
That's it. Run the application and see the image-date-taken in page.
More detail-how to read Image Metadata

Sunday, September 2, 2012

How to show Confirm Navigation using onbeforeunload event in javascript


I think, you have an experience as if you see "Confirm Navigation" popup when you close Browser. Let's say, when you clicks other link or close browser in Facebook before pressing "Post" button during post something, you will get the following confirm dialog.
Confirm Navigation in FB
This example sohow you how to use the onbeforeunload event to ask users whether they want to remain on the current document or refresh the page again. When the user press F5 or attempts to close the window, the onbeforeunload event fires on the body and a dialog box displays. If the user chooses OK, the document refresh again or closes the window; if the user chooses Cancel, the document remains the same.
Copy the following script to <head> tag.
<script type="text/javascript">
document.onkeydown = getKeyCode;
var keyCode = 0;
window.onbeforeunload = confirmExit;
function confirmExit() {
    // F5 is 116.
    if (keyCode == 116) 
    {
        keyCode = 0;
        // For F5
        return "If you have made any changes to the fields without clicking the Save button, " +
        "Your changes will be lost. Are you sure you want to exit this page?";
    }
    else
    {
        // For close browser
        return "You have attempted to leave this page." +
        "Are you sure you want to exit this page?";
    }
}
function getKeyCode(e) {
    if (window.event) {
        e = window.event;
        keyCode = e.keyCode;
    }
    else {
        keyCode = e.which;
    }
}
</script> 
That's it. When you close the browser or press F5, it show the "Confirm Navigation" popup with the different message. Now, it don't work in IE 7. If you know the root cause, please drop a line. Thank!

Saturday, August 4, 2012

Using Extension methods in Asp.Net 3.0 and higher .net framework

Since the dawn of asp.net, web based development has become a lot easier. It provides a great deal of control over designs and code. Let's say, one of them is Extension methods. It make it easy to add functionality to an existing type using a natural syntax. Also, since the extension methods appear in Visual Studio's IntelliSense drop-down list, they are easier to find and use than wrapper class equivalents. In this article, I show you how to create extension methods in asp.net.

Extension Methods in ASP.NET

At first, we need to create one class as below.
//Extensions.cs
namespace System
{
    public static class Extensions
    {
        public static int? ToNullInt(this string value)
        {
            int result;
            if (int.TryParse(value, out result))
            {
                return result;
            }
            return null;
        }
        public static int ToIntOrDefaultInt(this string value, int result = 0)
        {
            int.TryParse(value, out result);
            return result;
        }
        public static bool? ToNullBool(this string value)
        {
            bool result;
            if (bool.TryParse(value, out result))
            {
                return result;
            }
            return null;
        }
        public static bool ToBoolOrDefaultBool(this string value, bool result = false)
        {
            bool.TryParse(value, out result);
            return result;
        }
        public static string ToStringFormat(this int value)
        {
            return value.ToString("#,##0");
        }
        public static string ToStringFormat(this double value)
        {
            return value.ToString("#,##0.00");
        }
    }
}
we need an extension method to mark the function as static so that it can be accessed at any time without declaring object and secondly, mark the first parameter with the "this" keyword. This keyword basically tells the CLR that when this extension method is called, to use "this" parameter as the source.

Copy the following code to page load event in code-behind for using extension methods we created above.
string strVal = "12345";
int? nullableIntVal = strVal.ToNullInt();
//return 12345

int intVal = strVal.ToIntOrDefaultInt();
//return 12345

string blnVal = "True";
string blnVal2 = "Yes"; // can not parse
string blnVal3 = "1"; // can not parse
bool? nullableBool = blnVal.ToNullBool();
//return True

bool? nullableBool2 = blnVal2.ToNullBool();
//return Null since can not parse

bool? nullableBool3 = blnVal3.ToNullBool();
//return Null since can not parse

bool bln = blnVal.ToBoolOrDefaultBool();
//return True

bool bln2 = blnVal2.ToBoolOrDefaultBool();
//return False since can not parse

bool bln3 = blnVal3.ToBoolOrDefaultBool();
//return False since can not parse

string strIntFormat = intVal.ToStringFormat();
//return 12,345

double dblVal = 12345.67;
string strDblFormat = dblVal.ToStringFormat();
//return 12,345.67 
Now, run it again! I hope you guys those who are new to extension methods will able to write more better and reusable codes but I can not test it in Microsoft Visual Web Developer 2010 Express. Please drop a line if you know why. Thank.

Thursday, August 2, 2012

HTML noscript tag for javascript disabled browser

We often use javascript for dynamic web site and javascript is getting critical in most web application. So,   we also need to protect from malfunction for browsers that do not support client-side scripts. In this post, I introduce you html <noscript> tag here.
The <noscript> tag is used to provide an alternate content for users that have disabled scripts in their browser or have a browser that doesn’t support client-side scripting.The <noscript> element can contain all the elements that you can find inside the <body> element of a normal HTML page.The content inside the <noscript> element will only be displayed if scripts are not supported, or are disabled in the user’s browser. You can insert <noscript> tag to <head> tag or <body> tag.
Put the following script to <head> tag and disable javascript and then run and see it.
<script type="text/javascript">
        document.write("Hello World!")
</script>
<noscript>
    Please active javascript on your browesr.
</noscript>


Sunday, July 22, 2012

How to show Modal Dialog Box with JQueryUI API in Asp.net Web Form

I used JQuery a lot thesedays for user interactive web pages and then I start using JQueryUI for Dialog box in web form. I realize that It is simpler and more effective than I expected. This post explain you how to create Modal Dialog with JQueryUI in asp.net web form.
A dialog is a floating window that contains a title bar and a content area. The dialog window can be moved, resized and closed with the 'x' icon by default.
If the content length exceeds the maximum height, a scrollbar will automatically appear.

JQueryui Dialog Box in ASP.Net Web Form

First you need to download the JQuery UI API here and copy them to your project folder. After that, copy and paste the following code to <head> tag.
<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.21.custom.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.21.custom.min.js"></script>
<script type="text/javascript">
    $(function () {
        // Dialog
        $('#dialog').dialog({
            autoOpen: false,
            width: 500,
            closeOnEscape: true,
            resizable: false,
            draggable: true,
            modal: true,
            title: "Customer Details"
        });

        // Dialog Link
        $('#btnEditText').click(function () {
            $('#dialog').dialog('open');
            $('#dialog').parent().appendTo($('form:first'));
            return false;
        });

        $('#editBox_Cancel').click(function () {
            $('#dialog').dialog('close');
            return false;
        });
    });
</script>
Create the following control in <form> tag. There are tow sessions (two div) for displaying customer information. One is main content and other is for editing.
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
    <!--Using Partial Rendering to Update the Customer View -->
    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
        <ContentTemplate>
            <table>
                <tr>
                    <td>
                        <b>Customer ID:</b>
                    </td>
                    <td>
                        <asp:Label runat="server" ID="lblCustomerID" Text="C00001" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Company Name:</b>
                    </td>
                    <td>
                        <asp:Label runat="server" ID="lblCompanyName" Text="Eastern Connection" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Contact Name:</b>
                    </td>
                    <td>
                        <asp:Label runat="server" ID="lblContactName" Text="Ann Devon" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Country:</b>
                    </td>
                    <td>
                        <asp:Label runat="server" ID="lblCountry" Text="Germany" />
                    </td>
                </tr>
            </table>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="editBox_OK" />
        </Triggers>
    </asp:UpdatePanel>
    <asp:Button runat="server" ID="btnEditText" Text="Edit text" />
</div>
<div id="dialog">
    <!-- Dialog box:: Edit customer info -->
    <asp:UpdatePanel runat="server" ID="ModalPanel1" RenderMode="Inline" UpdateMode="Conditional">
        <ContentTemplate>
            <table>
                <tr>
                    <td>
                        <b>Customer ID:</b>
                    </td>
                    <td>
                        <asp:Label runat="server" ID="editCustomerID" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Company Name:</b>
                    </td>
                    <td>
                        <asp:TextBox runat="server" ID="editTxtCompanyName" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Contact Name:</b>
                    </td>
                    <td>
                        <asp:TextBox runat="server" ID="editTxtContactName" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <b>Country:</b>
                    </td>
                    <td>
                        <asp:TextBox runat="server" ID="editTxtCountry" />
                    </td>
                </tr>
            </table>
            <hr />
            <asp:Button ID="btnApply" runat="server" Text="Apply" OnClick="btnApply_Click" />
        </ContentTemplate>
    </asp:UpdatePanel>
    <asp:Button ID="editBox_OK" runat="server" Text="OK" OnClick="editBox_OK_Click" />
    <asp:Button ID="editBox_Cancel" runat="server" Text="Cancel" />
</div>
In code-behind, the coding is as below.
protected void InitDialog()
{
    editCustomerID.Text = lblCustomerID.Text;
    editTxtCompanyName.Text = lblCompanyName.Text;
    editTxtContactName.Text = lblContactName.Text;
    editTxtCountry.Text = lblCountry.Text;
    SetFocus("editTxtCompanyName");
}
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        InitDialog();
    }
}
protected void editBox_OK_Click(object sender, EventArgs e)
{
    // Save to the database
    // Refresh the UI
    lblCompanyName.Text = editTxtCompanyName.Text;
    lblContactName.Text = editTxtContactName.Text;
    lblCountry.Text = editTxtCountry.Text;
}
protected void btnApply_Click(object sender, EventArgs e)
{
    if (editTxtCountry.Text == "Germany")
        editTxtCountry.Text = "Cuba";
    else
        editTxtCountry.Text = "USA";
}
The jQuery UI API provides us simple and advance effects that you can use to create highly interactive web applications. Like other jQuery UI effects, jQuery UI Dialog is easy to use. Using it on the right way to help it be more flexible and scalability. You can see other post(How to show Modal Dialog Box with ASP.Net Ajax) I wrote before. Thank.

More Details

Other Nice Post