Friday, September 29, 2006

Patterns & Practices Guidance Explorer

ScottGu recommended a very useful tool,namely Patterns & Practices Guidance Explorer, which contains hundreds lists of security & performance best practices and patterns. The usage scenarios are

"1. Improve the security and performance of your application with guidelines and checklists that match your application exactly.
2. You can build custom sets of guidance and share with your team as recommended practice.

3. You can add new guidance to the library to share with your team, your company or the larger development community. "



Hope this helps...

Thursday, September 21, 2006

Free PDF Converter in .NET

I have been struggling looking for non-commercial PDF library to convert my ASP.NET pages to PDF for reporting purpose. Finally, I decided to choose iTextSharp v3.1.5 library among other free libraries. I have found out that the library is extremely handy with few cool features such as document watermarking and encryption, user permission on copying, printing the document and the list goes on.

Anyway, there is an annoying problem - the library has iTextSharp.text.Image class, which conflicts with the System.Drawing.Image class. Hence, the class will be ambiguous if both namespaces are imported in your project. Anyway, this matter is bearable for me. :)


Library Project Homepage : http://sourceforge.net/projects/itextsharp/
Library Download : http://prdownloads.sourceforge.net/itextsharp/itextsharp-3.1.5-dll.zip?download
Tutorial (C#) Download : http://prdownloads.sourceforge.net/itextsharp/iTextSharp.tutorial.01.zip?download
Tutorial (VB) Download : http://prdownloads.sourceforge.net/itextsharp/iTextSharp.tutorial.VB.NET.01.zip?download


Cool !

Tuesday, September 19, 2006

No more DbCommandWrapper class

I'm testing the Enterprise Library January CTP 2006, and I have been searching for the DbCommandWrapper class and the GetXCommandWrapper() methods of Database class but they do not exist. Eventually, I found out that they are actually removed from the DAAB in this new version.

Example of code for old versions of DAAB prior to January 2006 release

Database db = DatabaseFactory.CreateDatabase();
DBCommandWrapper dbCommand = db.GetStoredProcCommandWrapper("SelectAuthors");
dbCommand.AddInParameter("AuthorID", DbType.String, strAuthorID);
DataSet dsAuthors = db.ExecuteDataSet(dbCommand);


Example of code for DAAB January CTP 2006

using System.Data.Common;

Database db = DatabaseFactory.CreateDatabase();
DbCommand dbCommand = db.GetStoredProcCommand("SelectAuthors");
db.AddInParameter(dbCommand,"AuthorID", DbType.String, strAuthorID);
DataSet dsAuthors = db.ExecuteDataSet(dbCommand);


Be informed that some online examples are using DbCommandWrapper class. thus, make some modification like above. Visit Intro to DAAB January 2006 for more version migration issues.

Monday, September 18, 2006

EBook on Threading in .NET

Thinking of learning Threading in .NET? I've found out a very handy ebook that explains fundamentals about .NET Threading. Worth to read !

Web : http://www.albahari.com/threading/
Book (PDF) : http://www.albahari.com/threading/threading.pdf


Sharing~~

Corrections of ClientCallBack Example

I have tested the example of ASP.NET 2.0 new feature - ClientCallBack at ASP.NET 2.0's Client Callback Feature, but found not working due to:

1. There is no this.GetCallbackEventReference()
2. RaiseCallbackEvent() does not return string data type, from ICallbackEventHandler
3. Missing of GetCallbackResult(), that defined in ICallbackEventHandler


Finally I get it done by making some corrections:

1. Use this.ClientScript.GetCallbackEventReference()
2. Define the RaiseCallbackEvent() that returns no data type
3. Define GetCallbackResult() to return the result to the client-side


Corrected code:

protected void Page_Load(object sender, EventArgs e)
{
       sCallBackInvocation = this.ClientScript.GetCallbackEventReference(this, "message", "ShowServerTime", "context", "OnError",true);
}

public void RaiseCallbackEvent(string eventArgument)
{
       sCallBackInvocation = DateTime.Now.ToString();
}

public string GetCallbackResult()
{
       return sCallBackInvocation;
}



Recommendation
1. Check whether the browser does support callback feature in Page_Load() event


if (!Request.Browser.SupportsCallback)
    // error message

Page Redirect After Login in Forms Authentication

Normally, we will be redirected to the originally requesting page, with ReturnUrl query string appended in the URL after successful user login in Form Authentication using FormsAuthentication.RedirectFromLoginPage() method. Otherwise, the we will be redirected to default.aspx, by default.

The question is, what method do we need to use if we want to redirect the users to different page other than default.aspx? Here I demonstrate how it can be accomplished.


bool isAuthenticated = true;

if(isAuthenticated) // after user is authenticated
{
   if(Request.Params["ReturnUrl"] != null)
   {
      FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, false);
   }
   else
   {
      FormsAuthentication.SetAuthcookie(txtUsername.Text, false);
      Response.Redirect("yourpage.aspx");
   }
}


