Thursday, April 22, 2010

Encrypting values in web.config

Sometimes user requirements don't allow you to put password or sensitive data in web.config.

There is a really simple to do it:


  1. go to "command prompt"
  2. type: cd "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\" (which every your drivespace is)
  3. type: aspnet_regiis.exe -pef "<Name of node to encrypt>" "<Full path to web.config>"

Your done.



Edit post:

It was really that simple when i do it on my development server. But when i do the same thing on the SIT server, i was thrown with: "The RSA key container could not be opened"


Solution for me:

  1. Ensure that you have permission to use the keys in "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys" 
  2. Check the keyContainerName in "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config"
  3. go to "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727" type aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY/NETWORK SERVICE"
I'm assuming you are using the default name for NetFrameworkConfigurationKey.


Then go to the top of the post to do the encryption again.

Good luck.

Tuesday, April 20, 2010

Resizing array

If you ever had to work with an array that you wouldn't know the size till run-time, you have a couple of options:


  1. Clone the old array into the new array (un-necessary overhead)
  2. Just proceed with a array with redundant trailing allocated memory
  3. You can resize it with Array.Resize(ref <arrayName>, int newArraySize)


int[] myArray = new int[50];
int newArrayCount = 0;

//some biz logic goes here
//determined array size

newArrayCount = myArray.Count;

Array.Resize(ref myArray, newArrayCount);

You can put myArray.Count as the 2nd parameter of the resizing method, up to your preference.

Sunday, April 11, 2010

c#: boolean vs bool, String vs string, Int32 vs int

A frequently asked question, what is the difference between a Boolean and a bool object in c#? In short, it's actually the same thing. When compiled to MSIL(Microsoft Intermediate Language), they are referring to System.Boolean, thus there's no implication in performance.

But as a good conventional practice, i always use bool & string as opposed to Boolean & String. Unless you always use System.Int32 instead of int.

Friday, April 9, 2010

IIS logs 400 0 64

From my previous post, i've described how to consume a .NET webservice using netbeans. However, due to the JDK version on my colleague's solaris server, they are not able to import several libraries in order to do so.

Thus, they had use socket programming to send out the SOAP request. Everything was doing fine and well on development server, SIT server, and our local machines.

The wierd thing happens when the swing-over to UAT. When the function was called to send the SOAP request and in the while loop that waits for server response, it kept waiting... waiting... waiting... After several attempts to find faults in the java, web service and JDK versions. There was still no good explanation nor solutions. I went onto the web service machine and dug up the IIS Logs and found a couple of lines that showed the request reaching the web service machine but with an error code 400 0 64. After some research, i found out that the error code represents Bad request. Another vague error message -_-.

I almost wanted to give up, until i went into the HTTPERR folder and open up the logs and saw something that caught my attention. There was a request coming into the server via port 9090, but the response was sent to a random port number.

Bingo! In my client's environment, firewalls will block all the traffic going into the servers unless the need arises and we have to write in service requests to open up the port.

1 more problem resolved and hope this post will help anyone that hit this error.

Tuesday, April 6, 2010

Business objects VS Typed Datasets

 I always had this feeling that POCO (Plain old C# objects) will outperform typed datasets & datasets. The main reason why people are using it is only because it lessen development time by a very....... small amount in my opinion. Using business objects are easier to understand and in C# context, the compiler actually do a lot of work for you.

Example in other languages:

public myClass()
{
     private String someString;
  
     public String getString()
    {
        return this.someString;
    }
    public void setString(String value)
    {
        this.someString = value;
    }
}

you can do this in C#:
public myClass()
{
    public String someString { get; set; }
}

That only explains how much it takes to write a Business Object class. Next we go to real work.

I created a simple demo project in VS 2010 (beta), you can use any visual studio to compile this if you want to try it out yourself.

in my Business object class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DemoBizObject
{
    public class BizObject
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Desc { get; set; }
        public decimal price { get; set; }
        public DateTime CreatedDt { get; set; }
        public DateTime ModifiedDt { get; set; }
    }
}

in my aspx code behind, i did this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.ObjectModel;

using DemoBizObject;
using System.Diagnostics;
using System.Web.UI.DataVisualization.Charting;

namespace DemoWebApp
{
    public partial class _Default : System.Web.UI.Page
    {
        Collection<BizObject> BizObjects = new Collection<BizObject>();
        double[] pocotimings = new double[7];
        double[] typeddstimings = new double[7];

