browse by category or date

In my previous post, I have discussed on how to enable language translation in your server-side Ext.NET control.

But this translation method will not run “on-the-fly”. You need to refresh your page to get the new language rendered in the screen. To make it “on-the-fly”, you need to do these steps:

  1. Add an Ext.NET Store in your View page. The Store will hold all the translation data. It will have two fields. The first field is the Key, which is your Ext.NET control’s ID. The second field is the Value, which is the translation result
  2. When user changed its language preference, set the selected language in a cookie and reload the Store.
  3. The Store will make a HttpRequest to the server. The server read the cookie, and returned a JSON Store object.
  4. Handle the Ext.NET Store’s Load event by iterating the Store’s records, and then use Ext.getCmp to get the affected Ext.NET controls and set their Text/Label property
  5. …..
  6. Profit!!! 🙂

You might ask, “Why we need to set the language preference to a Cookie?” It’s required because it will make the Server know and remember about the changes.

Alright, now that I’ve told you the general concept, time to get dirty (with Code, not bacteria).

So in your Controller, we’ll add a method that returns AjaxStoreResult. Its function is to retrieve the resource set based on the language code specified in the cookie:

using Ext.Net;
using Ext.Net.MVC;
using System.Globalization;
using System.Threading;

// ... Code Snip ...
	public AjaxStoreResult Translate()
	{
		var lang = Request.Cookies["language"].Value;
		CultureInfo cult = Thread.CurrentThread.CurrentCulture;
		
		try {
			cult = new CultureInfo(lang);
		}
		catch(Exception ex) {}
		
		var res = Resources.LocalizedText.ResourceManager.GetResourceSet(cult, true, false);
		var trav = res.GetEnumerator();
		var dict = new Dictionary();
		
		while (trav.MoveNext())
		{
			if (trav.Key.ToString().Length > 2)
				dict.Add(trav.Key.ToString(), trav.Value.ToString());
		}
		
		var q = from c in dict
				select new { key = c.Key, value = c.Value };
				
		return new AjaxStoreResult(q, dict.Count);
	}
// ... Code Snip ...

And here is the Ext.NET Store in your views:


         
        
            
            
        
        
            
                
                    
                    
                
            
        
        
            
        
    

And finally, the event handler to the Store’s Load event:

var TranslateLoaded = function (objGrid, gridRecords, objOptions) {
	for (var i = 0; i < gridRecords.length; i++) {		
		var cmp = Ext.getCmp(gridRecords[i].data.key);
		if (cmp) {
			//Different Ext.NET control might need 
			//different treatment.
			if (cmp instanceof Ext.form.ComboBox) {		
				cmp.setFieldLabel(gridRecords[i].data.value);
			} 
			else if (cmp instanceof Ext.form.TriggerField) {
				if (cmp.emptyText != '') {
					Ext.apply(cmp, {
							emptyText : gridRecords[i].data.value
						});
					cmp.reset();
				}
				if (cmp.fieldLabel != '')
					cmp.setFieldLabel(gridRecords[i].data.value);
			} 
			else if (cmp instanceof Ext.menu.Item) {
				var pnl = tpMain.find('title', cmp.text);
				if (pnl.length > 0) {
					pnl[0].setTitle(gridRecords[i].data.value);
					pnl[0].reload();
				}
				cmp.setText(gridRecords[i].data.value);
			} 
			else if (cmp instanceof Ext.form.Label
				 || cmp instanceof Ext.tree.TreeNode
				 || cmp instanceof Ext.data.Node) {
					cmp.setText(gridRecords[i].data.value);
			} 
			else if (cmp instanceof Ext.Panel 
				|| cmp instanceof Ext.Window)
					cmp.setTitle(gridRecords[i].data.value);
			else if (cmp instanceof Ext.form.TextField 
				|| cmp instanceof Ext.form.CompositeField)
					cmp.setFieldLabel(gridRecords[i].data.value);
			else if (cmp instanceof Ext.Button) {
				if (cmp.getText() != '' && cmp.getText() != undefined)
					cmp.setText(gridRecords[i].data.value);
			} else if (cmp instanceof Ext.form.DisplayField) {
				cmp.setValue(gridRecords[i].data.value);
			}
		}
	}	
} 