Get rid of default ones.... !

Sunday, September 17, 2006

VIEWing your controls STATE

ViewState is one of the state managements in the ASP.NET and it is paramount especially in custom server control development. Proper understanding and use of ViewState could definitely save your life, notably in postback model in ASP.NET.

Here I recommend some articles of ViewState for your readings :

1. Understanding ASP.NET ViewState [MSDN]
2. TRULY Understanding ViewState [InfiniteLoop's Blog]
3. Understanding View State in ASP.NET [aspAlliance]
4. ViewState: All You Wanted to Know
5. The ASP.NET ViewState [MSDN Magazine]


You already mastered another ASP.NET 's state management ;)

ASP.NET 2.0 Full Page Life Cycle Diagram

Here is the big yet comprehensive diagram illustrating the page life cycle in ASP.NET 2.0




To recall the Page Life Cycle in ASP.NET v1.x




ASP.NET 2.0 ones much complex !

Checking Existence of Available SQL Server

Of late, I had read an article about determining list of SQL Servers that are available to your application.

.NET 1.1
There is no way but you need to use COM-based SQLDMO to have an interop call.


using SQLDMO;

try
{
NameList objSQLList;
ApplicationClass objSQLApp = new SQLDMO.ApplicationClass();

objSQLList = objSQLApp.ListAvailableSQLServers();

foreach(string name in objSQLList)
Response.Write(name + "
");
}
catch(Exception ex)
{

}
finally
{
objSQLApp.Quit();
}


* You have to reference the SQLDMO.dll, which located at :\Program Files\Microsoft SQL Server\\Tools\Binn by default.


.NET 2.0
It is much easier. You can retrieve the list of servers available using System.Data.Sql namespace, by enumerating each of the server instance.


SqlDataSourceEnumerator enumerator = SqlDataSourceEnumerator.Instance;
DataTable datatable1 = enumerator.GetDataSources();
foreach (DataRow row in datatable1.Rows)
{
Response.Write("Server Name:" + row["ServerName"] + "
");
Response.Write("Instance Name:" + row["InstanceName"] + "
");
}


Sometimes, these methods are better trying to connect the DB Server to see whether it is succesfully connected, but the output not always accurate due to :

1. Invalid Login / User credentials
2. Timeout due to network congestions


Neat !

Tuesday, September 12, 2006

Storing Static JavaScript in Resource File [ASP.NET 2.0]

In ASP.NET , we normally embedded the script string in the code-behind and invoke the RegisterStartupScript() to emit the JavaScript. The normal way we do like


ClientScriptManager csManager = Page.ClientScript;

StringBuilder strScript = new StringBuilder();
strScript.AppendLine("<script>");
strScript.AppendLine(@"var response = confirm('{0}, do you want to continue ?');","Alvin Chooi");
strScript.AppendLine("if(response)");
strScript.AppendLine(" alert('OK')");
strScript.Append("</script>");

if (!csManager.IsStartupScriptRegistered("ScriptTest"))
   csManager.RegisterStartupScript(this.GetType(), "ScriptTest", strScript.ToString());


The script is less readable and messy. What the worst is that would be a slightly string manipulation overhead. In ASP.NET 2.0, you can store this static script in the resource file resx, which is stored in the App_GlobalResources folder.

Screenshot



You could able to reference the script string from the resource file without hard-coding the script in the code-behind by


ClientScriptManager csManager = Page.ClientScript;

if (!csManager.IsStartupScriptRegistered("ScriptTest"))
{
  csManager.RegisterStartupScript(this.GetType(), "ScriptTest", String.Format(Resources.script.AlertMeScript,"Alvin Chooi"));
}



Neat and manageable !

Microsoft Interview Questions

Recently, I'd read the post of Jason Looney about questions asked Microsoft Interview. Amazing and extraordinary !

Worth to read
1. Microsoft Interview Questions Guide
2. ASP.NET Interview Questions (The only one I could answer well ;p)
3. .NET Interview Questions
4. The Guerrilla Guide to Interviewing

Hunting for more....

Friday, September 08, 2006

Fastest Ever Browser ?

Recently, I had read an article of What is the world's fastest browser, and it claimed that optimized firefox (swiftfox) is the fastest browser among others in 64-bit environment. Whereas, Konqueror is crowned best-performance browser in Linux.

Thursday, September 07, 2006

Accessing Text in DataGrid's TemplateField

If you try to access the content of TemplateField

<asp:TemplateColumn>
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem,"au_fname") %>
<%# DataBinder.Eval(Container.DataItem,"au_lname") %>
</ItemTemplate>
</asp:TemplateColumn>

using DataGrid1.Items[0].Cells[0].Text (I assume it is first column), you would probably get nothing. It is because the text would be placed in a special literal control called DataBoundLiteralControl, which is auto-generated by the compiler IF you place the data-bound expression in the ItemTemplate. Therefore, to access its content. You can use this,

((DataBoundLiteralControl)dgrdAuthors.Items[0].Cells[0].Controls[0]).Text


You get it !!!

Capitalizing Every First Letter of Words

How would you do that in your first thought? Would you create your own user-defined function for that purpose in .NET? Please do not reinvent the wheel because there is built-in method available.


using System.Globalization;

string str = "cool strINg";
string str1 = "COOL STRING";

TextInfo objTextInfo = new CultureInfo("en-US",false).TextInfo();
str = objTextInfo.ToTitleCase(str); // Cool String *CORRECT
str1 = objTextInfo.ToTitleCase(str1); // COOL STRING *WRONG
str1 = objTextInfo.ToTitleCase(str1.toLower()); // Cool String *CORRECT


* For FULL CAPITALIZED words, you need to convert them to lower case before passing it to the ToTitleCase() method.

Dynamically Adding Columns to GridView

I was asked in ASP.NET Forum why the dynamically inserted BoundField would be lost from the GridView's column collection on postback (eg. Button click in GridView)?

Many people would dynamically create controls in the Page_Load event. But I afraid it isn't a right place for the dynamic creation because the data in the control may not be pertained. (ViewState lost on postback). If possible, do the dynamic control creation in Initialization event (eg. Page_Init).

One of the differences between Page_Init and Page_Load is Page_Init event is only fired once and it is not fired on each postback, whereas the Page_Load event is always fired on every postback.

Back to the topic, hence, to avoid the dynamic GridView's fields gone from its GridView's collection on postback, you SHOULD always create it in GridView's Init event. For instance,

Protected Sub GridView_Init(sender as Object, e as EventArgs) Handles myGridView.Init
Dim field As New BoundField()
field.DataField = "data"

myGridView.Columns.Insert(0, field) 'To be first column in GridView
End Sub



The related discussion can be found here

Good luck !

Recovering DB with LDF only

Of late, I witnessed the loss of mdf (due to corrupted or accidentally removed/overwritten) is painful. It is easy to recover the data from the .bak (database backup) or mdf(database file), but how would it be done the same thing just using ldf (log file) ? Here are the 10 steps that needs to be followed in order you have data restored.

1. Find out your previous database .bak file (backup file).

2. Backup your updated .MDF file and the latest LDF file

3. Delete your current database
- If you cant access to SQL Queries Analyzer no worries just open with master
- type :
DROP DATABASE SAMPLE_DB
GO

p/s - Make sure your infected MDF and LDF fully deleted from C:\Program Files\Microsoft SQL Server\MSSQL\Data

4. Create a new database with FULL Mode
- Open SQL Analyzer type following codes:
- type :
USE master
GO

CREATE DATABASE myDB
ON(NAME='myDB',
FILENAME='C:\Program Files\Microsoft SQL Server\MSSQL\Data\myDB..mdf')
LOG ON(NAME='myDB',
FILENAME='C:\Program Files\Microsoft SQL Server\MSSQL\Data\myDB_Log')
GO

ALTER DATABASE myDB
SET RECOVERY FULL
GO

EXEC sp_dboption 'myDB', 'autoclose', true
GO


5. Delete existing data and log files
- type :
EXEC master..xp_cmdshell 'del C:\Program Files\Microsoft SQL Server\MSSQL\Data\myDB.mdf
EXEC master..xp_cmdshell 'del C:\Program Files\Microsoft SQL Server\MSSQL\Data\myDB_Log'
GO


- Make sure no more .MDF and .LDF in your C:\Program Files\Microsoft SQL Server\MSSQL\Data


6. Stop your whole database

7. Copy your previous infected .MDF and .LDF to C:\Program Files\Microsoft SQL Server\MSSQL\Data

8. Backup the log with NO_TRUNCATE
- Note that backup will error due to inaccessible data file, but log will still be backed up.
- type :
BACKUP LOG myDB
TO DISK='C:\Backups\myDB.bak'
WITH NO_TRUNCATE, INIT
GO

- Make sure backup success, check the .bak file if the file size too small if compare with your .LDF file size then might be error, maybe your infected .LDF file stored wrongly, but normally no problem.
- This is very important file, no error here then fine already.

9. Restore your database

- Restore your previous backup database. Doesn't matter if your data not up to date.
- type :
USE Master

RESTORE DATABASE DatabaseName
FROM DISK = 'c:\Backups\old_myDB.BAK
WITH NORECOVERY


- p/s Remember use WITH NORECOVERY



10. Restore your backup log

- type:
RESTORE LOG myDB
FROM DISK = 'C:\Backups\myDB.bak'
WITH RECOVERY


- p/s Remember use WITH RECOVERY

- Check your data again.
- Done !!!

JSON Reader

Today is a boring day, I decided to create a lightweight JSON reader for JSON manipulation using JavaScript (After I have not been touching JSON and JavaScript prototype since my FYP). My intention of creating this JSONReader is simply to manipulate/read the JSON value with string path supplied. To start off, I use a very simple JSON in my example.

var myJSON = {"Image": {
"Width":800,
"Width":200,
"Height":600,
"Title":"View from 15th Floor",
"Thumbnail":
{
"Url":"http:\/\/scd.mm-b1.yimg.com\/image\/481989943",
"Height": 125,
"Width": "100"
},
"IDs":[ 116, 943, 234, 38793 ]
}}


Now, we "instantiate" the object of JSONReader with the JSON format passed as parameter to its constructor.


var reader = new JSONReader(myJSON);


Then at the frontend, we allow the users to key in the string path in the TextBox.


<input type="text" id="txtPath" name="textfield">
<input type="button" onclick="GetValue()" name="Submit" value="Get the Value">

<span id="lblMessage"/>


The string path provided by user will be passed to the FindValueByKeyPath() method of JSONReader in the GetValue() function to obtain the value in JSON. The $F() is the method in the prototype.js that used to retrieve the value of specified HTML element.

var path = $F("txtPath");
lblMessage.innerHTML = reader.findValueByKeyPath(path);


Test Results
User Input : Image\Thumbnail
Output : {"Url":"http://scd.mm-b1.yimg.com/image/481989943","Height":125,"Width":"100"}

User Input : Image\Thumbnail\Url
Output : http://scd.mm-b1.yimg.com/image/481989943


Screenshot



Additional Libraries Needed
prototype.js
$F(), class.Create()

json.js
parseJSON(), toJSONString()


The complete example can be downloaded here


Still boring ~~ :|

Saturday, September 02, 2006

ASP.NET Best Practices

I have been collecting ASP.NET BEST PRACTICES articles for quite some time. Here are some articles/guidelines that may be handy to you.

ASP.NET Performance Best Practices
1. Improving ASP.NET Performance [MSDN]
2. Developing High-Performance ASP.NET Application [MSDN2]
3. Performance Tips and Tricks for .NET Applications [MSDN]
4. 10 Tips for Writing High-Performance Web Applications [MSDN Magazine]
5. Improving String Handling Performance in .NET Framework Applications [MSDN]
6. Performance Strategies for Enterprise Web Site Development [Code Project]
7. Improving SQL Server Performance [MSDN]
8. Developing High-Performance ASP.NET Applications [aspalliance]


ASP.NET Security Best Practices
1. Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication [MSDN]
2. Improving Web Application Security: Threats and Countermeasures [MSDN]
3. ASP.NET Security: 8 Ways to Avoid Attack [devx]
4. SQL Injection Attacks - Are You Safe? [sitepoint.com]
5. Security Practices: ASP.NET 2.0 Security Practices at a Glance [MSDN]
6. An Introductory Guide to Building and Deploying More Secure Sites with ASP.NET and IIS [MSDN Magazine]


ADO.NET Best Practices
1. Best Practices for Using ADO.NET [MSDN]
2. ADO.NET Best Practices [devx]
3. ADO.NET Best Practices, Part II [devx]
4. ADO.NET Best Practices [code-magazine]
5. Using Data with ASP.Net - 10 of my 'Best Practices'
6. Optimized ADO.NET [theserverside.net]
7. ADO.NET and SQL Server Performance Tips [sql-server-performance]


Error Logging / Exceptions Best Practices
1. Best Practices for Handling Exceptions [MSDN]
2. Exception Handling Best Practices in .NET [codeproject]
3. Exception Handling in Enterprise Applications [devcity]
4. Exception Handling Best Practices in .NET


Naming/Standards Guidelines
1. Naming Guidelines [MSDN]
2. C# Coding Standards and Best Programming Practices [dotnetspider]
3. SSW's Naming Conventions [SSW]


I'll post more useful ASP.NET links in the future. Hope this helps... :)