Thursday, January 24, 2008

Handle foreign key violation

When you delete a record that is being referenced by other tables, you will have a foreign key violation. The following code handles the error:

Protected Sub gvCompetencies_OnRowDeleting(ByVal sender As Object, ByVal e As GridViewDeleteEventArgs)

Dim TrainingCompetencyId As Integer = Convert.ToInt32(gvCompetencies.DataKeys(e.RowIndex).Value)

Try

TrainingCompetencyElementDAL.Instance.DeleteByTrainingCompetencyID(TrainingCompetencyId)

TrainingCompetency_EventTypesDAL.Instance.DeleteByTrainingCompetencyID(TrainingCompetencyId)

TrainingCompetencyDAL.Instance.Delete(TrainingCompetencyId)

bind()

Catch ex As System.Data.SqlClient.SqlException

If ex.Number = 547 Then 'handle foreign key violation(547)

Dim comp As TrainingCompetency = TrainingCompetencyDAL.Instance.GetTrainingCompetency(TrainingCompetencyId)

lblMsg.Text = comp.Name + " cannot be deleted as it is being used by other tables."

lblMsg.ForeColor = Drawing.Color.Red

End If

End Try

End Sub

Gridview confirm delete

There are two ways I normally use to add confirmation when deleting a record in a gridview:

<asp:gridview id="SearchResults" autogeneratecolumns="false" datakeynames="vbpk_intUserID" runat="server">

<columns>

<asp:hyperlinkfield datatextfield="strEmail" datanavigateurlfields="strEmail" datanavigateurlformatstring="mailto:{0}" headertext="Email" target="_blank" />

<asp:commandfield buttontype="Button" deletetext="Delete" headertext="Delete" controlstyle-cssclass="btn" showdeletebutton="true" />

</columns>

</asp:gridview>


Private Sub SearchResults_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles SearchResults.RowDataBound

If e.Row.RowType <> DataControlRowType.DataRow Then

Return

End If

Dim lastCellIndex As Integer = e.Row.Cells.Count - 1

Dim deleteButton As Button = DirectCast(e.Row.Cells(lastCellIndex).Controls(0), Button)

deleteButton.OnClientClick = "if (!window.confirm('Are you sure you want to delete this record?')) return false;"

End Sub

Confirm delete for GridView's CommandField using JavaScript



<asp:gridview id="SearchResults" autogeneratecolumns="false" datakeynames="vbpk_intUserID" runat="server">

<columns>

<asp:hyperlinkfield datatextfield="strEmail" datanavigateurlfields="strEmail" datanavigateurlformatstring="mailto:{0}" headertext="Email" target="_blank" />

<asp:TemplateField ItemStyle-HorizontalAlign="center" ItemStyle-Width="50">

<ItemTemplate>

<asp:LinkButton ID="delete" runat="server" Text="Delete" CommandName="delete" CssClass="accountButton"

OnClientClick="return confirmDelete();"/>

</ItemTemplate>

</asp:TemplateField>

</columns>

</asp:gridview>


<script type="text/javascript">

Function confirmDelete()

{

var agree=confirm("Are you sure you wish to delete this record?");

If (agree) Then

return true ;

Else

return false ;

}

</script>

Gridview hyperlinkfield

When you use hyperlinkfield like the following, the link for email actually becomes unclickable.

<asp:gridview id="SearchResults" autogeneratecolumns="false" datakeynames="vbpk_intUserID" runat="server">

<columns>

<asp:hyperlinkfield datatextfield="strEmail" datanavigateurlfields="strEmail" datanavigateurlformatstring="mailto:{0}" headertext="Email" target="_blank" />

</columns>

</asp:gridview>


So you have to use TemplateField to solve the problem:


<asp:gridview id="SearchResults" autogeneratecolumns="false" datakeynames="vbpk_intUserID" runat="server">

<columns>

<asp:TemplateField HeaderText="Email">

<ItemTemplate>

<asp:HyperLink runat="server" Text='<%# Eval("strEmail") %>' NavigateUrl='<%# Eval("strEmail", "mailto:{0}") %>' ID="hlEmail"/>

</ItemTemplate>

</asp:TemplateField>

</columns>

</asp:gridview>