        decimal d = 0.00m;
        const int ONE = 1;
        const int TEN = 10;
        const int ONEHUNDRED = 100;
        const int ONETHOUSAND = 1000;
        const int TENTHOUSAND = 10000;
        const int ONEHUNDREDTHOUSAND = 100000;
        const int ONEMILLION = 1000000;
        const string LINEBREAK = "<br />";

        protected void Page_Load(object sender, EventArgs e)
        {
           
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            this.Label1.Text += "Typed Datasets" + LINEBREAK + LINEBREAK;
            this.Label1.Text += ONE +": "+ demoTypedDS(ONE)+ LINEBREAK;
            this.Label1.Text += TEN + ": " + demoTypedDS(TEN) + LINEBREAK;
            this.Label1.Text += ONEHUNDRED + ": " + demoTypedDS(ONEHUNDRED) + LINEBREAK;
            this.Label1.Text += ONETHOUSAND + ": " + demoTypedDS(ONETHOUSAND) + LINEBREAK;
            this.Label1.Text += TENTHOUSAND + ": " + demoTypedDS(TENTHOUSAND) + LINEBREAK;
            this.Label1.Text += ONEHUNDREDTHOUSAND + ": " + demoTypedDS(ONEHUNDREDTHOUSAND) + LINEBREAK;
            this.Label1.Text += ONEMILLION + ": " + demoTypedDS(ONEMILLION) + LINEBREAK + LINEBREAK;

            this.Label1.Text += "POCO" + ": " + LINEBREAK + LINEBREAK;
            this.Label1.Text += ONE + ": " + demoPOCO(ONE) + LINEBREAK;
            this.Label1.Text += TEN + ": " + demoPOCO(TEN) + LINEBREAK;
            this.Label1.Text += ONEHUNDRED + ": " + demoPOCO(ONEHUNDRED) + LINEBREAK;
            this.Label1.Text += ONETHOUSAND + ": " + demoPOCO(ONETHOUSAND) + LINEBREAK;
            this.Label1.Text += TENTHOUSAND + ": " + demoPOCO(TENTHOUSAND) + LINEBREAK;
            this.Label1.Text += ONEHUNDREDTHOUSAND + ": " + demoPOCO(ONEHUNDREDTHOUSAND) + LINEBREAK;
            this.Label1.Text += ONEMILLION + ": " + demoPOCO(ONEMILLION) + LINEBREAK + LINEBREAK;
        }
        private string demoTypedDS(int numOfRecords)
        {
            typedDS ds = new typedDS();
            Stopwatch watch = Stopwatch.StartNew();
           
            for (int i = 0; i < numOfRecords; i++)
            {
                ds.DemoTable.AddDemoTableRow(i, "demo name", "demo desc", d + i, DateTime.Now, DateTime.Now);
            }
            watch.Stop();
            return watch.Elapsed.TotalSeconds.ToString();
        }
        private string demoPOCO(int numOfRecords)
        {
            BizObject tempObject;
            Stopwatch watch = Stopwatch.StartNew();

            for (int i = 0; i < numOfRecords; i++)
            {
                tempObject = new BizObject();
                tempObject.Id = i;
                tempObject.Name = "demo name";
                tempObject.price = d + i;
                tempObject.CreatedDt = DateTime.Now;
                tempObject.ModifiedDt = DateTime.Now;
                tempObject.Desc = "demo desc";
                BizObjects.Add(tempObject);
            }
            watch.Stop();
            return watch.Elapsed.TotalSeconds.ToString();
        }
    }
}

pardon my messy codes, i didn't want to create this project initially, but i want to be someone that talks the talk and walk the walk.Next, create a similar table in your database with following...


 After that, right click on your solution file and click "Add new item" and select a dataset object.
Double click on the XSD file and go to your DB and drag-and-drop the table onto the XSD and you will get the table there..

The codes are very self explanatory and simple, not much re-using of codes especially @ the printing part.

I ran the test and get the results for POCO VS DS

Results are:
Typed Datasets

1: 4.1E-05
10: 5.47E-05
100: 0.0004515
1000: 0.0045912
10000: 0.0747852
100000: 0.6806366
1000000: 7.4931112

POCO:

1: 5.8E-06
10: 9.6E-06
100: 8.26E-05
1000: 0.0008128
10000: 0.0081756
100000: 0.1015654
1000000: 1.1922586


I tested it several times and dare to confirm that with this demo project, POCO is that Datasets in the lower range (1 to thousands) and the ratio justs exponential when the records reaches millions.

In this test, i only did instantiation and assignment, the Big O notation for:
  • POCO = n Log n 
  • Dataset = C^n
