December 2004 - Posts

The latest build has been released and it can be downloaded through MSDN.  I am currently downloading it if anyone wants to install it.  This should be the most feature complete version released to date.  I'll post more on it as I evaluate it.
Expression handlers in ASP.NET 2.0 are similar to the previous data handling declarative syntax; <%# DataBinder.Eval ( .. ) %>.   You can now access various elements out of your web.config or resources files by using these expressions in your markup.
 
For example, if you need access to a connection string names LocationConnectionString, you would simply type (remember from yesterday, connection strings are in their own section of the web.config):
 
<%$ connectionstrings: LocationConnectionString %>
 
This is typically used in things like SqlDataSources.
 
To access something in the appSettings element, you just do:
 
<%$ appSettings: MyKey %>
 
Resources files have been extended greatly and they may actually pose a viable solution for multilingual text management now.  So they can now be used in things like labels, textboxs, etc.
 
For example:
<asp:label id="MyLabel" runat="server" text="<%$ resources: MyKey %>" />
 
If these expression handles don't provide you with what you need, then you can always write your own.  Although, I am not exactly sure how to do that yet.
The configuration API has been expanded greatly to allow for new features such as writing and encryption.  In the past, doing these tasks were not convenient at all but now they are relatively easy.  The web.config has many new sections as you will come to find out.  A new <connectionStrings/> section has been added specifically for connection strings.  
 
Encrypting your connectionStrings now is easy.  Simply write a page to do the initial encryption.
 
// get an instance of the configuration object
Configuration configuration = Configuration.GetWebConfiguration(Request.ApplicationPath);
 
// get the connection strings section
ConnectionStringsSection connectionStringsSection = configuration.ConnectionStrings;
 
// encrypt using DPAPI
connectionStringsSection.ProtectSection("DataProtectionConfigurationProvider");
 
// update the web.config
configuration.Update();
 
To access your encrypted connections strings, you don't have to do a thing.  Instead of using the AppSettings property, just use the Configuration.ConnectionStrings
This is something that we learned in a session at Visual Studio Connections.  The person that lead the session finally posted how to do it on his site.  This really won't work for ASP.NET applications, but it will work for class libraries and things of that nature.
 
Ok, by now you have probably heard of at least some of the new features that will be added with the new version of SQL Server.  A lot of theses changes allow you to do things on a SQL Server that you could have never done before.  Some of the biggest changes that have been added come from CLR intergation.  This gives you things like .NET Stored Procedures, .NET User Defined Functions, Extended Triggers, and .NET user defined types.  On the ADO.NET side, new things have been added such as Multiple Active ResultSets, asynchronous support, and paging support. 
 
Alright, a lot of buzz words have been mentioned today and I am not going to go into defining them at this time.  However, I encourage to go this URL and read some of the sample chapters. 
 
 
The chapter even has some sample code of a lot of the new features and is worth the read.
I have installed the Novemeber CTP on a virtual machine which already has some of the changes included in Beta 2.  The entire software installs like it is Beta 2 (i.e.: the text everywhere in the product says Beta 2).  The framework version is 2.0.41202.
 
Aside from the compiler directives and directory changes that Microsoft has notified us of (also discussed in the announcements), there are numerous other changes.  The first thing I noticed is that there is actually a start page now.  It automatically pulls a list of recent projects and displays headlines from MSDN.  I am not sure if any of this is configurable yet.
 
I am attempting to migrate an existing application from Beta 1 and here is what I have noticed so far.  The names of all of the providers have changed (i.e.: WindowsTokenRoleProvider is now AspNetWindowsTokenRoleProvider).  The other thing that appears to have happened is that all the attributes used to define a custom profile provider have changed. 
 
Unfortuanately, there is no MSDN help in this build.  An installer happens to be sitting on the disc image but when you try to install it, it tells you that .NET Framework Beta 2 is required.  My guess is that it was built with a different build of the framework.  An update to Visual SourceSafe is also included but I could not get its installer to run either.
 
Any how, I am currently unable to get my application working because there is no help available for setting up the parameters in the web.config and intellisense doesn't really give me enough information to help either.  This is normally something that you could simply use the ASP.NET Configuration pages (WebAdmin.axd) to set up, but unfortunately I couldn't get those pages to run either.  I eventually did get this to run on a simple new application, but for some reason there was no profile provider listed.
 