Displaying a Formatted Email Addresses in a GridView or DetailsView

Tuesday, January 15, 2008

Performing Cross-Page Posts (2) Typed

As an alternative to using the FindControl() method to retrieve a particular control from the previous page, you can expose the control through a page property. The page ButtonSearchTyped.aspx exposes the txtSearch TextBox through a property named SearchString. The page posts the form data to a page named ButtonSearchResultsTyped.aspx.

ButtonSearchTyped.aspx

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

Public ReadOnly Property SearchString() As String

Get

Return txtSearch.Text

End Get

End Property

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

<title>Button Search Typed</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:Label

id="lblSearch"

Text="Search:"

Runat="server" />

<asp:TextBox

id="txtSearch"

Runat="server" />

<asp:Button

id="btnSearch"

Text="Go!"

PostBackUrl="ButtonSearchResultsTyped.aspx"

Runat="server" />

</div>

</form>

</body>

</html>


ButtonSearchResultsTyped.aspx

<%@ Page Language="VB" %>

<%@ PreviousPageType VirtualPath="~/ButtonSearchTyped.aspx" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

Sub Page_Load()

If Not IsNothing(Page.PreviousPage) Then

lblSearch.Text = String.Format("Search For: {0}", PreviousPage.SearchString)

End If

End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

<title>Button Search Results Typed</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:Label

id="lblSearch"

Runat="server" />

</div>

</form>

</body>

</html>


Notice that the page ButtonSearchResultsTyped.aspx includes a PreviousPageType <%@ PreviousPageType %>directive. This directive casts the value returned by the PreviousPage property as an instance of the ButtonSearchTyped class. Without this directive, the PreviousPage property would return the previous page as an instance of the generic Page class.

ASP.NET 2.0 Unleashed

Monday, January 14, 2008

Performing Cross-Page Posts (1)

By default, if you click a button control, the page containing the control is posted back to itself and the same page is reloaded. However, you can use the PostBackUrl property to post form data to another page.

ButtonSearch.aspx

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

<title>Button Search</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:Label

id="lblSearch"

Text="Search:"

Runat="server" />

<asp:TextBox

id="txtSearch"

Runat="server" />

<asp:Button

id="btnSearch"

Text="Go!"

PostBackUrl="ButtonSearchResults.aspx"

Runat="server" />

</div>

</form>

</body>

</html>


ButtonSearchResults.aspx


<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

Sub Page_Load()

If Not IsNothing(PreviousPage) Then

Dim txtSearch As TextBox = CType(PreviousPage.FindControl("txtSearch"), TextBox)

lblSearch.Text = String.Format("Search For: {0}", txtSearch.Text)

End If

End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

<title>Button Search Results</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:Label

id="lblSearch"

Runat="server" />

</div>

</form>

</body>

</html>


In the Page_Load event handler in ButtonSearchResults.aspx, the PreviousPage property is used to get a reference to the previous page. Next, the FindControl() method is used to retrieve the txtSearch TextBox control from the previous page. Finally, the value entered into the TextBox is displayed in a label on the page.

ASP.NET 2.0 Unleashed

Saturday, January 12, 2008

DateTime Parse & TryParse

1. Using Convert when the value is null, it will set to its default value, whereas using Parse will throw an exception

Dim strDT As String = Nothing

Dim dt As DateTime = Convert.ToDateTime(strDT) 'Result: 1/01/0001 12:00:00 AM

Dim dt1 As DateTime = DateTime.Parse(strDT) 'Result: ArgumentNullException

Console.WriteLine(dt.ToString(), Environment.NewLine)

Dim strA As String = Nothing

Dim intResult As Integer = Convert.ToInt32(strA) 'Result: 0

Dim intResult1 As Integer = Integer.Parse(strA) 'Result: ArgumentNullException

Console.WriteLine(intResult)

Console.ReadLine()

Note:
Convert.ToDateTime("") or DateTime.Parse("") will both throw an exception (String was not recognized as a valid DateTime.)


2. TryParse: Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded. The TryParse method is like the Parse method, except the TryParse method does not throw an exception if the conversion fails. It has the flexibility to set cultureinfo as well.


Dim result As Boolean

Dim datetimeVal As DateTime

