Sunday, July 21, 2013

How to create and read Xml in asp.net

We often have to deal with Xml message when our applications are integrated with SMS Api, Email Api or Payment Api. At that time, we prepare Xml message and feed the services. Likewise, it gets the Xml message from the service of API and extracts the message from Xml message for on-going process. This post explain step by step how to create Xml message and read the message from Xml elements.

First, copy and paste the following Xml message to new file "XmlMessage.xml" in "App_Data" folder in your project. You see "[xxxxxxx]" and it is place holder for data we put.
<?xml version="1.0" encoding="utf-8" ?>
<paymentService version="1.4" merchantCode="[merchantCode]">
  <reply>
    <orderStatus orderCode="[orderCode]">
      <payment>
        <paymentMethod>[paymentMethod]</paymentMethod>
        <amount value="[value]" currencyCode="[currencyCode]" exponent="[exponent]"/>
        <lastEvent>[lastEvent]</lastEvent>
        <CVCResultCode description="[CVCResultCode]"/>
        <ISO8583ReturnCode code="[ISO8583ReturnCode]" description="[ISO8583ReturnDescription]"/>
      </payment>
    </orderStatus>
  </reply>
</paymentService>
Second, we need to add Textbox server control to .aspx page as below:
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="txtXml" runat="server" Height="250px" Width="576px" 
            TextMode="MultiLine"></asp:TextBox>
    </div>
    </form>
</body>
Third, copy and paste the following code in code behind.
protected void Page_Load(object sender, EventArgs e)
{
    //Set the data here.
    string merchantCode = "MYMERCHANT";
    string orderCode = "T0211234";
    string paymentMethod = "ECMC-SSL";
    string value = "162095";
    string currencyCode = "GPB";
    string exponent = "2";
    string lastEvent = "REFUSED";
    string CVCResultCode = "NOT SUPPLIED BY SHOPPER";
    string ISO8583ReturnCode = "33";
    string ISO8583ReturnDescription = "CARD EXPIRED";

    string xmlMsg = GetXmlMessage();
    //Fill the data in place holder in Xml message.
    xmlMsg = xmlMsg.Replace("[merchantCode]", merchantCode);
    xmlMsg = xmlMsg.Replace("[orderCode]", orderCode);
    xmlMsg = xmlMsg.Replace("[paymentMethod]", paymentMethod);
    xmlMsg = xmlMsg.Replace("[value]", value);
    xmlMsg = xmlMsg.Replace("[currencyCode]", currencyCode);
    xmlMsg = xmlMsg.Replace("[exponent]", exponent);
    xmlMsg = xmlMsg.Replace("[lastEvent]", lastEvent);
    xmlMsg = xmlMsg.Replace("[CVCResultCode]", CVCResultCode);
    xmlMsg = xmlMsg.Replace("[ISO8583ReturnCode]", ISO8583ReturnCode);
    xmlMsg = xmlMsg.Replace("[ISO8583ReturnDescription]", ISO8583ReturnDescription);
    txtXml.Text = xmlMsg;
    ReadXmlMessage(xmlMsg);
}

public string GetXmlMessage()
{
    //Get Xml message from file.
    string XmlFile = "~/App_Data/XmlMessage.xml";
    StreamReader sr = new StreamReader(Server.MapPath(XmlFile));
    string str = sr.ReadToEnd();
    return str;
}

public void ReadXmlMessage(string xmlMsg)
{
    if (!string.IsNullOrEmpty(xmlMsg))
    {
        //Read the data from Xml elements.
        XmlDocument document = new XmlDocument();
        document.LoadXml(xmlMsg);
        string merchantCode = document.GetElementsByTagName("paymentService")[0].Attributes["merchantCode"].Value;
        string orderCode = document.GetElementsByTagName("orderStatus")[0].Attributes["orderCode"].Value;
        string paymentMethod = document.SelectSingleNode("//paymentMethod").InnerText;
        string value = document.GetElementsByTagName("amount")[0].Attributes["value"].Value;
        string currencyCode = document.GetElementsByTagName("amount")[0].Attributes["currencyCode"].Value;
        string exponent = document.GetElementsByTagName("amount")[0].Attributes["exponent"].Value;
        string lastEvent = document.SelectSingleNode("//lastEvent").InnerText;
        string CVCResultCode = document.GetElementsByTagName("CVCResultCode")[0].Attributes["description"].Value;
        string ISO8583ReturnCode = document.SelectSingleNode("//ISO8583ReturnCode").Attributes["code"].Value;
        string ISO8583ReturnDescription = document.SelectSingleNode("//ISO8583ReturnCode").Attributes["description"].Value;
    }
}
I use XmlNode.SelectSingleNode method to get xml data. It selects the first XmlNode that matches the XPath expression. The first XmlNode that matches the XPath query or null if no matching node is found.
I used aslo XmlDocument.GetElementsByTagName method to return an XmlNodeList containing a list of all descendant elements that match the specified Name. If no nodes match name, the returned collection will be empty.

Finally, run and see the result. It look like as below:

Sunday, May 5, 2013

How to use Pass-through authentication to Access Resources in different domain environment

Our web application often need to access local or network resources in production environment. For example, our application have to access file server for read/write access in different domain (not in a domain). In the above cases, we can use mirrored local accounts known as "Pass-through authentication". With this approach, you use two local accounts with the same user name and password on both servers (such as web server and file server). For network resources in the same domain, see previous post. Let's start here.

Step 1. Create a New User Account on Web Server

1. Click Start, select Administrative Tools and click Computer Management.
2. In Computer Management, click Local Users and Groups.
3. Double click the Users folder.
4. Right click in the users list and click New User.
5. Fill in the information for the new user (e.g. newacc) and click Create.


6. Make that account a member of the IIS_IUSRS group (In IIS 6, it is IIS_WPG group instead of IIS_IUSRS) as below:


Step 2. Create an Application Pool with a Custom Identity

1. Right click on Applicaton Pools node underneath the Machine node and Click Add Application Pool...
2. Type the name of new application pool (e.g. NewAppPool) on Add Application Pool dialog and press OK.


3. Select new application pool (NewAppPool) under Application Pools node and click Advanced Settings.


4. Advanced Settings dialog will appear and select the "Identity" list item and click the ellipsis (the button with the three dots).


5. Select Custom account option and press Set..


6. Type the new created account information (newacc) and press OK.


Step 3. Configure Your Application to Run in the New Application Pool

1. Go to IIS, click on your web application and click "Advanced Settings".
2. Click the ellipsis (the button with the three dots) on Application Pool item list.


3. Select the new application pool (NewAppPool) on Select Application Pool dialog and press OK.


Step 4. Create a New User Account on File Server

1. Create a local account with the same username and password as the one in Web Server (Step 1).

Step 5. Set permission of folder on File Server

1. Go to the given folder (e.g. FileShare) in File Server
2. Right click the folder and select "Properties"
3. Select the "Security" tab and click Edit


4. Click Add for new user account.


5. Type the created user account (newacc) and click Check Names and OK.


6. Set permission for that created local accout as below:


7. Click OK to finish.

By doing this, the file or directory you selected in file server will now allow the custom account  identity access from your web application in web farm.

Reference :
How To: Create a Service Account for an ASP.NET 2.0 Application
Understanding Built-In User and Group Accounts in IIS 7

Saturday, March 23, 2013

How to use Network Service Account to Access Resources in ASP.NET in the same domain

Our web application often need to access local or network resources in production environment. For example, our application have to access file server for read/write access in the same domain. In case, web application upload and save user account photo or document such as excel and word file. At that time, it need the Network Service Account that is least privileged, although it have network credentials which means that you can use it to authenticate against network servers.

By default, Microsoft Internet Information Services (IIS) 6.0 on Windows Server 2003 runs ASP.NET applications in application pools that use the NT AUTHORITY\Network Service account identity. This account is a least privileged machine account with limited permissions and an application that runs using this account has restricted access, network credentials, which means you can use it to access network resources and remote databases by using Windows authentication. The network resources must be in the same domain as your Web server or in a trusted domain. Normally, the Application Pool Identity in IIS7 is "ApplicationPoolIdentity" by default and in IIS5 or IIS6, is "NetworkService" by default. Let's start here, to use the NT AUTHORITY\Network Service machine account to access local and network resources in Web Farm.

1. Configuring IIS Application Pool Identities
First, we check what Application Pool our web application use as follow:


Go to IIS, click on your web application and click "Advanced Settings".


Now, you see your application use "DefaultAppPool" Application Pool. If you want to change it to another, click the ellipsis (the button with the three dots). The following dialog appears.


Select the Application Pool you want from the combo box and Press OK button. Now, we know already what Application pool we used. Then we change the Identity Type for Application Pool.
Go to IIS, select "Application Pool" node and then select Application Pool you want to change as shown below:


Click "Advanced Setttings" and you will see the following dialog box:


Now, Identity is "NetworkService" already. Otherwise, select the "Identity" list item and click the ellipsis (the button with the three dots). The following dialog appears.


Select the Identity Type "NetworkService" from the combo box and press OK button. So, we finished marking sure that our web application that run using "NetworkService" Application Pool Identity.

2. Securing Resources
Whenever a new Application Pool is created, the IIS management process creates a security identifier (SID) that represents the name of the Application Pool itself. For example, if you create an Application Pool with the name "MyNewAppPool," a security identifier with the name "MyNewAppPool" is created in the Windows Security system. From this point on, resources can be secured by using this identity. However, the identity is not a real user account; it will not show up as a user in the Windows User Management Console.
Let's start giving permission to folder in remote server here.

1. Open Windows Explorer
2. Select a file or directory.
3. Right click the file and select "Properties"
4. Select the "Security" tab
5. Click the "Edit" and then "Add" button



6. Click "Locatoins" and make sure you select your domain and then enter the Network Service account.


The Network Service account's credentials are of the form DomainName\AspNetServer$, where DomainName is the domain of the ASP.NET server and AspNetServer is your Web server name.For example, if your ASP.NET application runs on a server named SVR1 in the domain CONTOSO, the Network Service account is CONTOSO\SVR1$.

7. Click the "Check Names" button and click "OK".
8. Set permission for new account as below:


By doing this, the file or directory you selected in file server will now allow the Network Service identity access from your web application.

Reference :

How To: Use the Network Service Account to Access Resources in ASP.NET
Application Pool Identities

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.