I don't find the need to extract data from database tables and going through the whole cycle as it will end up the same for both, the main difference only occurs when i instantiate and assign values to them. Even with just 6 primitive type objects, typed datasets are giving C^n in terms of performance. That is why my organization's Entity Objects are such a pain in the neck (they used typed datasets plus overriding several events)

Monday, April 5, 2010

Consume .NET webservice with only WSDL file

Objective: Consume .NET web service
Problem: I only have WSDL file (Server is blocked from my dev server)

In the past, a web service consumption was only: Right click on project, click on "Add web reference" and enter URL. But it's different this time as the production server had firewalls that blocked unauthorized/unnecessary access. I know it's possible to generate class files from the WSDL file, but how?

Time saver:.NET Framework Tools

After you generate the .cs file, CSC compile it into a dll and put the dll into your project and you will be able to invoke web methods immediately. For my case, i have to bring it to the production server to try access it, and it did worked perfectly :)

Sunday, April 4, 2010

Performance bottleneck? review boxing & unboxing frequencies

There are times where our applications exceed users' response time threshold of 7s (usually), where all action must be completed under 7s.

Page-by-page code reviews are the last resort, but when you are resorting to that, look out of redundant boxing and unboxing of objects, check out: Technet

That's usually my case, or un-necessary objects declaration and recursion.

It's always better to go with iteration than recursion in terms of performance, as well as a typical For loop will outperform a foreach loop due to the boxing and unboxing overhead.

Check the traffic, CPU & memory utilization for resource bottleneck.

The last option is to review the entire architecture of the application (a PM's nightmare as that means a lot of time and resource needs to be pumped into the project). If good architectural designs was laid in place before development start, it wouldn't have to come to this point :)

Friday, April 2, 2010

Consuming .NET webservice using Java (netbeans 6.8) in 2 mins

I'm not a very Java person, but i was tasked to assist a team of Java developers using Solaris server. (A .Net developer's nightmare) I'm a GUI person and didn't like the command line concept, well it's powerful and have very little overhead but i need time to learn before jumping into it.

I told the team that i'm a .NET person, not a java guy. They told me leave the console/terminal/ftp to them, just help them to consume a .NET web service. Good.

I asked them from the WSDL file and went to research how java can consume a web service.

Luckily, there was a lot of resource out there documenting how to consume web service in netbeans.

First, create a New Project in NetBeans, give it a meaningful name.
Second, add a file and select "Web service" tab.
third, browse the wsdl file and click "Finish".

Now NetBeans will auto generate all the dependent files.

Expand the tree under your webservices and you will be able to see the web methods with red dots.

Drag and drop them into your methods and all the objects will be automatically instantiated and invoked with default values.

Using your java DAO(Data Access Objects) or equivalent and assign them the correct values and hit then run button.

There you go, java consumption of .NET web service in under 2 mins.

Thursday, April 1, 2010

IIS6 - The specified handle is invalid

I've met an issue on a development server whereby the IIS just simply refuses to start. I took a step-by-step diagnostic approach and went to "inetmgr", and all i see is just a IIS without a "+" sign.

When i right click on it and start, it just loads a progress bar and terminates. No error messages, no prompts, no nothing!

I remembered that IIS needs IIS Admin service to be running in order to start, so i checked "services.msc" and i saw the problem. IIS Admin service wasn't running even though it was set to be automatic. When i try to start the service, it gave me a very "helpful" error message

"Error 6: - The specified handle is invalid".

After scouring around the net, i manage to find a couple of solutions, tried all of them and IIS still wouldn't budge. I told the support team to reinstall IIS and we will reconfigure all the sites. Going home and waiting for the reinstallation to finish, i came back when they informed me and found out that the IIS gave me an even better error message now.

"System cannot find the path specified"
Very pissed off, i decided to dig deeply into the root of the problem. I found out from the rest of the team that someone had actually messed around with the server. He was trying to get a X.509 certificate going in the server, but somehow he messed up IIS configs.

After a couple more hours of troubleshooting, i found out that the error message literally implies the truth. IIS is unable to find a couple files that it has direct dependencies. One of which is MetaBase.xml and MBSchema.xml 


True enough, when i navigate to the directory ":\WINDOWS\system32\inetsrv" i saw MetaSchema.xml was there, but MetaBase.xml was missing. I also found out that IIS creates 10 versions of backups whenever there are changes to its configs. I took the latest and renamed it back to MetaBase.xml and everything was up and running again.