'result = DateTime.TryParse("7/12/2004 12:34:56", datetimeVal)

Dim ci As CultureInfo = New CultureInfo("en-US")

result = DateTime.TryParse("4/7/2004 12:34:56", ci, DateTimeStyles.None, datetimeVal)

If result Then

Console.WriteLine(datetimeVal.ToString("dd-MMM-yyyy")) '07-Apr-2004

Else

Console.WriteLine("Parse failed.")

End If

Console.ReadLine()

Int32.TryParse Method


3. This article

Comparing String to Integer Conversion Methods in VB.NET

will compare all the methods which converts string to integer, such as:

1. Val

2. CInt

3. Parse

4.TryParse

5. Convert.ToInt32

The author recommends using Parse & TryParse which have the best Usability, Flexibility and Performance.


4. DateTime samples:


Dim dtNow As DateTime = DateTime.Now

Console.WriteLine("dtNow.ToString: " + dtNow.ToString)

Console.WriteLine("dtNow.Date: " + dtNow.Date)

Console.WriteLine("dtNow.ToShortDateString: " + dtNow.ToShortDateString)

Console.WriteLine("dtNow.ToLongDateString: " + dtNow.ToLongDateString)

Console.WriteLine("dtNow.ToShortTimeString: " + dtNow.ToShortTimeString)

Console.WriteLine("dtNow.ToLongTimeString: " + dtNow.ToLongTimeString)

Console.WriteLine("dtNow.ToUniversalTime: " + dtNow.ToUniversalTime)

Console.WriteLine("dtNow.DayOfYear: " + dtNow.DayOfYear.ToString)

Console.WriteLine("dtNow.DayOfWeek: " + dtNow.DayOfWeek.ToString)

Console.WriteLine("dtNow.Day: " + dtNow.Day.ToString)

Console.WriteLine("dtNow.Month: " + dtNow.Month.ToString)

Console.WriteLine("dtNow.Year: " + dtNow.Year.ToString)

Console.WriteLine("dtNow.AddDays(1): " + dtNow.AddDays(1))

Console.ReadLine()

Result:


dtNow.ToString: 13/01/2008 12:17:09 PM
dtNow.Date: 13/01/2008
dtNow.ToShortDateString: 13/01/2008
dtNow.ToLongDateString: Sunday, 13 January 2008
dtNow.ToShortTimeString: 12:17 PM
dtNow.ToLongTimeString: 12:17:09 PM
dtNow.ToUniversalTime: 13/01/2008 1:17:09 AM
dtNow.DayOfYear: 13
dtNow.DayOfWeek : Sunday()
dtNow.Day: 13
dtNow.Month: 1
dtNow.Year: 2008
dtNow.AddDays(1): 14/01/2008 12:17:09 PM

This article String Formatting in C# has all the basic number formatting specifiers.

Friday, January 11, 2008

Application Domain




Process Basics:


  • There will be at least one thread executing instructions inside of the process, and in most cases there are multiple threads. If the program opens any files or other resources, those resources will belong to the process.
  • aspnet_wp.exe is the ASP.NET worker process which hosts all the ASP.NET applications on Windows XP and Windows 2000, this process runs under the security context of the local ASPNET account
  • w3wp.exe is the process runs under the NETWORK SERVICE account by default on Windows 2003 and Vista.

Why AppDomain?

  • More efficient: Application domains are more efficient than processes, enabling multiple assemblies to be run in separate application domains without the overhead of launching separate processes.
  • More reliable: Use application domains to isolate tasks that might cause a process to terminate. If the state of the application domain that’s executing a task becomes unstable, the application domain can be unloaded without affecting the process. This technique is important when a process must run for long periods without restarting.
  • Unload assembly: If an assembly is loaded into the default application domain, the assembly cannot be unloaded from memory while the process is running. However, if you open a second application domain to load and execute the assembly, the assembly is unloaded when that application domain is unloaded. Use this technique to minimize the working set of long-running processes that occasionally use large dynamic-link libraries (DLLs).

