Sunday, December 13, 2009
Running a Periodic Process in .NET using a Windows Service
Usually this question comes up when the need arises to do any of the following examples: checking for new information, reporting, sending emails, updating content on a screen, maintenance, and the examples go on and on.
I prefer to relegate this type of task to a Windows Service. The service can be created using Visual Studio .NET and then installed on your machine or server. The service is always running (once started) and provides a good mechanism for preforming repeated background tasks like periodic execution.
After doing research on this topic myself, I have found the best way to have a process run on a set time interval is to use a 'ThreadPool.RegisterWaitForSingleObject' from the System.Threading namespace. As from the MSDN on this method: "Registers a delegate to wait for a WaitHandle, specifying an integer for the time-out in milliseconds."
The 'RegisterWaitForSingleObject' method registers a delegate to wait for a WaitHandle, specifying a timeout. It allows this service to tell the thread pool, "Hey, could you call me when this object is signalled or the timeout has elapsed? Thanks." The method queues the specified delegate to the thread pool (The thread pool uses background threads). A worker thread will execute the delegate when one of the following occurs:
-The specified object is in the signaled state.
-The time-out interval elapses.
This method will repeatedly call the delegate each time the timespan value has elapsed, or until the 'Unregister' method has been called. The callback method registered can do anything you need. The actual method will probably be local to the service, but from there you could make a call to a .dll, WCF or .asmx service, etc. to reuse existing functionality that may already exist. You just need the Windows Service to the the work of waking up every so often to do some work.
You can implement 1:many of these delegates to run as few or as many repeated tasks from within a Windows Service. I must give credit to the following Blog entry which really helped get me started with using this method: Periodic Execution in .NET <<--Code
The blog link above has a terrific easy to follow code example with explanations of implementing the RegisterWaitForSingleObject within a Windows Service, so I will not duplicate it here. I will just say that I myself have implemented the code and expanded on it, and can say that this is a great way to handle repeated processing of a task on a set time interval.
And lastly, you might be saying "I don't know how to create and use a Windows Service in .NET!". Well to get you going on that (there are quite easy by the way to get up and running), check out the following site:
Walkthrough: Creating a Windows Service Application in the Component Designer
Saturday, December 12, 2009
How To: Bind an Enum to an ASP.NET DropDownList
You may find that you need or want to bind that enumeration directly to a control such as an ASP.NET DropDownList. The DropDownList is obviously an easy fit for an enumeration as it uses a key-value pair style of data for its 'Text' and 'Value' attributes which align to an enumeration's member name and initializer attributes.
For all of the following examples, we will work with the following simple enumeration using 'Months of the Year' (yes, it may be possible to get this same info by looping through a DateTime object and adding 1 month to each iteration, but this is just to show a basic example of a simple enumeration type):
Public Enum Months
January = 1
February = 2
March = 3
April = 4
May = 5
June = 6
July = 7
August = 8
September = 9
October = 10
November = 11
December = 12
End Enum
Accomplishing this task can be done in so many ways. One way is to directly bind just the enum member values to a DropDownList without its associated name. This may acceptable in the situation of months in the year where only the actual integer value is needed. This code to bind just the values is displayed below:
'Populate the months dropdown (from Enumeration)
Dim tEnumMonths As Type = GetType(Months)
Me.ddlMonths.DataSource = System.Enum.GetValues(tEnumMonths)
Me.ddlMonths.DataBind()
'Insert blank '0' value at beginning of DropDown
Me.ddlMonths.Items.Insert(0, New ListItem(" "))
However, most of the time you will probably find that you want to bind both the member name and its associated value. This way you can display to the user a description and extract its value server side for storing in a database, processing business rules, etc. In this case we need to transform or port the enumeration data from the enum type into a bindable object type to the ASP.NET DropDownList. There are so many bindable types; a few examples are: DataSet, DataTable, DataView, Array, ArrayList, HashTable, Object Collection (Generics), and many more.
In the following I will focus on (3) additional methods. All will involve calling a Shared function in a 'Utilities' call that is accessible by all of the UI. This type functionality is not specific to any specific object and holds no concise responsibility other than being a 'Helper' function. Therefore these methods are Shared and do not require class instantiation to access.
The 1st method will take the DropDownList in question and the Enum type as parameters and perform all of the work necessary to bind the data. This method is a full on binding method specific to an ASP.NET DropDownList, so in that sense it is quite powerful, but offers not much reuse beyond binding to this control type.
Public Shared Sub BindDDLToEnum(ByVal EnumType As Type, ByVal DropDown As UI.WebControls.DropDownList, ByVal InsertBlankZeroValue As Boolean)
'Get the Name (String) values from the Enum
Dim EnumNames As String() = System.Enum.GetNames(EnumType)
'Get the Values (Integer) from the Enum
Dim EnumValues As Array = System.Enum.GetValues(EnumType)
'If the caller requested a blank entry with a value of 0 entered, do that now.
If InsertBlankZeroValue Then
'Add a space and a '0' value at the beginning
DropDown.Items.Add(New Web.UI.WebControls.ListItem(" ", 0))
End If
'Loop through the Enum values and add the name,value pair to a 'ListItem' object to be directly inserted into the DropDownList
For i As Integer = 0 To EnumNames.Length - 1
DropDown.Items.Add(New Web.UI.WebControls.ListItem(EnumNames(i), Integer.Parse(EnumValues.GetValue(i))))
Next
'If a blank '0' value was entered, make sure it is the default selected item. This is important
'for RangeValidator controls and the like to pick up on and validate against.
If InsertBlankZeroValue Then
DropDown.ClearSelection()
DropDown.Items.FindByValue(0).Selected = True
End If
End Sub
As you can also see above, I chose to add an additional boolean parameter named 'InsertBlankZeroValue'. This value dictates if a blank string with a '0' value is inserted as the 1st element in the DropDownList. This functionality could easily be modified, removed, or even expanded (i.e. take additional parameters specifying default name and value rather than '0' and blank) to suit your individual needs.
Now you may want to make some more abstract methods that transform the Enum into a bindable type, but don't want to bind it immediately to a control. In this case I have made (2) more sample methods that simply take the Enum type and return a key-value pair object. The 1st method returns a HashTable as shown below:
Public Shared Function GetHashTableFromEnum(ByVal EnumType As Type) As Hashtable
'Get the Name (String) values from the Enum
Dim EnumNames As String() = System.Enum.GetNames(EnumType)
'Get the Values (Integer) from the Enum
Dim EnumValues As Array = System.Enum.GetValues(EnumType)
'Declare a HashTable to hold the Enum name,value pairs
Dim ht As New Hashtable()
'Loop through all of the name,value pairs in the Enum and add them as new elements to the HashTable
For i As Integer = 0 To EnumNames.Length - 1
ht.Add(EnumNames(i), Integer.Parse(EnumValues.GetValue(i)))
Next
Return ht
End Function
The main issue you will note about the method above is that the HashTable returned will indeed have the enum values in a key-value format but they will not be in the order that they were within the Enum. Typically this is an unwanted result. This class could be expanded to implement an ICompare interface and expose a sorting routine to then sort the HashTable values. However, other object types will give us this functionality with built in ability.
The last type I wrote a Utilities method for that solves the sorting issue is by returning a 'DataTable' object from the Enum type passed in as an argument. Once the DataTable is created by making a table with (2) columns named "key" and "value", we can create a DataView from it using the sort we specify and then return a DataTable type back from the DataView. The code for this is shown below:
Public Shared Function GetDataTableFromEnum(ByVal EnumType As Type) As DataTable
'Get the Name (String) values from the Enum
Dim EnumNames As String() = System.Enum.GetNames(EnumType)
'Get the Values (Integer) from the Enum
Dim EnumValues As Array = System.Enum.GetValues(EnumType)
'Declare a new DataTable with column names "key" and "value"
Dim dt As New DataTable()
dt.Columns.Add("key", GetType(String))
dt.Columns.Add("value", GetType(Integer))
'Loop through all of the name,value pairs in the Enum and add them as new rows to the DataTable
For i As Integer = 0 To EnumNames.Length - 1
Dim dr As DataRow = dt.NewRow
dr("key") = EnumNames(i)
dr("value") = Integer.Parse(EnumValues.GetValue(i))
dt.Rows.Add(dr)
Next
'Sort the DataTable by the value column
Dim dv As DataView = dt.DefaultView
dv.Sort = "value asc"
'Apply the sorted DataView back to the DataTable to be returned
dt = dv.ToTable()
Return dt
End Function
Once again it is important to note that this method is just a base example and could be customized easily to fit your needs. As you can see above, the method automatically sorts based on the "value" column in ascending order. You could add parameters to the method that could dictate the sort. And you could also change this method and just have the DataView returned rather than extracting a DataTable back out of it. Both types can be used as the DataSource for a control like an ASP.NET DropDownList.
Below is the code used to make the call to the Utilities class and have it bound to our 'Months' enumeration.
'Option 1: Bind the DropDownList immdeatly to the Enum type
Utilities.BindDDLToEnum(GetType(Months), Me.ddlMonths, True)
'Option 2: Get a HastTable back from the Enum, and use it however needed:
Dim MyHt As New Hashtable()
MyHt = Utilities.GetHashTableFromEnum(GetType(Months))
'Option 3: Get a DataTable back and then bind on the columns named "key" value"
Dim MyDt As New DataTable
MyDt = Utilities.GetDataTableFromEnum(GetType(Months))
'Set the Text and Value properties which correspond to the "value" and "key" elements
'of the DataTable object created and populated above
Me.ddlMonths.DataTextField = "key"
Me.ddlMonths.DataValueField = "value"
'Set the DataSource Bind the DataView to the passed in DDL control
Me.ddlMonths.DataSource = MyDt
Me.ddlMonths.DataBind()
Lastly is a picture of the bound ASP.NET DropDownList:
The main purpose of this was just to get you as the developer started when needing to bind an Enum to a control like an ASP.NET DropDownList. You can easily expand or modify any of the methods to suit your needs providing the most streamlined use and reusability for your application.
Tuesday, November 17, 2009
.NET Object Collections Using Generics 101
So the next question might be, "Well why do I need that?" Think of another common way to organize relation data using a non-strongly type traditional DataSet. A DataTable within a DataTable has rows and columns. Typically to reference a value within that DataSet we might have a line of code similar to the following:
Dim MyValue As String = ds.Tables("MyTable1").Rows(0).Item("FirstName").ToString()
Now that does work, however that is a lot of hardcoding and can be difficult to keep up with. Especially on a multi developer project. Imaging trying to remember all of those column names if that DataSet was passed back to the UI to be bound to a control or populate others. This is where a nice entry point into a list of objects arises. Of course developers could comment on the several reasons using lists of objects is advantageous, but I will take the approach to a developer that is using native ADO.NET objects to do the same thing.
I will provide a simple example to help beginners understand how to put together a list of objects using the 'List(of T)' class. First let's start by looking at the following simple class named 'Customer':
Public Class Customer
Private mFirstName As String = String.Empty
Private mLastName As String = String.Empty
Private mID As Integer = 0
Public Sub New()
'Default class Constructor
End Sub
Public Property FirstName() As String
Get
Return mFirstName
End Get
Set(ByVal value As String)
mFirstName = value
End Set
End Property
Public Property LastName() As String
Get
Return mLastName
End Get
Set(ByVal value As String)
mLastName = value
End Set
End Property
Public Property ID() As Integer
Get
Return mID
End Get
Set(ByVal value As Integer)
mID = value
End Set
End Property
Public Function ShowFullName() As String
'Simple class method; just for show
Return Me.FirstName + Me.LastName
End Function
End Class
Now at this point we may have received multiple rows back from the database containing data with the elements mapping to the properties above. Previously, we could have placed this data into a DataSet to pass back to the UI as mentioned before. This time we are going to build up a list of objects to use. Now in this case you may still have used an ADO.NET DataAdapter to get the data from a stored procedure and it is currently in a DataTable object. No problem, now is the time to place that data into an object instance (1 DataRow = 1 Object of type Customer) and then add that to the list. Let's take a look how that is done below:
'Create an Customer Object
Dim MyCustomer As New Customer()
'Create a List of objects of type Customer
Dim MyCustomerLst As New List(Of Customer)
'Iterate through the data returned in the DataTable
For Each dr As DataRow In dt.Rows
'Create a new instance of the Customer object to place this iterations values
MyCustomer = New Customer()
'Add the data to the object's properties
If Not IsDBNull(dr("FirstName")) Then MyCustomer.FirstName = dr("FirstName")
If Not IsDBNull(dr("LastName")) Then MyCustomer.LastName = dr("LastName")
If Not IsDBNull(dr("CustomerID")) Then MyCustomer.ID = dr("CustomerID")
'Add the single object instance created above to the 'List' of objects
MyCustomerLst.Add(MyCustomer)
Next
At this point the object collection named 'MyCustomer' can be passed around your application's layers as a type of 'List(of Customer)'. For example take a look to the following method that takes the list as a parameter, and then loops through it to use its values:
Public Function GenerateCustomerList(ByVal CustomerLst As List(Of Customer)) As String
Dim sb As New StringBuilder
'Iterate through each 'Customer' object instance in the List(of Customer) passed into method:
For Each SingleCustomer As Customer In CustomerLst
'Build a String in the format of: John Smith ID: 1234
sb.AppendLine(SingleCustomer.FirstName + " " + SingleCustomer.LastName + " ID: " + SingleCustomer.ID.ToString())
Next
'Return the appended String
Return sb.ToString()
End Function
So as you can see we were able to iterate through the object collection and being able to refer to the values by object property name rather than a hardcoded value representing the original column named returned from the database. One might say in the example above that we did at one point reference the column name when adding the data to the 'Customer' object instance. Yes, that is true but with this methodology you need only to reference it once and the location of that reference is typically at a low level either in the DAL or at the bottom of the BLL depending on your design. Therefore, if there were database changes that affected those names, they could be changed in one place rather than scattered throughout the UI and entire application.
Passing around a list of objects is much preferable to passing around traditional ADO.NET objects in many situations. Also, there are other types that may have been used similarly that could also be replaced using object collections. An example could be an Array or ArrayList. In fact performance wise, object collections are very good. Read the following excerpt from the MSDN:
"In deciding whether to use the List(Of(T)) or ArrayList class, both of which have similar functionality, remember that the List(Of(T)) class performs better in most cases and is type safe."
There are so many uses for a list of objects, and this entry was just to describe one usage and to provide the developer new to using the List(of T) class some ideas on how they may expand on it. Once you begin to harness the power of OOP and the basic component of it: the class, you will discover an entire new set of powerful tools the .NET Framework offers as discussed here using a List(of Customer).
***UPDATE*** You can imporve this code one step further by using LINQ to populate the list of objects directly rather than manually looping through each DataRow. To see the code look the post of mine from the link below:
How To: Populate a List of Objects from a DataSet Using LINQ
Tuesday, November 10, 2009
How To: Sort Items in an ASP.NET ListBox Control
The work is done by copying the ListBoxItems out of the ListBox and into a List(of ListItem) object collection. This secondary collection can then be manipulated via a 'Comparison' delegate with the address of a method that will compare the (2) items and return them in order. The ordered List of objects is then added back to the original control after being cleared, and the result is having the items in order.
All that the caller needs to do is pass the ListBox control in as a parameter. This could possibly be called on PostBack when the item is added, or maybe upon some other user interaction that calls this method. Another idea might be to use an AJAX UpdatePanel around the ListBox to asynchronously postback to sort the items without a full postback.
Here are the (2) methods needed to sort the ListBox control:
Public Shared Sub SortListBox(ByVal lbxId As ListBox)
Dim t As New List(Of ListItem)()
Dim compare As New Comparison(Of ListItem)(AddressOf CompareListItems)
'Iterate through each ListItem in the Listbox, and add them to the 'List' object
For Each lbItem As ListItem In lbxId.Items
t.Add(lbItem)
Next
'Sort the List
t.Sort(compare)
'Clear the Listbox passed in, and add the sorted list from above
lbxId.Items.Clear()
lbxId.Items.AddRange(t.ToArray())
End Sub
Public Shared Function CompareListItems(ByVal li1 As ListItem, ByVal li2 As ListItem) As Integer
'Return the strings in order that have been compared:
Return [String].Compare(li1.Text, li2.Text)
End Function
And here is an example of calling the method above to sort the ListBoxItems:
'Sort the ListBox control items on the .aspx page
SortListBox(Me.lbxMyItems)
That's all you need to sort the ListBox control. You could also easily change the 'CompareListItems' method to compare the items other than by 'String' which will ultimately make the items appear in alphabetical order. If you did this you may want to overload or extend the original method so that it could be called to sort the items in various ways.
Monday, November 2, 2009
Tools for Converting C# code to VB.NET (or vice versa) and a little => ... Function(), Lambdas too
- developerFusion's Convert C# to VB.NET - This is probably the most well know site and referenced most often. I typically start with this one: http://www.developerfusion.com/tools/convert/csharp-to-vb/
- Code Converter Provided by Telerik - This is another great and stable converter online. I typically go to this one if the code to convert is complex or there were any issues with the converter: http://converter.telerik.com/
- KamalPatel.Net - Convert C# to VB .NET - Several years ago I used this one as the defacto converter, but somewhere along the lines the code I was converting was getting too complex, or the site was not upkept anymore because it shows issues converting often. I now come here lastly: http://www.kamalpatel.net/ConvertCSharp2VB.aspx
Now, one of the issues all the converters seem to have issue with is .NET Lambda Expressions. Recently, I have found several powerful code snippets in C# including Labmda expressions that none of the converters would convert properly. This code will need a little extra help in getting it converted. Below I have a brief example of a C# Labmda expression and the equivelent VB.NET code that I had to modify. Hopefully, this code will help guide readers to get started with a proper conversion of Lambda expressions.
The C# version:
.Aggregate(new StringBuilder(), (sb, node) => sb.Append(node.ToString()), sb => sb.ToString());
The VB.NET version:
.Aggregate(New StringBuilder(), Function(sb, node) sb.Append(node.ToString()), Function(sb) sb.ToString())
Both code examples take use of passing values to a function to shorthand the return, however in VB.NET the syntax is more explicit with the 'Function' statement being required. A good reference for Lambda expressions for each language can be found below.
Lambda Expressions (VB.NET):
http://msdn.microsoft.com/en-us/library/bb531253.aspx
Lambda Expressions (C#):
http://msdn.microsoft.com/en-us/library/bb397687.aspx
This was by no means a full entry on .NET Lambda expressions, but I just wanted to briefly highlight some of the differences syntactically between the (2) languages, and where the converters may have issue with more complex code.
Tuesday, October 20, 2009
How To: Strip Illegal XML Characters from a String in VB.NET
"Response is not well-formed XML System.Xml.XmlException: ' ', hexadecimal value 0x13, is an invalid character."
The origination of this cause was due to my users copying and pasting data from Microsoft Word into a WYSIWYG editor that was preserving illegal characters, such as the one ('!!') shown in the exception above.
Rather than put in place some calls shielding the web service from the bad data, I decided to research building a method that would strip out and remove illegal characters prior to placing the data into my business object on the front end. Of coarse I could check it on the back end too to be thorough, but this is what was appropriate for my scenario.
There turns out to be some information on this topic, but oddly enough most of the solutions were written for Java and PHP. The .NET solutions I found were only half working and not complete. The best solution I came across was one written in Java at Ben J. Christensen's Blog. With the help from users on the ASP.NET forums here I was able to place all the information I had found together to come up with a VB.NET version of the code. I really credit Ben and the forum for the base code help; thank you.
The code's purpose is to take the passed in string value, and check each character 1 by 1 to see if any illegal XML characters exist. All valid characters are re-appended to the output, and illegal characters are omitted.
If you need the C# version check the forum link I provided above. The main difference is that the 'AscW' function that wraps the character in focus is not required in C#. This is because C# and VB.NET deal differently in character to integer conversions. The final code is below, and hopefully this .NET version will help somebody in the future as it did for me.
Public Shared Function RemoveIllegalXMLCharacters(ByVal Content As String) As String
'Used to hold the output.
Dim textOut As New StringBuilder()
'Used to reference the current character.
Dim current As Char
'Exit out and ruturn an empty string if nothing was passed in to method
If Content Is Nothing OrElse Content = String.Empty Then
Return String.Empty
End If
'Loop through the lenght of the content (1) character at a time to see if there
'are any illegal characters to be removed:
For i As Integer = 0 To Content.Length - 1
'Reference the current character
current = Content(i)
'Only append back to the StringBuilder valid non-illegal characters
If (AscW(current) = &H9 OrElse AscW(current) = &HA OrElse AscW(current) = &HD) _
OrElse ((AscW(current) >= &H20) AndAlso (AscW(current) <= &HD7FF)) _
OrElse ((AscW(current) >= &HE000) AndAlso (AscW(current) <= &HFFFD)) _
OrElse ((AscW(current) >= &H10000) AndAlso (AscW(current) <= &H10FFFF)) Then
textOut.Append(current)
End If
Next
'Return the screened content with only valid characters
Return textOut.ToString()
End Function
Someone had asked how this method could be modified to accept and return an 'XmlDocument' type. The method only needs a few small code changes to support this, and would make a good overload to the original funtion. You will need to import the System.XML and System.IO namespaces for this overload.
Public Shared Function RemoveIllegalXMLCharacters(ByVal XmlDoc As XmlDocument) As XmlDocument
'Use a StringWriter & XmlTextWriter, to extract the raw text from the XmlDocument passed in:
Dim sw As New StringWriter()
Dim xw As New XmlTextWriter(sw)
XmlDoc.WriteTo(xw)
Dim Content As String = sw.ToString()
'Used to hold the output.
Dim textOut As New StringBuilder()
'Used to reference the current character.
Dim current As Char
'Exit out and ruturn an empty string if nothing was passed in to method
If Content Is Nothing OrElse Content = String.Empty Then
Return Nothing
End If
'Loop through the lenght of the content (1) character at a time to see if there
'are any illegal characters to be removed:
For i As Integer = 0 To Content.Length - 1
'Reference the current character
current = Content(i)
'Only append back to the StringBuilder valid non-illegal characters
If (AscW(current) = &H9 OrElse AscW(current) = &HA OrElse AscW(current) = &HD) _
OrElse ((AscW(current) >= &H20) AndAlso (AscW(current) <= &HD7FF)) _
OrElse ((AscW(current) >= &HE000) AndAlso (AscW(current) <= &HFFFD)) _
OrElse ((AscW(current) >= &H10000) AndAlso (AscW(current) <= &H10FFFF)) Then
textOut.Append(current)
End If
Next
'Build a new XMLDocument to return containing the screened content with only valid characters
Dim XmlDocClean As New XmlDocument
XmlDocClean.LoadXml(textOut.ToString())
Return XmlDocClean
End Function
Wednesday, October 14, 2009
How To: Use 'Edit and Continue' Debugging Functionality in VS.NET 2008
Visual Studio .NET has claimed for some time now to have 'Edit and Continue' capabilities. Several years ago, I jumped all over it for my ASP.NET development, but could never get it to actually work. To be honest I gave up on it, and assumed it did not work for ASP.NET development and was for mainly for Win Forms or other types of thick client development.
Well somewhere along the way it has become (or always has been and I didn't configure it properly) functional, and that will save me a lot of time. I can't count how many times I have been 5 levels deep into code and need to make a tiny change. I just got so used to pressing 'Stop' in VS.NET, making the changes, and then starting all over again. It didn't dawn on me to check out the 'Edit and Continue' functionality until something I read recently peaked my interest.
I know a lot of you may read this and say... "You didn't know about this???" Yes I did, but never obviously configured it properly or something else. So this post is more for the seasoned developers or new guys that may have let the 'Edit and Continue' functionality in ASP.NET projects go by the wayside because you could never get it to work either.
It is really simple to implement in VS.NET 2008, and really only involves (2) steps to get the functionality working. The only prerequisite is that you are using a 'Web Application' project type. The 'Website' project type in VS.NET does not have the 'Edit and Continue' functionality and will display a message like: "The source file has changed..." if you attempt to make changes while debugging, and will not allow changes.
If you are using a 'Web Application' project type here are the (2) steps you need to do to get the 'Edit and Continue' functionality to work in an ASP.NET app:
- In Tools -> Options -> Debugging -> Edit and Continue, make sure 'Enable Edit and Continue' is selected. In mine I left the default options selected and did not make any further changes.
- Double click on 'My Project' in 'Solution Explorer' (or alternatively, right click your project and select 'Properties'). From here select the 'Web' tab. Under 'Servers' make sure 'Use Development Server' is selected (not IIS), and finally, make sure to check the checkbox that states 'Enable Edit and Continue'.
After you have configured the above (2) steps, set a breakpoint on some code. I tried switching some string values and even variable names and then continue debugging, and everything worked!
Again, this post doesn't really highlight anything brand new in VS.NET, but is really just there to help dust something off that some of us may have forgotten about or overlooked.
Wednesday, October 7, 2009
VSLive! Orlando 2009 Thoughts and Comments
My 1st impression of this conference vs. the one from (2) years ago was how much the attendance was down. In Vegas (2) years ago, there must have been 1000 attendees. I think this time I overheard one of the conference organizers state that there were about 350 attendees. I do not attribute any of this to the conference content or presenters, but rather to the economy. The conference this time around was about $1400 with a 'buy one get one free' option a few months ago. Even at this discounted cost (which I believe is down from around the $1900 we paid (2) years ago in Vegas), it is still a lot for companies of all sizes where the 1st item to get cut in budgets is typically training.
One note for those reading this that have never been to a VSLive! conference and are wondering about attending. At $1400 (give or take) to go to the conference, odds are the entire team will not be able to go. In actuality it works out better anyways as I will explain. This conference is probably best for Software Engineers with 5+ years of development experience and a solid knowledge of Microsoft .NET Technologies. The main sessions (not including the pre-conference day long workshops) are 75 minutes each with a 15 minute break in between. 75 Minutes on ASP.NET MVC, WCF, WF, or TFS is obviously not enough to learn the entire topic, but it gives seasoned engineers 'food for thought' on new or existing technologies, which is GREAT and why I enjoy it so much. However, if you have a developer on your team that still thinks a 'Class Object' is an apple (object) on a teacher's desk (class), then this is not for them.
Another comparison I have between the Vegas conference and the Orlando conference was the 'Passport Gaming Lounge'. In Vegas it had black leather couches to watch movies, lots of comfortable seating, and seemed to be really popular because the room was always packed. In Orlando, they used those same uncomfortable conference room chairs with the snacks and drinks constantly being out and waiting for more. It didn't have that same 'oasis' feel that the one in Vegas had. It is a nice perk for these (4) day long conferences.
A traditional event at the VSLive! conference is the 'VSLive! After Dark' event typically held on the 2nd or 3rd day of the conference in the evening for attendees to network and kick back. It also gives another chance to meet in person with the presenters or to ask questions which is great. In Vegas, it was an 'all you can drink' really kick back and have a good time event. The one here in Orlando still had the framework of a nice event, but fell a bit short and attendance was low. I only networked with one other set of developers from Atlanta. I think the downfall may have been the (1) drink coupon we received as compared to the 'all you can drink' from before. And to add on a glass of wine was $9.00... no thank you. I really did enjoy when they got a panel of the presenters to get up on stage and debate (light hardily) 12 questions asked by the audience. I thought the humor was great and was really the highlight of the After Dark event.
One other high point of going to a VSLive conference is the ability to hear Microsoft representatives speak of new and upcoming products in the daily 'Keynote Speaker' session that kicked off the day. This year they announce the 'Microsoft Team Foundation System Basic' package that will soon be available in response to many being intimidated to get into TFS because of the massive install and large learning curve. This excited me because we are still using the archaic VSS, and it would be nice to make small steps to something more modern. TFS Basic should help with that small step.
Now to the meet and potatoes of the event... the actual conference content. This did not fall short by any means and was as informing and interesting as expected. Good Job VSLive! + Presenters!! Some of the presenters seems to be regulars at VSLIve! like Rocky Lhotka, Richard Hale Shaw, Paul Sheriff (scheduled to be there but slipped on his boat in LA and could not attend), and Ken Getz. Then there were some presenters I had not seen previously (may have been there but I had not attended) like Billy Hollis (a.k.a. Bully... not really but anyone that attended the Agile session would understand this), John Papa, Gus Emery, Miguel Castro, and Aaron Skonnard that all were just as impressive.
I tell you, these presenters in my opinion did a fantastic job and I enjoyed all of the sessions! The content provided by a VSLive! conference regardless of all of the little things I wrote at the beginning make it well worth every penny. If I had to pick (1) presenter that was my favorite I would have to say Rocky Lhotka. He is the founder of the CSLA.NET Framework and instructed the pre-conference session called 'Build Distributed App in .NET 3.5 SP1'. I actually attended this same or closely titled session in Vegas (2) years ago, and Rocky does a great job of keeping it fresh. I would really like to implement his CSLA.NET framework into a new project at some point in the near future; it looks to take care of a lot of the plumbing and 'in between' code needed with OOD.
I also enjoyed listening to Miguel Castro in his Advanced ASP.NET class. He created a framework called 'NavFlow' that wraps up the server side needs for implementing forward and back button functionality in a navigation wizard style web application. Miguel's Blog
Gus Emery gave a great (2) part presentation on ASP.NET MVC that I enjoyed, because although I know of the concepts I have not yet built out a production application using this design. Gus' Blog
Aaron Skonnard gave a wonderful and concise presentation on Cloud Computing that I thought was easy to follow. I felt like I went from almost 0 knowledge on the subject to being really well informed (I can now call a Spade a Spade) in 75 minutes. Aaron's Blog
Lastly, I thought Billy Hollis had a great sense of humor, and a really engaging way of presenting his topic. This guy has a ton of experience in SmartClient and ThickClient application development going way back, and I would like to hear him speak more as I get more into WPF.
One random point here too, it appears as nice as 'Linq to SQL' is and is to use, it does not actively have any main staff at Microsoft with plans to further enhance it or upgrade it. 'Linq' itself is not dead, just Linq to SQL is being phased out. Soon asking questions about it will be like asking about how to use WSE 3.0 in VS.NET 2008. The answer to that is "Quit using asmx and make a WCF service". For Linq to SQL it will be "Quit using it and use the Entity Framework". Better get used to the Entity Framework, which I now understand is much improved in the .NET Framework 4.0. WF (Windows WorkFlow) is also supposed to have much improved functionality in with Framework 4.0 as well. It seems that the early adapters of some of these technologies have gone through some pains, and Microsoft heard them and has now made significant improvements. VS.NET 2010 however needs to get some more improvement before release. I can't tell you how many times it crashed in the different sessions, to the point where VS.NET 2008 was mostly used where applicable.
Overall, I was extremely pleased with this VSLIve! conference and wouldn't think twice about attending another one... I would definitely go again.
Wednesday, September 30, 2009
How to: Set a conditional breakpoint in VS.NET
Below I will highlight a quick and simple way to set up a conditional breakpoint in VS.NET. This breakpoint will only be hit once the condition we set is = 'True'.
This method of setting up a conditional breakpoint can be quite useful when looping through a large list of values, and the developer wants to only debug the code once a certain value has arisen.
In the code below, I created a simple ArrayList and added some characters to it (A-G). Now let's say that I really only want to debug once the variable 'alItem = "D"'. Well I could place a breakpoint on the line that reads 'MyValue = alItem' and keep pressing 'F5' on the keyboard until the value of 'alitem = "D"', or I can set up a conditional breakpoint, so execution only stops once the value I want is set.
To begin, let's take a look at the code for this example below:
Dim al As New ArrayList
al.Add("A")
al.Add("B")
al.Add("C")
al.Add("D")
al.Add("E")
al.Add("F")
al.Add("G")
Dim MyValue As String = String.Empty
For Each alItem As String In al
MyValue = alItem
Next
1st, place a breakpoint on the line in which we want to set up a conditional breakpoint as pictured below:
2nd, open the 'Breakpoints' window by going to 'Debug -> Windows -> Breakpoints' as shown below:
3rd, right click the 'Condition' column description for the breakpoint set and select 'Condition' as shown below. This is where we dictate what condition we want to break execution:
4th, enter in the condition we want to break on debugging; in our case I entered 'alItem = "D"' and made sure the 'Is True' radio button is selected:
Lastly, run the code. You will notice that the code will only break execution when the condition we set up is 'True' as pictured below.
That's it! Hopefully this will save you a little time debugging in the future.
Saturday, September 26, 2009
How To: Make an asynchronous call from an AJAX Modal Popup
There is really no low level magic to making this happen, but rather it just involves making sure the proper AJAX UpdatePanels, and associated AsyncPostBackTriggers are placed in the correct locations.
I think the confusion sometime lies around where the UpdatePanel is to be located. I have seen times where the developer feels it should wrap the entire control referenced by the modalpopupextender, but actually it only needs to be placed around the individual control(s) causing the postback within the modal popup.
For this example, I made a simple page with a 'Show AJAX Modal Popup' button that displays the popup. Then a button within the modal popup calls its server side click event to change the label's 'Text' property. This is all done without the modal popup ever closing.
First, take a look at the source for the .aspx page:
<%@ Register Assembly="AjaxControlToolkit, Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"
Namespace="AjaxControlToolkit" TagPrefix="AjaxControlToolkit" %>
Second, look at the code behind:
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
Protected Sub btnShowModalPopup_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShowModalPopup.Click
If Page.IsValid Then
Me.ModalPopupExtender1.Show()
End If
End Sub
Private Sub btnTestPostback_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnTestPostback.Click
Me.lblMessage.Text = "We made an asynchronous call server side from a modal popup."
End Sub
Private Sub btnCloseModalPopup_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCloseModalPopup.Click
'Reset the text back to its default message:
Me.lblMessage.Text = "Press to test postback without full postback."
Me.ModalPopupExtender1.Hide()
End Sub
End Class
As you can see the trick was the placement of the UpdatePanel and having an AsyncPostBackTrigger in the UpdatePanel containing the label, to the '
btnTestPostback' click event. You may ask why both controls (label and button) didn't just go in the same UpdatePanel; well I was trying to show an example that could be more scalable to a larger ModalPopup with a greater number of control that could not be placed in the same UpdatePanel.
If you ever have any problems getting this implemented on a larger project, I recommend removing the UpdatePanels and associated triggers, and adding them back in carefully one at a time to get the behavior you are trying to accomplish.
Tuesday, September 22, 2009
How To: Add an .asmx Web Service Reference to a WCF Project in VS.NET
In my VS.NET 2008 WCF project there is only the option to 'Add Service Reference...'. So how do I add a .asmx web service? It is still easy to do to a WCF Service in VS.NET 2008, but it is a bit more hidden in the menus, so I will show you how to do it.
1st, right click the project and select 'Add Service Reference...' as displayed below:
2nd, click the 'Advanced' button in the bottom left-hand corner as displayed below:
3rd and lastly, click the 'Add Web Reference...' button in the bottom left-hand corner as displayed below:
At this point the more familiar 'Add Web Reference' window will be displayed where you can enter your .asmx URL and proceed to consuming the web reference to your WCF project.
Wednesday, September 16, 2009
Using Reflection to Map Properties on Objects by their String Name
In addition, you can not refractor the code to use a list of objects or other method and are stuck with having several properties with a similar purpose on a single object. You may have coded logic in a ‘Case’ statement to determine which property to set on the object based on some other logic like the sample UI event and associated method below:
MyObject.Value1
MyObject.Value2
MyObject.Value3
MyObject.Value4
MyObject.Value5
Public Sub MyUIEvent()
UpdateProperty(Me.txtValue1.ClientID, MyObject)
UpdateProperty(Me.txtValue2.ClientID, MyObject)
UpdateProperty(Me.txtValue3.ClientID, MyObject)
UpdateProperty(Me.txtValue4.ClientID, MyObject)
UpdateProperty(Me.txtValue5.ClientID, MyObject)
End Sub
Private Sub UpdateProperty(ByVal TextBoxID As String, ByVal MyObject As MyCustomObject)
Select Case TextBoxID
Case "txtValue1"
MyObject.Value1 = txtValue1.Text
Case "txtValue2"
MyObject.Value2 = txtValue2.Text
Case "txtValue3"
MyObject.Value3 = txtValue3.Text
Case "txtValue4"
MyObject.Value4 = txtValue4.Text
Case "txtValue5"
MyObject.Value5 = txtValue5.Text
End Select
End Sub
In this case you can change your ‘UpdateProperty’ method to use Reflection to map the property name on an object using its String name equivalent. You can infer the UI element to property name logic mapping inline in the call to your new method. This saves a lot of code, especially if you have more that 5 properties that are involved in the ‘Case’ statement.
Take a look to the modified method named ‘UpdatePropertyUsingReflection’ and the change to the parameter values passed in to reduce the code using Reflection:
Public Sub MyUIEventCallingReflectionMethod()
'Call the method to Update the object's property based on the name value of the property provided:
UpdatePropertyUsingReflection(Me.txtValue1.Text, MyObject, MyObject.Value1.ToString())
UpdatePropertyUsingReflection(Me.txtValue2.Text, MyObject, MyObject.Value2.ToString())
UpdatePropertyUsingReflection(Me.txtValue3.Text, MyObject, MyObject.Value3.ToString())
UpdatePropertyUsingReflection(Me.txtValue4.Text, MyObject, MyObject.Value4.ToString())
UpdatePropertyUsingReflection(Me.txtValue5.Text, MyObject, MyObject.Value5.ToString())
End Sub
Private Sub UpdatePropertyUsingReflection(ByVal TextBoxValue As String, ByVal MyObject As MyCustomObject, ByVal PropertyToUpdate As String)
'Use Reflection to get the property attributes for the Property Name Value passed into Sub():
Dim myProperty As System.Reflection.PropertyInfo = MyObject.GetType().GetProperty(PropertyToUpdate)
'Set the value on the object passed in using the setvalue method on the reflected property.
myProperty.SetValue(MyObject, TextBoxValue, Nothing)
End Sub
So there you have it; the (2) lines of code using Reflection replaced the larger ‘Case’ statement needed to determine which property to update.
Of course, the example used here was not the only use for this method and could be applied in many situations. The main goal was to show how to reflect properties using their String type name equivalent. There is some overhead associated with Reflection in .NET, but we can leave that for another day. Depending on its usage, this method can save a lot of code and be used not only with object properties, but in calling methods on objects by their String name as well.
Wednesday, September 9, 2009
Lets get things started; Initial thoughts
This industry more than most can humble one's opinion of how much they think they know, quickly by doing a quick search of the latest technology, architecture, design pattern, etc. and realizing you can't know it all. But this very fact is also one of the best parts of the industry as well; there is always more to know and another challenge around the corner. I guess that is why now more than ever I am so engaged in creating applications, writing code, and learning something new every day.
In this process of becoming a more seasoned developer I believe it is important to know that someone will always know more than I do (young and old), and it is OK to be wrong (hopefully not a lot, but hey it happens). This is one important way to become better in what we do; learn from our mistakes and grow from them.
This Blog will not concentrate around any one .NET or Microsoft technology, but rather bounce around topics and even escaping the bounds to other topics that help support building solid Microsoft based applications (i.e. Javascript, the software development life cycle, design patterns, etc.). The topics will also range from the introductory to the advanced in an attempt to spread knowledge to all tiers of people writing applications. I particularly enjoy helping those newer to the industry as it can be an uphill grind learning so many of the key concepts needed to build applications, before one really gets a head of steam and takes off. However, I also enjoy diving into the newest Microsoft Technologies and discussing more advanced development topics in an effort not to duplicate so many of the tutorials, blog posts, forum posts, books, and articles that have already covered the introductory subjects. When I do, I will try to explain them as I see them and how I needed to learn them in an effort to help others that find them useful.
With those thoughts laid out, I hope to contribute some nice posts here, and I encourage good discussion so please feel free to chime in or contact me with any questions. And away we go....