02.26.06
Posted in Programming at by chenty
I recently transferred an e-commerce website to a new server. Everything works perfectly: faster server, faster network connections, and more features and spaces. However, I got many reports from cusotmers that the ordering system does not work properly. I took a look at the website this weekend, and I noticed that the Session I used to store user account and shopping cart kept missing. It is different from “session expires” because the sessions come back again after several refresh. I contacted the technical support from the hosting company, and they moved me to an individual pool of sessions, and the problem remains. I am not sure what exactly happens, but I think they might implement “server farm”. “In-process” session state will not be copied to other servers, so if the visitor is sent to another server, the sessions will lose. This can be solved by setting up the server farm so that the same visitor will be directed to the same server all the time. However, it might be an easy task.
We come up with a solution with the hosting company by implement session state on SQL Server. Unfortunately, they don’t have experience on this before. I have found many articles online, and before I add my tab in web.config, the hosting company needs to run InstallSqlState.sql script. This is right for .NET Framwork 1.0/1.1, but it is no longer a right approach in .NET 2.0. In .NET 2.0, you must not run this script manually. Instead, a program called “aspnet_regsql.exe”. You can locate this program in the same directory as InstallSqlState.sql. The directory is [system directory]/Microsoft .NET/Framework/[version number]In our case, the directory is C:\WINNT\Microsoft .NET\Framework\v2.0.50727.
The hosting company notified me that the script is installed. However, I didn’t see any database ASPState is created. I talked to them over live chat, and I found out they just ran aspnet_regsql.exe directory, and setup through a wizard. This is wrong.
YOU CANNOT SETUP SQL SESSION STATE by running aspnet_regsql.exe
The right way to do it, run:
aspnet_regsql -ssadd -E
-ssadd is to enable Sql Session State. -E is using Windows Authentication. If you have ’sa’, you can use -U ’sa’ -P [password].
By default, all sessions are saved in tempdb database, and all stored procedures are saved in ASPState database. Sessions will lose if you restart Sql Server. However, if you want to use Persisted mode (save all sessions in ASPState database), you should use “-sstype p” option.
In our case, I just use default type.
After running script successfully, you need some more work:
1. make sure your sql account has access to ASPState and tempdb. For ASPState, you will need EXEC privileges for all stored procedures, and in tempdb database, you will need SELECT/INSERT/UPDATE for 2 user tables: ASPStateTempApplications and ASPStateTempSessions.
2. insert the following code in web.config:
-
<sessionstate cookieless="false" mode="SQLServer" sqlConnectionString="server=[server name];user id=[user name];password=[password]">
-
</sessionstate>
Now, your session should run in SQL Server.
In summary, most tutorials online is for .NET Framework 1.1:
1. run InstallSqlState.sql script
2. insert above code in web.config
not many tutorials for .NET Framework 2.0, at least you won’t find them if you google “.net sql session state” (use “.net 2.0 sql session state” instead):
1. run aspnet_regsql.exe, e.g. aspnet_regsql -ssadd (DO NOT run aspnet_regsql without parameters. that wizard is for something else)
2. setup database user
3. insert above code in web.config
Here is a link for aspnet_regsql.exe on MSDN: http://msdn2.microsoft.com/en-us/library/ms229862.aspx
If you have problem to setup SQL session state, feel free to email me.
Permalink
02.24.06
Posted in Programming at by chenty
I am still in a panic mode after receiving 3 traffic tickets yesterday. I delete all the stored procedures from local SQL Server by mistake. Inside of restore a former backup, I decide just to copy from remote server. However, after importing all stored procedures back, the owners of these objects are all changed. I need to change all back. Sure I could use sp_changeobjectowner, but it is not fun to change over 100 stored procedures in this way.
Luckily I found this script by Darrell Norton. Here is the URL: http://codebetter.com/blogs/darrell.norton/archive/2005/03/21/60134.aspx
Because I only need to change stored procedure, I only need type ‘P’. Here is my modified code:
-- note: I am not the author of this code
-- this code is created by Darrell Norton
declare @ObjectName varchar(256)
-- we are only interested in USER Objects
-- not already owned by 'sa'
-- we don't want keys and constrainst
set @ObjectName = (
select top 1 [name] from sysobjects
where uid <> SUSER_SID(’sa’)
and [type] in (’P'))
declare @ObjectOwner varchar(256)
declare @ObjectFullName varchar(512)
declare @NewOwner varchar(256)
set @NewOwner = ‘dbo’
– default to ‘dbo’ if null
set @NewOwner = isnull(@NewOwner, ‘dbo’)
while @ObjectName is not null
begin
select @ObjectOwner = USER_NAME(uid)
from sysobjects where [name] = @ObjectName
set @ObjectFullName = @ObjectOwner + ‘.’ + @Objectname
PRINT ‘Changing ownership of ‘'’ + @Objectname +
‘'’ from ‘'’ + @ObjectOwner + ‘'’ to ‘'’ +
@NewOwner + ‘”’
execute sp_changeobjectowner @ObjectFullName, @NewOwner
set @ObjectName = (select top 1 [name] from sysobjects
where uid <> SUSER_SID(’sa’)
and [type] in (’P'))
end
It works like a charm!
Permalink
02.21.06
Posted in Programming at by chenty
I had a great dinner with some of my old friends from university, and someone was talking about MD5 is breakable. I later realize he just meant MD5 is possible to find a “collision”. So, it is time for many of our programmer use SHA to protect our passwords in database.
I will skip introduction on SHA because you can simply google it. There are several different SHA: SHA-0, SHA-1, SHA-224, SHA-256, SHA-384, and SHA512. Sometimes, we call SHA-224 to SHA-512 as “SHA-2”. Basically, the latter version in above list is better, but it also consumes more computing.
Luckily, it is very easy to implement SHA in .NET Framework. Here, I will give the code to encrypt your user password into an encrypted string:
In order to use SHA512 and SHA512Managed classes, you need to import “System.Security.Cryptography” namespace:
string SHA512Compute(string inputPassword)
{
SHA512 sha512 = new SHA512Managed();
Byte[] hashedDataBytes;
UTF8Encoding encoder = new UTF8Encoding();
hashedDataBytes = sha512.ComputeHash(encoder.GetBytes(inputPassword));
return Convert.ToBase64String(hashedDataBytes);
}
-
string SHA512Compute(string inputPassword)
-
{
-
SHA512 sha512 =
new SHA512Managed
();
-
Byte[] hashedDataBytes;
-
UTF8Encoding encoder =
new UTF8Encoding
();
-
hashedDataBytes = sha512.ComputeHash(encoder.GetBytes(inputPassword));
-
return Convert.ToBase64String(hashedDataBytes);
-
}
inputPassword is what user input text password, and the function return a string as encrypted password. You can simply replace “512” as 1, 224, 256 and 384 in your code to use other SHA algorithms.
For programmers determining the size of data column in database to store encrypted passwords, I give a quick reference of the “length of encrypted password” (in bytes):
MD5 – 24
SHA1 – 28
SHA256 – 44
SHA384 – 64
SHA 512 – 88
I hope my tutorial help. If you still have questions regarding cryptographic hash functions in .NET Framework, feel free to email me.
Permalink
02.17.06
Posted in Programming at by chenty
Sometimes, we put control links and main content in separate user controls in the same webpage. In this case, you cannot call Visible property directly because buttons or linkbutton in one control cannot access panels or labels in another user control.
A simple solution is to use QueryString. In this case, when a button or link is clicked, the webpage will be rerendered, and the main contant pane will determine what information to display depends on parameters in QueryString. However, ever time you submit the querystring, this may not be efficient in some cases especially if it involves a lot of database queries. It will be a much better approach, if we can load all information once, and then use “Visible” property to control what to display. In this case, no further database transactions are required, and pages will be loaded much faster in this manner since all informaiton already cached.
The hard part for this approach is how can we send command from one user control to another. Actually, it is not possible to do this directly (or at least I do not know). We will need to use parent page that contains both user controls as medium. During this two way process, it is fairly easy to send command from parent to a child user control. For example,
Parent Page:
-
<script language="c#" runat="server">
-
void changeDisplay ()
-
{
-
//myControl is the user control that the command is sent to
-
myControl.change();
-
}
-
</script>
Child User Control:
-
<script language="c#" runat="server">
-
public change ()
-
{
-
myLabel.Visible = true; //change visibility of one label
-
}
-
</script>
However, it takes much more effort to do this the other way. One solution is to use event and delegates, which I think it is quite complicated. I use “BubbleEvent” in .NET. In BubbleEvent, the event triggered by calling RaiseBubbleEvent(), and the event will be passed upward to parents. In parent control, we override OnBubbleEvent() to catch the catch and process it. The amount of code is much less than using delegates. I give an example here to pass a command to parent page from a linkbutton.
In User Control, we have a linkbutton:
-
<asp :linkbutton id="linkTest" OnClick="OnClick_Test" text="Test" CommandName="something we want to pass to parent control" runat="server" />
We define the OnClick_Test as:
void OnClick_Test(object sender, EventArgs e)
{
//raise the event
RaiseBubbleEvent(this, e);
}
-
void OnClick_Test(object sender, EventArgs e)
-
{
-
//raise the event
-
RaiseBubbleEvent(this, e);
-
}
In parent page, we need to catch the event:
protected override bool OnBubbleEvent(object sender, EventArgs e)
{
if (sender.ToString() == "System.Web.UI.WebControls.LinkButton")
{
Response.Write(((System.Web.UI.WebControls.LinkButton)sender).CommandName);
}
return true;
}
-
protected override bool OnBubbleEvent(object sender, EventArgs e)
-
{
-
if (sender.ToString() == "System.Web.UI.WebControls.LinkButton")
-
{
-
Response.Write(((System.Web.UI.WebControls.LinkButton)sender).CommandName);
-
}
-
return true;
-
}
In this example, when you run the parent page and click on the button, it will display a string: “something we want to pass to parent control”.
If you want to pass a command from one control to another, you can simply define CommandName and CommandArgument in linkbutton or button, and write some code to process these command and arguments in OnBubbleEvent method, and then pass down to another user control.
Permalink
02.15.06
Posted in Life at by chenty
I stopped at claiming that I measure my success by making sure I always live better than I did instead of comparing myself with other people. Then I briefly claimed that “living better” doesn’t mean getting richer or getting famous. This leads my second approach: “What is a better life?” A person who has a good life is definitely successful. Again, it is a very hard question. I am happy; I am healthy; I have financially freedom; I have a good wife, good kids and a warm family; I don’t have stress; I don’t have debt… it goes on and on. If we look at some of these factors closely, we will find some of them are contradictory. You cannot spend more time with family, if you want to work more and make better money; you cannot have less stress if you want to be successful in your business, etc. Therefore, I think the key of good life is balance. A successful person needs to find a good balance between work and leisure, stress and health, wealth and happiness.
I used to work all the time, and undermine my health and leisure. That gave me a lot of bad habit and unhealthy lifestyle until recently I got aware of my problem. I have completely changed my life style since I came back from China. I started not to work at night and not to eat fast food. Instead, I work out in gym, cook healthy food for myself with fresh ingridients. Amazingly, I feel not only healthier, but also happier and more energetic. I can feel the change inside my body and my attitude towards my future.
In all, with these two approaches I stated above, I can work slowly but surely towards my success.
Permalink
02.14.06
Posted in Life at by chenty
I have gained so much energy from the trip to China, and I often tell myself that I must work harder to be successful. However, what is success to me? I just realize that it’s really hard to answer this question. A simple way is to be rich or to be famous, but I don’t think that’s a considerate answer.
This question has troubled me for the past two days, and I think I should answer it in two different approaches. The first approach is “how we measure it”. How do we know we are successful? I think a common way is to compare with others, which is used by most people I know. “George bought a new house recently. When do you think you gonna have a house?” “James got a really beautiful girl friend, and I heard she’s a model. Hey, why do you never get one?” There are many questions like that from friends, family or being asked by myself. Does that mean I am not successful?
A young man graduated from one of top universities in the nation, and he believed he could finally be “successful” after more than 15 years of study. He felt very motivated, and dreamt for a wonderful future. However, the reality taught him the first lesson since he left school: this world is so much more than the courses he took, and he ended up working in a factory where he couldn’t even use what he studied.
One day, he took a smoke break at work. Yes, he started smoking now. He found smoking is a good getaway aginst stress and worries about paying back his student loan. Suddenly, a young boy, who is only 16-17, driving a luxury car parked beside him, and the driver went in the factory. The young man later learned that was boss’s son.
What does this young man think? He tried his life to fight for his success, but someone else could simply have more without working. This young man then conclude that he is not as successful as that young boy.
Why does this young man think this way? I think it’s because human tends to compare with others, especially in a materialistic world. From certain aspect, this encourages competition, and motivates people to work harder, but on the other hand, it may also discourage people. Someone will think: no matter how hard I work, I will never have that kind of life. I want to argue that, first, “that kind of life” may not be as good as you think. Everyone has its own problem; second, even “that kind of life” is really good, why do we “have to” have it? Is that something the very thing we call “greed”?
I strongly feel that I shall not measure my success in terms of comparason with others. Everyone is born from different background, so there is nothing we can complain about our background. Otherwise, we are just complaining to God, and questioning his fairness. My two cents on this is: be happy and be thankful for what you have. Instead of comparing with others, why not compare with what we used to be? I say a successful person is a person who can always say: Today I live better than yesterday. By saying living better, I don’t mean to be richer or more famous, but happier and more confident about the future.
(To be continued)
Permalink
02.09.06
Posted in Programming at by chenty
Things have not got better since my last blog about this I/O error I got. I kept backing up and restoring for the past week. I have tried many methods including moving data file to a different drive and reinstalling SQL Server, but both ways did not work. There are not many information on the Internet regarding this error. Here is a list for possible situations when people getting this error:
1. A small glitch in I/O. Solution: dbcc will not repair it. Simply restores a previous backup will work.
2. Disk failed. Solution: run diagnostics utilities to make sure disk is damaged, and just install a new hard drive.
Strangely, my case does not fall in either category above. No matter how many times I restored, no matter which drive I put the data file, it showed the same problem. Windows 2000 logs do not show any disk failure or error at all. After 2 days of debugging, I locate one stored procedure often produced I/O error, and I tried to run it a couple of times, but event viewer still showed no disk error, which I/O error was reported in SQL Analyzer. I noticed that the stored procedure was actually wrapped in a transaction, so I decided to removed the transaction so it could run in individual steps. That was a very successful move. After SQL Analyzer reports I/O error as normal, 4 warning and one error is reported in Event Viewer. It looks like the SATA controller reports some errors.
I had built a RAID 1 on 2 SATA hard drives for main system. I have run WD Diagnostics tool for these 2 Western digital hard drives, and it reported no error for hard drive itself. This reminded me how the hard drive previously failed and lost all data, but then the hard drive works again after reformatting. It must be something wrong with SATA controller! Therefore, I backed up all data and reinstalled the system. I removed RAID 1, and installed the system on a single hard drive. This time, everything works perfectly.
I have been tracking the database for the past 3 days, and it works flawlessly, so I think SATA controller and RAID was the problem.
Lessons from this experience:
Even though RAID 1 can increase reliability of data, this has a pre-condition: the I/O controller works flawlessly. If the controller does not work properly, the I/O system could still fail even the disks are error-free. I do not know if SATA RAIDs in general are unstable or just my motherboard, but I would not have too much confidence on it. I think SCSI is still a better way, despite of its high cost.
Permalink
Posted in Miscellaneous at by chenty
I upgraded my blog to Wordpress 2 today, and installed a new theme (as you see now).
It simply looks good, period.
Permalink
Comments off