AppDomain Basics:

  • The .NET runtime uses an AppDomain as a container for code and data, just like the operating system uses a process as a container for code and data.
  • Application domain is not a secure boundary when the application runs with full trust. Applications running with full trust can execute native code and circumvent all security checks by the .NET runtime. ASP.NET applications run with full trust by default.
  • An AppDomain is a great solution for the ISP who is hosting hundreds of applications. Each application can exist inside an isolated AppDomain, and many of these AppDomains can exist inside of a single process – a cost savings.
  • In order to communicate or pass objects between AppDomains, you’ll need to look at techniques in .NET for communication across boundaries, such as .NET remoting or web services.
  • If you copy an updated dll into an application’s bin subdirectory, the ASP.NET runtime recognizes there is new code to execute. Since ASP.NET cannot swap the dll into the existing AppDomain , it starts a new AppDomain. The old application domain is “drain stopped”, that is, existing requests are allowed to finish executing, and once they are all finished the AppDomain can unload. The new AppDomain starts with the new code and begins taking all new requests.
  • Not only can you isolate entire applications from each other, but you can also isolate individual parts (assemblies) from the rest of your application.
  • The runtime host usually determines when and if additional application domains are created. Runtime hosts are free to use different application domain strategies to suit their application execution model and security requirements.
  • Application isolation ensures that one application cannot purposefully or inadvertently modify the memory, or access the resources owned by another.

Shadow Copies:

  • Typically, when a dll loads into a process, the process locks the dll and you cannot overwrite the file on disk. However, AppDomains have a feature known as Shadow Copy that allows assemblies to remain unlocked and replaceable on disk.
  • The runtime initializes ASP.NET with Shadow Copy enabled for the bin directory. The AppDomain will copy any dll it needs from the bin directory to a temporary location before locking and loading the dll into memory. Shadow Copy allows us to overwrite any dll in the bin directory during an update without taking the web application offline.

In summary:

  • AppDomain is more efficient than process
  • A single process can have many AppDomains
  • An AppDomain can execute many assemblies
  • An AppDomain cannot unload an assembly, you can create another AppDomain to load the assembly and after finish executing the assembly, you can unload the AppDomain in order to unload the assembly
  • A change to the bin folder will cause the application to restart because the AppDomain cannot unload an assembly, so the AppDomain has to be unloaded first, then re-loaded to pick up the new assembly
  • When create a IIS web application, you create an application domain for it.
  • IIS web applications cannot share session objects because objects cannot be shared between AppDomains.

MCTS Self-Paced Training Kit (Exam 70-536): Microsoft .NET Framework 2.0 Application Development Foundation

What ASP.NET Programmers Should Know About Application Domains

Programming .NET Security

Sunday, January 6, 2008

TreeView Database Design

We recently come cross a project where we need to design a training course pathway. To be able to finish the final course, one need to do all the prerequisites of this course first. The prerequisites can have options which means you can either finish one or another to be eligible for the final course. There coule be prerequisites under prerequisites as well. So this is a recursive datasource.
We came up with a solution using asp.net treeview control. The most difficult part of this job is the database design. Here is our design:

The main relationships are:

  • One course can be many nodes
  • One node can have many options
  • One option can have many nodes

In order to populate the hierarchical data structure for the treeview, we need to

  • Step1: Start with the top level nodes, then find their options
  • Step2: Find nodes under these options
  • Step3: Find options of the nodes in step2
  • Step4: Keep searching recursively till no nodes are found

Friday, January 4, 2008

Install Visual Studio 2005 on Vista

There is a compatibility issue between Windows Vista and Visual Studio 2005. To solve this problem, install the following updates:
Visual Studio 2005 Service Pack 1
Visual Studio 2005 Service Pack 1 Update for Windows Vista

There is also a compatibility issue between Windows Vista and SQL Server 2005.
Microsoft SQL Server 2005 on Microsoft Windows Server 2008 or Microsoft Windows Vista

To install IIS 7 to serve dynamic content:

  • Click the Start button , click Control Panel, click Programs, click Programs and Features,‌ and then click Turn Windows features on or off. If you are prompted for an administrator password or confirmation, type the password or provide confirmation.
  • In the list of Windows features, click the plus sign (+) next to Internet Information Services, click the plus sign (+) next to World Wide Web Services, click the plus sign (+) next to Application Development Features, select the dynamic content features you want to install, and then click OK.