I hope it helps 😉 Cheers!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

I am recently created an .NET Application that needs to utilize a Procedure from Oracle database. The Stored Procedure has five parameters. The first two is input, one is integer output and the last two is ref cursor output. Roughly, the SP looks like this:

PACKAGE PKG_TEST_PACKAGE AS
	TYPE REF_CURSOR IS REF CURSOR;
	PROCEDURE SP_TEST_PROCEDURE(strInput1 IN VARCHAR2, 
            intInput2 IN INTEGER, intOutput1 OUT INTEGER, 
            recordSet1 OUT REF_CURSOR, 
            recordSet2 OUT REF_CURSOR);
END;

After much tinkering and searching Internet, I found out that there are at least three ways to do it.

1. Using ADO.NET

Since Microsoft has deprecated System.Data.OracleClient, this option might not be good for production release.

using System;
using System.Data;
using System.Data.OracleClient;

namespace TestOracle
{
    class Program
    {
        static void Main(string[] args)
        {
            var con = new OracleConnection();
            con.ConnectionString = @"Server=(
                    DESCRIPTION=(
                        ADDRESS_LIST=(
                            ADDRESS=(PROTOCOL=TCP)
                            (HOST=YOUR_ORACLE_HOST_NAME)
                            (PORT=1521)
                        )
                    )
                    (CONNECT_DATA = (SID = YOUR_ORACLE_SID)));
                    Uid=YOUR_USERNAME;
                    pwd=YOUR_PASSWORD;";
            con.Open();
            var cmd = con.CreateCommand();
            cmd.CommandText = "PKG_TEST_PACKAGE.SP_TEST_PROCEDURE";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new OracleParameter
            {
                ParameterName = "strInput1",
                Direction = ParameterDirection.Input,
                Value = "SOME_VALUE"
            });
            cmd.Parameters.Add(new OracleParameter
            {
                ParameterName = "intInput2",
                Direction = ParameterDirection.Input,
                Value = 1903
            });
            cmd.Parameters.Add(new OracleParameter
            {
                ParameterName = "intOutput1",
                Direction = ParameterDirection.Output,
                OracleType = OracleType.Int32
            });
            cmd.Parameters.Add(new OracleParameter
            {
                ParameterName = "recordSet1",
                Direction = ParameterDirection.Output,
                OracleType = OracleType.Cursor
            });
            cmd.Parameters.Add(new OracleParameter
            {
                ParameterName = "recordSet2",
                Direction = ParameterDirection.Output,
                OracleType = OracleType.Cursor
            });
            cmd.ExecuteNonQuery();

            int intOutput1 = (int)cmd.Parameters["intOutput1"].Value;
            var recordSet1 = new DataTable();
            recordSet1.Load((OracleDataReader)cmd.Parameters["recordSet1"].Value);

            var recordSet2 = new DataTable();
            recordSet2.Load((OracleDataReader)cmd.Parameters["recordSet2"].Value);

            con.Close();
        }
    }
}

2. Using ODP.NET

If you’re developing in 64-bit environment, you might need to specifically set the running environment to x86 to prevent issues. For the time being, I think developing in x64 doesn’t worth the hassle needed just to get your environment working correctly.
Oh and BEWARE of the difference of Connection String between ADO.NET and ODP.NET

using System;
using System.Data;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