In summary, this build seems very preliminary, but it is good to see that they are making progress.
Some of you already know that the .NET Framework v2.0 supports FTP, so this may not be new to all of you.  The FtpWebRequest class makes it easy to upload and download files to an FTP server. 
 
The class functions similarly to the HttpWebRequest class.
You open a connection by using WebRequest.Create()
 
// create a new request and cast it to ftp
FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(serverUri);
// set the credentials
ftpWebRequest.Credentials = new NetworkCredential ("anonymous","blah@blah.com");

Strangely enough, the example I have seen uses the DownloadData() method to download a file, but this method is mentioned nowhere in the documentation.  So I have no idea if it works or not.  If anyone tries it, please let me know.

byte [] newFileData = request.DownloadData (serverUri.ToString());

The FtpWebRequest class also supports most typical ftp operations.  Secure FTP can be enabled by setting the EnableSsl property to true.  Passive mode can be enabled by setting Passive to true.
 
In turn the FtpWebResponse class can be used to get the status, banner message, etc.
The BackGroundWorker class makes it easy to execute an operation on a seperate, dedicated thread.  In the past, creating new threads for simple background operations could prove to be quite troublesome.  The BackGroundWorker class makes it easy. 
 
To set up a BackGroundWorker simply add an event handler for the DoWork event.  You can put your long, time-consuming operations inside that event.  When you are ready to start the operation, simply call the RunWorkerAsync method.  The ProgressChanged event can be used to notify your application of any progress that has occurred.  Lastly, the RunWorkerCompleted method will fire when the operation has completed.
 
// Set up the BackgroundWorker object by 
// attaching event handlers
protected void InitializeBackgoundWorker()
{
    backgroundWorker1.DoWork +=
                new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
 }
 
// launch the aync process on a button click event
protected void Button_Click(System.Object sender, System.EventArgs e)
{
     // start the async process
     backgroundWorker1.RunAsync();
}
 
// perform the long operation
protected void backgroundWorker1_DoWork(object sender,
            DoWorkEventArgs e)
{
    // do something
    DoSomething();
}
 
// work completed event
protected void backgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
{
     // display completed message
     ShowWorkCompletedMessage();
}
 
For more information, take a look at:
ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/cpref/html/T_System_ComponentModel_BackgroundWorker.htm
The MultiView control is a container for a group of View controls.  What the MultiView control is good for is creating multistep processes.  Each view control can contain a series of controls that you create.  Use the ActiveViewIndex property can be used to set which view is currently being displayed.  Only one view at a time can be displayed, but this can be a great way to implment multistep processes where you previously used panels.
 
For more information:
ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/cpref/html/T_System_Web_UI_WebControls_MultiView.htm
 
By now, most of you have heard about the new GridView control and stuff like that.  However, the new FormView control allows you to quickly create the ability to display and edit data while giving you full control of your HTML markup.
 
The FormView control binds to a DataSource control just like the GridView.  The beauty of a FormView control is that when you bind it to a typed dataset or whatever using a datasource control.  It will automatically generate a template for displaying and editing items from that datasource.
 
For example, I didn't have to type any of the code below.  All I did was drag and drop an ObjectDataSource control and a FormView control in the designer.  I used the menu to configure the data source and bind the formview to that data source.
 
<asp:FormView ID="FormView1" Runat="server" DataSourceID="ObjectDataSource1">
    <EditItemTemplate>
        CarModelId:
        <asp:TextBox Text='<%# Bind("CarModelId") %>' Runat="server" ID="CarModelIdTextBox"></asp:TextBox><br />
        ImageFileName:
        <asp:TextBox Text='<%# Bind("ImageFileName") %>' Runat="server" ID="ImageFileNameTextBox"></asp:TextBox><br />
        ThumbnailImageFileName:
        <asp:TextBox Text='<%# Bind("ThumbnailImageFileName") %>' Runat="server" ID="ThumbnailImageFileNameTextBox"></asp:TextBox><br />
        LuggageCount:
        <asp:TextBox Text='<%# Bind("LuggageCount") %>' Runat="server" ID="LuggageCountTextBox"></asp:TextBox><br />
        PassengerCount:
        <asp:TextBox Text='<%# Bind("PassengerCount") %>' Runat="server" ID="PassengerCountTextBox"></asp:TextBox><br />
        Description:
        <asp:TextBox Text='<%# Bind("Description") %>' Runat="server" ID="DescriptionTextBox"></asp:TextBox><br />
        MatchedBy:
    </EditItemTemplate>
    <ItemTemplate>
        CarModelId:
        <asp:Label Text='<%# Bind("CarModelId") %>' Runat="server" ID="CarModelIdLabel">
        </asp:Label><br />
        ImageFileName:
        <asp:Label Text='<%# Bind("ImageFileName") %>' Runat="server" ID="ImageFileNameLabel">
        </asp:Label><br />
        ThumbnailImageFileName:
        <asp:Label Text='<%# Bind("ThumbnailImageFileName") %>' Runat="server" ID="ThumbnailImageFileNameLabel">
        </asp:Label><br />
        LuggageCount:
        <asp:Label Text='<%# Bind("LuggageCount") %>' Runat="server" ID="LuggageCountLabel">
        </asp:Label><br />
        PassengerCount:
        <asp:Label Text='<%# Bind("PassengerCount") %>' Runat="server" ID="PassengerCountLabel">
        </asp:Label><br />
        Description:
        <asp:Label Text='<%# Bind("Description") %>' Runat="server" ID="DescriptionLabel">
        </asp:Label><br />
    </ItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="ObjectDataSource1" Runat="server" TypeName="Thrifty.Components.Web.Locations.Resources.Locations"
    SelectMethod="GetFleetByLocationCode">
    <SelectParameters>
        <asp:Parameter Type="String" Name="locationCode"></asp:Parameter>
    </SelectParameters>
</asp:ObjectDataSource>
 
The FormView control has various templates but the two it autogenerates are ItemTemplate and EditItemTemplate.  ItemTemplate displays the data and EditItemTemplate provides a means to edit the items.  This control can easily be used in conjunction with the GridView control to provide a master/details data editor. 
 
This means that creating simple data editors that used to take several hours can probably now be done in a manner of minutes.
While the C# team was working on thing of <del>no-importance</del> great importance like generics, the VB.NET team has worked diligently on creating a new series of classes called the My Classes.  These classes provide a series of basic functionality that provide features for everything from logging, getting computer information, playing sounds, and opening serial ports.
 
All the methods are considered static when used through Visual Basic.  Here is an example of how to play a WAV file using Visual Basic .NET.
 
My.Computer.Audio.Play("c:\Windows\Media\chimes.wav")
 
Some of the other classes available are: MyClock, MyComputer, MyComputerInfo, MyLog (huh huh), MyNetwork, and MyPrinters.  The MyComputer class hosts properties including FileSystem, Keyboard, Moouse, Registry, and Screen.  The MyComputerInfo class provides properties to get information such as the MachineName, OSVersion, Physical Memory, etc.
 
Now don't run out and switch to VB just yet (sorry, Marcus).  These classes are available in the Microsoft.VisualBasic.MyServices namespace.  To get access to that namespace, just add a reference to Microsoft.VisualBasic.dll.
 
Here is the above example in C#.
 
// instantiate myAudio object
MyAudio myAudio = new MyAudio();
 
// play a wav file
myAudio.Play("C:\\WINDOWS\\Media\\Chimes.wav");
 
In C#, the only extra step you have to take is to instantiate the object first.  The MyServices namespace is worth exploring because they make a lot of taks that sometimes took a bit of code really simple.
 
Ever wanted to open a file and store it in a string and not worry about having to deal with streams and all that crap?  Well now you can with File.ReadAll and File.WriteAll.  The ReadAll method will open a file, read the entire contents into a string, and then close the file.
 
// read the entire contents of the file into a string
string fileString = File.ReadAll("ReservationLabels_en-US.xml");
 
The WriteAll method crates a new file, writes the contents of the string to the file and then closes the file.  If the file already exists, it is overwritten.
 
// write the entire contents of the string into the file
File.WriteAll("ReservationLabels_en-US.xml", fileString);
 
If you need a little more control of the file, you can use the File.ReadAllLines() and File.WriteAllLines methods.  These methods do the same thing as the previous methods except that each line is stored as a different element in a string array.
 
// read entire file into an array of strings
string fileStringArray[] = File.ReadAllLines("ReservationLabels_en-US.xml");
 
If you are working with binary files, you can use the File.ReadAllBytes() and File.WriteAllBytes() methods to read the contents of the file into a byte array.
 
Although working with files has never been terribly difficult, this certainly makes dealing with files in these situations even easier.
Tired of object referece is null errors?  The new Nullable<T> generic type is here to make your life easier.  In continuing our discussion with generics from yesterday, this new type allows you to have value types which accept null values.
 
Here are couple of examples of Nullable declarations:
Nullable<int> x = 123;
Nullable<int> y = null;

Both lines are ok and will not throw an exception.
 
There are many ways you can access the type safely.
 
To check if the type has a value (i.e. not null), simply use the HasValue property.
 
// check to see if x has  a value
if (x.HasValue)
{
    int myInt = x.Value;
}
 
Or you can access it safely using the static GetValueOrDefault(Nullable<T>) method:
 
int myInt = Nullable.GetValueOrDefault(y);
 
The above method will return the default value for the alue type int (in this case 0).
 
I believe the Nullable<T> type will prove to be quite valueable, especially when doing data access.
Most people have experienced this by now, but I am going to go ahead and document it.  After installing the .NET Framework 2.0 Beta 1, all of your web applications are configured to run using version 2.0 of the framework.  When you try to run any of your existing 1.1 applications using a browser, more often than not you are going to get a yellow screen, or a server application unavailable error message.  If you have event logging turned on, you will probably either see a message elaborating more on the above or one of your controls might give you an error like "DataSource and DataSourceId are both defined on this control.".
 
For the most part, this is easy to fix.  Simply tell your web applications to run using ASP.NET 1.1 again.  In the past you usually just used aspnet_regiis -i out of the v1.1 folder.  However, ASP.NET 2.0 added a new ASP.NET tab in IIS on your web site's properties.  Simply, click on the tab and choose v1.1.  You may need to do this on every web instance and web application on your server or machine.
 
Running multiple versions of the Framework on the same web instance
Some times it may be necessary to run one particular web application inside an instance on a different version of the framework.  Typically how you do this is you create the application in IIS and choose v2.0 on the ASP.NET tab.  However, when you run the application, you get an error.  If you check the event log it will tell you that you can not run two version of the framework inside the same application pool.
 
To resolve this, open up Application Pools inside IIS and add a new application pool.  Call it something like ASP.NET 2.0 Application Pool.  Then edit the web application that you created and choose the new application pool you created.  Make sure all of the other web applications on the site are using a different application pool (i.e.: Default Application Pool). 
 
At this point, it almost always requires a restart of IIS.  Once you do that, all of your applications should run.
 
 
Some of this stuff you may have already heard about, but I thought I would touch on some stuff regarding generics.  The dictionary object is an object that can take many different data types for both it's key and value.
 
Here is example of how one is declared:
 
Dictionary<string, VehicleDataSet> vehicleDataSetDictionary = new Dictionary<string, VehicleDataSet>();
 
In this case a string is the key (i.e.: PickupLocationCode) and it is taking a typed dataset as a value.
 
Before you might have had to do something like this to retrieve data:
 
int CarModelId = ((VehicleDataSet) vehicleDataSetHashTable["LAX"]).CarModelId;
 
That's a bad time.
 
The dictionary object will let you use retrieve an item from the dictionary without boxing.
 
int carModelId = vehicleDataSetDictionary["LAX"].CarModelId;
 
Notice, that there is no casting required.
 
Note: If you want to verify that the key is valid before accessing an item in the dictionary object, simply use the ContainsKey() method.  This is necessary otherwise you will throw an exception.
 
if (vehicleDataSetDictionary.ContainsKey(locationCode))
   return vehicleDataSetDictionary[locationCode];
 
Lastly there are a ton of new generic collections available in the System.Collections.Generics namespace: List, LinkedList, Queue, SortedDictionary, Stack, etc.
More Posts Next page »