Wednesday, January 2, 2008

ByVal vs ByRef (2)

  • Avoid defining methods that take arguments passed by reference
  • There is rarely the need to pass a reference type to a by-reference parameter because a by-value parameter still lets the method read and modify all the field and properties of the object
  • The only exception to this rule is when the method must be allowed to set the parameter to a null object reference or to make it point to a different object

There are four cases in total:

  • Passing value types by value: A copy of the value type is created and passed to the method. This exhibits no side effects because the callee cannot change any member of the original value type. (Cannot change anything)
  • Passing reference types by value: A copy of the pointer to the object is created and passed to the method. The method can use the parameter to access and change the fields and properties of the object. If the method changes the parameter (e.g. it assigns it a null value or makes it point to a different instance), the original object variable is not affected. (Can only change fields and properties)
  • Passing value types by reference: A pointer to the original value is passed to the method. When a value type argument is passed by reference, the code in the method can modify fields and properties in the value type. This case is mostly used in nonvoid/function methods when you want to return additional information to the caller or in COM interop scenarios. (Can only change fields and properties)
  • Passing reference types by reference: The address of the pointer to the object is passed to the method. The callee can change the object's fields and properties, plus all the changes to the pointer are reflected in the original object variable. If the method sets the argument to a null object reference, the original object variable is set to null as well. (Can change anything)

Practical Guidelines and Best Practices for Microsoft Visual Basic and Visual C# Developers

ByVal vs ByRef (1)


' *** Wrong: the method doesn't need to modify the pointer

Sub ClearProperties(ByRef u As User)

u.FirstName = Nothing

u.LastName = Nothing

End Sub

' *** Corrent: the object is passed by value

Sub ClearProperties(ByVal u As User)

u.FirstName = Nothing

u.LastName = Nothing

End Sub

' *** Corrent: the method assigns a new object reference

Sub ClearProperties(ByRef u As User)

u = New User

End Sub

Tuesday, January 1, 2008

ASP.NET AJAX Page Methods (2) Demo


<%@ Page Language="vb" AutoEventWireup="false" Codebehind="Default.aspx.vb" Inherits="PageMethodsDemo._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript">

Function Add()

{

var x = $get("txtX").value;

var y = $get("txtY").value;

PageMethods.AddNumbers(x,y,OnSucceeded,OnFailed);

}

function OnSucceeded(result) {

$get("lblResult").innerHTML = result;

}

function OnFailed(error) {

// Alert user to the error.

alert(error.get_message());

}

</script>

</head>

<body>

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />

<div>

<asp:TextBox ID="txtX" runat="server"></asp:TextBox>

+

<asp:TextBox ID="txtY" runat="server"></asp:TextBox>

=

<asp:Label ID="lblResult" runat="server"></asp:Label><br />

<asp:Button ID="btnAdd" runat="server" OnClientClick="Add(); return false;" Text="Add" />

</div>

</form>

</body>

</html>



Imports System.Web.Services

Partial Public Class _Default

Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

End Sub

<WebMethod()> _

Public Shared Function AddNumbers(ByVal x As Integer, ByVal y As Integer) As Integer

If Not IsNumeric(x) AndAlso Not IsNumeric(y) Then

Throw New Exception()

End If

Return x + y

End Function

End Class

ASP.NET AJAX Page Methods (1) Intro

  • By using page methods, the amount of data transferred between client and server will be greatly reduced compared with UpdatePanel
  • Using Ajax with web service sometimes seems overkill
  • Page methods communicate directly with an ASP.NET AJAX-enabled page and pass JSON request and response messages back and forth, just as WebMethods do in Web services.
  • Each code behind method is accessed from the client-side by using the PageMethods proxy class.
  • You must set the ScriptManager control's EnablePageMethods property to true
  • Need to add "WebMethod" attribute on static methods
  • Using page methods when you want to include the method inside a page, you cannot use it with user control
  • Since page methods must be static/shared methods, you cannot access any instance member of a class such as controls in the page or ViewState etc.

Using Page Methods in ASP.NET AJAX

Perspectives on ASP.NET AJAX

PageMethods in ASP.Net AJAX

Creating and Consuming ASP.NET AJAX Page Methods