namespace TestOracle
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var con = new OracleConnection();
                con.ConnectionString = @"Data Source=(
                    DESCRIPTION=(
                        ADDRESS_LIST=(
                            ADDRESS=(PROTOCOL=TCP)
                            (HOST=YOUR_ORACLE_HOST_NAME)
                            (PORT=1521)
                        )
                    )
                    (CONNECT_DATA = (SID = YOUR_ORACLE_SID)));
                    User Id=YOUR_USERNAME;
                    Password=YOUR_PASSWORD;";
                con.Open();
                var cmd = con.CreateCommand();
                cmd.CommandText = "PKG_TEST_PACKAGE.SP_TEST_PROCEDURE";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new OracleParameter
                {
                   ParameterName = "strInput1",
                   Direction = ParameterDirection.Input,
                   Value = "SOME_VALUE"
                });
                cmd.Parameters.Add(new OracleParameter
                {
                   ParameterName = "intInput2",
                   Direction = ParameterDirection.Input,
                   Value = 1903
                });
                cmd.Parameters.Add(new OracleParameter
                {
                   ParameterName = "intOutput1",
                   Direction = ParameterDirection.Output,
                   OracleDbType = OracleDbType.Int32
                });
                cmd.Parameters.Add(new OracleParameter
                {
                   ParameterName = "recordSet1",
                   Direction = ParameterDirection.Output,
                   OracleDbType = OracleDbType.RefCursor
                });
                cmd.Parameters.Add(new OracleParameter
                {
                   ParameterName = "recordSet2",
                   Direction = ParameterDirection.Output,
                   OracleDbType = OracleDbType.RefCursor
                });   
                
                cmd.ExecuteNonQuery();

                var recordSet1 = new DataTable();
                OracleRefCursor ref1 = (OracleRefCursor)cmd.Parameters["recordSet1"].Value;
                recordSet1.Load(ref1.GetDataReader());

                var recordSet2 = new DataTable();
                OracleRefCursor ref2 = (OracleRefCursor)cmd.Parameters["recordSet2"].Value;
                recordSet2.Load(ref2.GetDataReader());

                con.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

3. Using Enterprise Library

I found out about this when I was working with a project that utilizes Subsonic to connect Oracle. When you are using ORM, you will likely to interact with classes from System.Data.Common. This is a problem because you can’t specify the data-type of the SP parameter. Luckily, this article saved me from confusion by giving me the needed pointer.

using System;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data;
using System.Data.Common;

//..... Code Snipped
                //ORACLE_DB is connection string name found
                //in your App.config/web.config
                Database db = DatabaseFactory.CreateDatabase("ORACLE_DB");

                //Specify the number of SP's parameters
                object[] myParams = new object[5];
                
                //Database object will construct the reqired parameters
                DbCommand dbCmd = db.GetStoredProcCommand("PKG_TEST_PACKAGE.SP_TEST_PROCEDURE", myParams);
                db.SetParameterValue(dbCmd, "strInput1", "SOME_VALUE");
                db.SetParameterValue(dbCmd, "intInput2", 1903);

                //Tran is a transaction object, you can use this if 
                //you want to be part of a transaction, otherwise
                //you can remove this parameter
                db.ExecuteNonQuery(dbCmd, Tran);

                int intOutput1 = (int)dbCmd.Parameters["intOutput1"].Value;
                var recordSet1 = new DataTable();
                recordSet1.Load((DbDataReader)dbCmd.Parameters["recordSet1"].Value);

                var recordSet2 = new DataTable();
                recordSet2.Load((DbDataReader)dbCmd.Parameters["recordSet2"].Value);
//..... Code Snipped

I hope it helps 😉

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

My development PC is a Windows 7 64-bit with Visual Studio 2008 (yeah.. i’m lagging behind darn it 🙂 ). Most of the time, I need to write/debug application in 32-bit(x86) environment.

Occasionally, the debugging session will abruptly ended, leaving me just this window:

Apparently there was an exception happened, and that’s how the 32-bit debugger handles it. Sucks right?

So in order to get the Exception details, you just need to put one single try-catch to cover the whole application, and put a breakpoint inside the catch section.

By now, you should be able to get the exception details whenever you x86 debugging session abruptly ended.

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant: