Thursday, January 31, 2013

c# - Edit,Update Resource files in a Multilingual Site programmatically

There are a lot of third party content management tools available.(See here http://www.webdesignerdepot.com/2011/10/top-10-content-management-systems/ ).
Recently I have been tasked with a rewrite of some of my company's websites, that is used by millions of people.The old sites use xml,xslt for content management and multiple language support

One of the requirements was to provide the team that managed the content for the sites, the flexibility to edit the content on the fly for any of the language supported by the site. This would also reduce the need for developers to spend time editing content on the sites.

My first goal is to build a simple site with few content pages.I am using ASP.Net Localization feature for this sample.

Below is structure of the sample project that I have.The site has two content pages i.e. Home.aspx and About.aspx.The site will have the feature to display to the content in 3 different languages i.e German (de),Spanish (es) and English as default.I have added resource files for each page and each langauge
Home.aspx.resx (English),Home.aspx.de.resx(German),Home.aspx.es.resx(Spanish)
About.aspx.resx (English),About.aspx.de.resx(German),About.aspx.es.resx(Spanish)




The About.aspx.resx resource file is below.






In the next step I add a page that will allow to make the changes for the content in the resource files.I have added a page called Edit.aspx which will be available only for the team responsible for the content of the site.

The Edit.aspx page will list all the pages,languages supported in the site.Once the page,language is selected a dropdownlist will list all the resource keys. The user would then choose a resource key and on key selection the corresponding value(content) stored in the resource file will be shown in the RadEditor(Use a richtextbox to display the content).The save button will allow to rewrite the resource file.

Once the changes are made the content changes can be viewed Home,About pages.  


The source code for the Edit.aspx page is below

<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest="false" CodeBehind="Edit.aspx.cs" MasterPageFile="~/Site.Master" Inherits="Sample.SupportForm" %>

<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <table width="100%" style="table-layout:fixed">
        <tr>
            <td><telerik:RadScriptManager ID="RadScriptManager1" runat="server">
</telerik:RadScriptManager>
                <asp:DropDownList ID="PagesDropDownList" runat="server" Width="133px" AutoPostBack="true">
                    <asp:ListItem Text="Home" Value="Home"></asp:ListItem>
                    <asp:ListItem Text="About" Value="About"></asp:ListItem>
                </asp:DropDownList>
            </td>
        </tr>
        <tr>
            <td>
                <asp:DropDownList ID="LangaugesDropDownList" runat="server" Width="133px" 
                    AutoPostBack="true" 
                    onselectedindexchanged="LangaugesDropDownList_SelectedIndexChanged">
                    <asp:ListItem Text="English" Value=""></asp:ListItem>
                    <asp:ListItem Text="EspaƱol" Value="es"></asp:ListItem>
                    <asp:ListItem Text="Deutsch" Value="de"></asp:ListItem>
                </asp:DropDownList>
            </td>
        </tr>
        <tr>
                <td>
                    <asp:DropDownList ID="ResourceKeyDropDownList" runat="server" Visible="false" 
                        AutoPostBack="true" AppendDataBoundItems="true" Height="23px" 
                        onselectedindexchanged="ResourceKeyDropDownList_SelectedIndexChanged" 
                        Width="300px">
                    </asp:DropDownList>
                </td>
        </tr>
        <tr>
            <td>
                <telerik:RadEditor ID="ResourceValueEditor" runat="server" Width="100%" 
                    Visible="False"></telerik:RadEditor>
            </td>
        </tr>
        <tr>
            <td>
                <asp:Button ID="SaveButton" runat="server" Text="Save" Visible="false" 
                    onclick="SaveButton_Click" />
            </td>
        </tr>
    </table>
</asp:Content>


The code behind for Edit.aspx

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.Resources;
using System.Collections;

namespace Sample
{
    public partial class SupportForm : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                ResourceKeyDropDownList.Visible = true;
                ResourceKeyDropDownList.Items.Clear();
                ResourceKeyDropDownList.Items.Add(new ListItem("Select", "Select"));

                string sPage = PagesDropDownList.SelectedValue;
                string sLanguage = LangaugesDropDownList.SelectedValue;
                SortedList<string, string> oKeyValue = new SortedList<string, string>();

                string sPath = Request.PhysicalApplicationPath + @"App_LocalResources\" + sPage + (string.IsNullOrEmpty(sLanguage) ? ".aspx.resx" : (".aspx." + sLanguage + ".resx"));

                using (ResXResourceReader oReader = new ResXResourceReader(sPath))
                {
                    IDictionaryEnumerator oResource = oReader.GetEnumerator();
                    while (oResource.MoveNext())
                        ResourceKeyDropDownList.Items.Add(new ListItem(oResource.Key.ToString(), oResource.Key.ToString()));
                }
            }
        }

        protected void LangaugesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            ResourceKeyDropDownList.Visible = true;
            ResourceKeyDropDownList.Items.Clear();
            ResourceKeyDropDownList.Items.Add(new ListItem("Select", "Select"));

            string sPage = PagesDropDownList.SelectedValue;
            string sLanguage = LangaugesDropDownList.SelectedValue;
            SortedList<string,string> oKeyValue = new SortedList<string,string>();

            string sPath = Request.PhysicalApplicationPath + @"App_LocalResources\" + sPage + (string.IsNullOrEmpty(sLanguage) ? ".aspx.resx" : (".aspx." + sLanguage + ".resx"));
            
            using (ResXResourceReader oReader = new ResXResourceReader(sPath))
            {
                IDictionaryEnumerator oResource = oReader.GetEnumerator();
                while (oResource.MoveNext())
                    ResourceKeyDropDownList.Items.Add(new ListItem(oResource.Key.ToString(), oResource.Key.ToString()));
            }
        }

        protected void ResourceKeyDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            string sResourceKey = ResourceKeyDropDownList.SelectedValue;
            if (!(string.IsNullOrEmpty(sResourceKey) || sResourceKey == "Select"))
            {
                ResourceValueEditor.Visible = true;
                SaveButton.Visible = true;

                string sPage = PagesDropDownList.SelectedValue;
                string sLanguage = LangaugesDropDownList.SelectedValue;

                string sPath = Request.PhysicalApplicationPath + @"App_LocalResources\" + sPage + (string.IsNullOrEmpty(sLanguage) ? ".aspx.resx" : (".aspx." + sLanguage + ".resx"));

                using (ResXResourceReader oReader = new ResXResourceReader(sPath))
                {
                    IDictionaryEnumerator oResource = oReader.GetEnumerator();
                    while (oResource.MoveNext())
                    {
                        if (oResource.Key.ToString() == sResourceKey)
                        {
                            ResourceValueEditor.Content = oResource.Value.ToString();
                            break;
                        }
                    }
                }
            }
            else
            {
                ResourceValueEditor.Visible = false;
                SaveButton.Visible = false;
            }
        }

        protected void SaveButton_Click(object sender, EventArgs e)
        {
            string sResourceKey = ResourceKeyDropDownList.SelectedValue;
            string sPage = PagesDropDownList.SelectedValue;
            string sLanguage = LangaugesDropDownList.SelectedValue;
            
            Hashtable oHt = new Hashtable();

            string sPath = Request.PhysicalApplicationPath + @"App_LocalResources\" + sPage + (string.IsNullOrEmpty(sLanguage) ? ".aspx.resx" : (".aspx." + sLanguage + ".resx"));
             using (ResXResourceReader oReader = new ResXResourceReader(sPath))
                {
                    IDictionaryEnumerator oResource = oReader.GetEnumerator();
                    while (oResource.MoveNext())
                        oHt.Add(oResource.Key,oResource.Value);
                }

            oHt[sResourceKey] = ResourceValueEditor.Content;

            using (ResXResourceWriter oWriter = new ResXResourceWriter(sPath))
            {
               
                foreach (string key in oHt.Keys)
                    oWriter.AddResource(key.ToString(), oHt[key].ToString());
                oWriter.Generate();
            }
        }
    }
}





Tuesday, January 29, 2013

c# - check if two strings are anagrams

From Wikipedia (http://en.wikipedia.org/wiki/Anagram)
An anagram is a type of word play, the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once.

Program to check if two strings are anagrams are not


using System;

namespace StringAnagrams

{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Please enter the first string.");
                string sFirst = Console.ReadLine();
                Console.WriteLine("Please enter the second string.");
                string sSecond = Console.ReadLine();
                if (sFirst.Length == sSecond.Length)
                {
                    char[] cFirst = sFirst.ToLower().ToCharArray();
                    char[] cSecond = sSecond.ToLower().ToCharArray();

                    Array.Sort<char>(cFirst);

                    Array.Sort<char>(cSecond);

                    if ((new string(cFirst)).Equals((new string(cSecond))))

                        Console.WriteLine("Anagrams");
                    else
                        Console.WriteLine("Not Anagrams");
                }
                else
                    Console.WriteLine("Not Anagrams");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
    }
}

Output




Thursday, January 10, 2013

Windows Presentation Foundation #WPF - Coin Toss

Today at work,I could not find a coin to toss so decided to write a WPF program (Too lazy to search a site,download an app, find a penny on street to toss...)
This is a very basic Windows Presentation Foundation example.

Open Visual Studio 2010 -> Choose WPF Application -> Give it an appropriate name

















Click on the MainWindow.xaml file.Drag and Drop

  • Label - To display result
  • TextBoxes - Counters for toss
  • Button - Trigger toss event


The MainWindow.xaml looks like below

















Double click the button on MainWindow.xaml.cs and add the toss logic
I am generating a random number and dividing it by 2 to determine heads or tails.If the random number generated is even then its a Head else it is a Tail.


using System;
using System.Windows;
using System.Windows.Media;

namespace CoinToss

{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int iHCounter = 0;
        int iTCounter = 0;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)

        {
            Random oRandom = new Random();
            int iRandomNumber = oRandom.Next(0, 10000);
            if (iRandomNumber % 2 == 0)
            {
                iHCounter++;
                textBox1.Text = "H:" + iHCounter.ToString();
                label1.Content = "HEADS";
                label1.Background = Brushes.Red;
            }
            else
            {
                iTCounter++;
                textBox2.Text = "T:" + iTCounter.ToString();
                label1.Content = "TAILS";
                label1.Background = Brushes.Green;
            }
        }
    }
}

Compile the solution and run it.Click the Toss button to see the result.






Monday, January 7, 2013

Server SERVERNAME is not configured for RPC

I had a requirement where I had to read data from a table on a different database server.So I created linked server to the database server to read the data.However when I executed my query I started getting the error "Server XYZ is not configured for RPC". 
After checking the linked server options I noticed that the RPC is set to false by default.Setting RPC option to true fixed the issue.
Right Click on the linked server and choose Server Options.Set RPC,RPC OUT to true.