# Monday, April 30, 2007

Silverlight - not just pretty graphics - Cross platform .NET Framework!

Watching Scott Guthrie's keynote at Mix07 right now. The word is finally out - and wow. Silverlight is not just a Flash alternative - it is a cross platform, cross browser .NET runtime and framework. C#, VB, any .NET language driving display in the browser, running on the client side, on other platforms.

Beta for 1.0 is out today, available on www.silverlight.net.

You can even debug cross platform with the .NET code running in a Mac browser. I think we are not far from stepping through the time space continuum now...



.NET | Languages and Tools

Monday, April 30, 2007 7:10:48 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, April 28, 2007

Great guidance on using Team Foundation Server for your projects

Its been a sparse year of blogging due to a lot of overlapping commitments, but I am going to try to remedy that now that I am digging my way out.

A couple of great articles on VSTS and team development have recently been posted on CodePlex. The first is some general guidance for structuring your projects in team system:

http://www.codeplex.com/BranchingGuidance/Wiki/View.aspx?title=Guidance%20for%20Structuring%20Team%20Projects

The other is guidance on branching and merging:

http://www.codeplex.com/BranchingGuidance/

Some good reading on using TFS right for your team.



.NET | Languages and Tools

Saturday, April 28, 2007 1:24:41 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, March 13, 2007

ClickOnce Community Resource Kit has found a new home

For those of you looking for the ClickOnce Community Resource Kit I wrote for the Patterns and Practices Smart Client Software Factory team, you may have found that it has disappeared from its old location on GotDotNet.

In case you haven't heard, GotDotNet is slowly fading away (known as dying a slow death in some circles) and CodePlex has replaced it as the place that Microsoft will put community resources.  So if you go looking for something on GotDotNet and don't find it, make sure you do a search on CodePlex.

The download for my ClickOnce Community Resource Kit can be found here:

http://www.codeplex.com/smartclient/Project/FileDownload.aspx?DownloadId=5060

on the Wiki for the Smart Client Guidance.

 



.NET | ClickOnce | Community | Languages and Tools

Tuesday, March 13, 2007 11:10:10 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, March 12, 2007

Hands on WPF - dnrTV - Part 1

I recorded a dnrTV with Carl a while back on WPF and it was posted last week. I'll be recording a part 2 this week so keep your eyes out for that. This episode gives a good overview of what programming WPF is like (for now until the tools evolve some more) and what the structure of a WPF application is. Part 2 will dive deeper into data binding, styles and resources, as well as a few other things.



.NET | .NET 3.0 | Languages and Tools

Monday, March 12, 2007 12:24:02 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Friday, July 14, 2006

MSDN Webcast: Implement a Data Access Layer with the Visual Studio 2005 DataSet Designer slides and demos

Here are the slides and demos from last week's webcast. Keep in mind that you will need to add a Modified DateTime column and respective stored procedures to your database to be able to run the code as it was demo'ed in the webcast. The demo code includes my CodeSmith templates for generating those stored procedures and also one for making the coumn modification scripts for you if you want to do it to all the tables in your database that are transactional. There is also a SQL script just for doing the Employees table in Northwind, which was all I used in the demos.

Slides

Demos



.NET | Languages and Tools | Speaking

Friday, July 14, 2006 3:13:51 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, June 24, 2006

Managing ClickOnce publisher certificate files

I've had several people ask questions surrounding how to get a pfx file to use for ClickOnce manifest signing when you have purchased a real certificate from a provider like Verisign or Comodo (www.instantssl.com - a great, cheaper alternative that has its root issuer already installed as a trusted root certification authority).

Usually when you purchase a certificate, the process involves going to the provider's site, such as instantssl.com, providing your contact information online and entering payment information. The certificate issuer must then verify your identity through some means (corporate DUNS number, business license, bank statement, utility bill, etc.). Once they have done that, they will allow you to download and install your certificate through your browser. They should also provide you with a separate download or generation of a .pvk (private key) file that will contain the private key portion of your certificate. They may or may not provide you a download of a .spc or .cer file that just contains the public key portion of your certificate. If they do not provide a download of the .spc file, you may have to export it from your certificate store after the browser installs it as described later in this post.

Step 1: Download and install pvkimprt.exe
If you have a .spc or .cer file and a .pvk file, then you have the pieces you need to create a .pfx file. You will need to download,expand, and install the pfximprt tool,  which you can get here:

http://www.microsoft.com/downloads/details.aspx?FamilyID=F9992C94-B129-46BC-B240-414BDFF679A7&displaylang=EN

Generate an install a public/private key pair certificate in your store
To generate a pfx file from an spc/cer and pvk file, do the following:
1. Open a command prompt and run pvkimprt, passing the spc and pvk file:
C:\>"C:\Program Files\Pvkimprt\pvkimprt.exe" softinsight_comodo.spc softinsight_comodo.pvk
2. You will be prompted for a password for the pvk file as shown in Figure 1. The password is the one you provided when you ordered the certificate or when the pvk file was issued to you.

password prompt

Figure 1

3. After entering your password and clicking OK, the certificate import wizard will launch as shown in Figure 2.
start import wizard

Figure 2

4. Click Next, and you will be prompted as shown in Figure 3 for selecting the store. Just allow it to automatically select the store (the default) and click Next.
select cert store

Figure 3


5. You will then just see the summary as shown in Figure 4, click Finish.
Import summary

Figure 4

6. You should now have a publisher certificate installed into your personal certificate store that contains both the public and private keys for the same certificate. Now you need to export it to a .pfx file that you can back up and use on other machines. Open certmgr by running certmgr.exe from a Visual Studio 2005 command prompt (see Figure 5).
certmgr.exe

Figure 5

7. Find the certificate you just imported (by publisher name) in the list in the Personal tab (selected by default). Press the Export button.
8. The first step of the export wizard will be presented (see Figure 6). Press Next.
Start export wizard

Figure 6

9. The next step asks whether you want to export the private key. If you are generating a pfx file for ClickOnce deployment, the answer here must be yes, which is not selected by default (see Figure 7). Press Next.
Export private key prompt

Figure 7

10. The next step asks what export file format you want, the default is fine (see Figure 8). Press Next.
Export file format selection

Figure 8

11. The next step asks for a password to protect the pfx file that will be output, use a secure password and be careful who you give it to because this is the last line of defense if someone is able to get their hands on your physical pfx file to prevent them from being able to use it. Enter a password twice and click Next (see Figure 9)
Password prompt

Figure 9

12. The next step has you enter the path to the output file. You can press the browse button and navigate to the desired folder and select the file format from the file type drop down, or you can just type in a path (see Figure 10). Press Next.
Output file path

Figure 10

13. You will see the summary screen, press Finish to generate the file (see Figure 11).
Summary screen

Figure 11

14. You will see a message box showing that the export was successful (see Figure 12).
Finished prompt

Figure 12

At this point you now have a pfx file that you can point to with your Visual Studio project Signing tab properties to sign your ClickOnce manifests. You can share that file with other trusted members of your team and they can use it to sign your applications to put them into production.

Just realize that anyone who gets their hands on that file and knows or can guess the password will be able to sign and publish applications that look like they come from you, so you need to treat those files (particularly the pfx and pvk) very carefully.

 

 


 



.NET | ClickOnce | Languages and Tools

Saturday, June 24, 2006 12:04:18 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, June 19, 2006

Another TechEd Complete - Slides and Demos

It was a crazy week at TechEd last week. So crazy, no time to write or consume blogs. I gave two breakout sessions (Real World ClickOnce and Windows Forms: Build Enterprise Ready Forms Applications) and a Birds of Feather session (Windows Workflow Foundation).

You can get the slides and demos from the sessions here:

Real World ClickOnce:  Slides   Demos

Windows Forms: Build Enterprise Ready Forms Applications:  Slides   Demos

 



.NET | ClickOnce | Data Binding | Languages and Tools | Speaking

Monday, June 19, 2006 2:27:37 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, June 9, 2006

WCF and WF Course Materials

For the students from my 3 day WCF course and 2 Day WF course this week, or for anyone else who wants the code with out the supporting delivery, here you go.

For those who attended, it was good working with you this week!

WCF Course Demos and Lab Code

WF Course Demos and Lab Code



.NET | Languages and Tools | Speaking | WinFx

Friday, June 9, 2006 10:57:19 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, May 29, 2006

ClickOnce Trust Model - What Should and Shouldn't You Be Able To Do Through a ClickOnce Install

Julie Lerman has a nice post about creating a desktop icon as part of a ClickOnce install - a fairly common question / request, and very representative of the kinds of "custom" things people would like to be able to do as part of a ClickOnce installation.

There were specific discussions about the option to create a desktop icon in some design reviews in Redmond I took part in several years ago. If I remember correctly, that one was dismissed mostly because it is discouraged to add desktop shortcuts as part of an install, especially without prompting the user to let them choose.

But part of this kind of desire really comes back to understanding the trust model of ClickOnce in general.

The trust issues of ClickOnce are twofold:
1. ClickOnce should not make any modifications to the local machine at install time that could affect other applications or data on the machine.
2. ClickOnce should provide runtime protections to avoid allowing the application to do harm to the local machine.

For #1, this means that you cannot install things to the GAC, add things to the registry, put things in specific places in the file system, etc. Any of those things could affect other apps and users on the machine, which means that administrators are not going to trust low-privilege users to perform ClickOnce installs. As a result, the model will not get adopted in enterprise environments, which is the primary target environment for ClickOnce - to replace those darn intranet web apps that companies create for ease of maintenance with smart client apps that give the user a better experience but are just as easy to maintain because of ClickOnce.

So the bottom line for #1 is that the only forms of customization you have available to you directly through ClickOnce is specifying:

- Whether the app is available offline (meaning you get a Start menu item and an Add or Remove Programs item)

- When updates checks will occur

- What the publisher name is - which sets what the program group in the Start menu is

- What the application name is - which sets the name of the program in the Start menu and Add or Remove Programs

- What the application icon is - through the Visual Studio application settings, and used for the icon in the Start menu item and Add or Remove Programs

There are a number of other assorted options you can set through the Publish tab, but they all really affect how the publication and deployment occurs, but none are in the form of explicit control over what goes where.

For #2 - You specify what runtime permissions the application will have as part of its publish settings (through the Security tab in VS), which end up as a list of required permissions in the application manifest. If those permissions exceed what the application would be granted by Code Access Security at runtime based on the zone of the launch URL (Internet, LocalIntranet, MyComputer, TrustedSites, or RestrictedSites), then the permissions have to be elevated either through user prompting (the default, ClickTwice experience) or through the trusted publishers capability of ClickOnce.

The fact is that you can overcome or workaround any limitations caused by #1 by exploiting #2. If you request full trust for your application, code in your application can do whatever you want it to do when your application first starts up. However, this requires one big assumption - you are also assuming the user who is running your application has sufficient privilege to do whatever it is that your code will try to do. This violates one of the goals of ClickOnce - to provide a deployment mechanism that can be used by low privilege users. So if you write some custom code in your app that tries to create a registry key - your app will have to have Registry permission through ClickOnce, and the user will have to have permission to create a key wherever your app is trying to create it.

As Julie points out, to create the Desktop icon with your own code, the user doesn't need any special permissions because anyone can add a shortcut to their own desktop, but you will need several high trust permissions including unmanaged code execution, which basically means most people will just elevate the application to full trust to get it done. Elevating to full trust is definitely something to avoid if you can.

The recommended way of addressing a lot of scenarios that would require high-privilege custom startup code is to create those things through the Bootstrapper as a prerequisite. A desktop icon is not really a good candidate for that, but pre-deploying something like GAC components is. Making something a prerequisite may allow you to avoid requiring full trust for your application.

However, the dirty little truth about Full Trust is that even though you should always try to avoid jumping all the way to full trust, there are many things that you will likely need to do in any meaningful ClickOnce app that will require you to go to full trust. Examples include:

  • Using the ClickOnce API ApplicationDeployment class for just about anything, such as checking if this is the first run of a given version to execute your custom code, or to perform on demand updates.
  • Using WCF for remote communications
  • Using Windows Workflow in your Windows Forms application

One way to add protections back into your application even if you do have to request full trust for the application as a whole is to have sections of code where you restrict permissions below that level. You can do this through Code Access Security IStackWalk modifiers to Deny certain permissions or PermitOnly certain permissions. You can do this to bracket out a section of code (for example where you call out to some third party component to make sure that they are not doing something like reading/writing from your disk or sending information over the web for data /intelligence collection purposes). The details for doing this are too involved for this post, but I do cover it in my upcoming ClickOnce book and the underpinnings from a CAS perspective are covered well in my colleague Juval Lowy's Programming .NET Components, Second Edition.



.NET | ClickOnce | Languages and Tools

Monday, May 29, 2006 4:27:35 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, May 27, 2006

Mid-Atlantic Code Camp - Schedule Up and Volunteers Needed!

The schedule for our upcoming DC area / Mid-Atlantic Region code camp on 10 June in Reston VA is up:

http://www.madcodecamp.com/schedule/codecampmain.htm

The event is being held at the Microsoft Technology Center at:

Microsoft Technology Center
12012 Sunset Hills Rd
Reston, VA 20190

You can find directions at:

http://www.microsoft.com/mscorp/info/usaoffices/midatlantic/mtc_reston.mspx

We are currently filled up on registration, but are taking waitlist people to fill in for no-shows.

If you are planning on attending and would be willing to volunteer to help out, please send me a note at brian.noyes(AT)idesign.net. (Change the (AT) to @)

We need volunteers for:

Registration - Help check people in off the registration lists.

Room monitors: All this means is you sit in on a session and make sure that if the speaker needs any help, you can help go and find someone so the speaker doesn't leave the room. You will also prompt the speaker when there is 15 minutes remaining and at completion time so that we can stay on schedule.

Food/drink - Just need a couple of folks to hang out in the food area for the morning break and at lunch to help out if anything is needed.



.NET | Community | Languages and Tools | Speaking

Saturday, May 27, 2006 2:25:39 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, May 26, 2006

CAPICOM Build Error on ClickOnce Publishing

I was working with Paul Sheriff of PDSA this week to ClickOnce deploy a reporting tool we use for the Regional Directors program. We ran into a problem where we got the following error when we tried to publish:

CAPICOM Error

The resolution was to obtain the correct version of the CAPICOM.dll, drop it into the \SDK\bin directory where the SignTool.exe lives (C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin with a default VS install), and then register the library with Regsvr32.exe). Since it is a COM library for the CryptoAPI, it can actually live anywhere on your machine once it is registered.

Not sure how this was not there on the machine in question, it normally gets installed and registered when you install VS according to the ClickOnce product team folks.



.NET | ClickOnce | Languages and Tools

Friday, May 26, 2006 3:53:46 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, May 24, 2006

I love the smell of fresh hot bits in the morning...

If you haven't stumbled on the top link on the MSDN homepage in the last 24 hours... WinFX Beta 2 is out. Finally some fresh bits that are synced up between WCF, WPF, and WF.

There is also a Go-Live license associated with all the bits, so you can get the jump on the competition by putting apps into production right away with WinFX capabilities. If you haven't started looking at WinFX capabilities yet, now is definitely the time. One good way to do so is to attend our WCF Master Class. You can find more details at http://www.idesign.net/.

You can get all the download bits for WinFX Beta 2 here: http://msdn.microsoft.com/windowsvista/downloads/products/getthebeta/

 



.NET | Languages and Tools | WinFx

Wednesday, May 24, 2006 1:42:01 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, May 20, 2006

Manually Putting a ClickOnce Application into Production

A common question with respect to ClickOnce is how to take an application that you have published and tested on your local machine or a local development server and move that application into production. The steps involved are not particularly complex, but do involve using some other tools to get it done and are not easy to figure out on your own unless you have a solid understanding of ClickOnce manifests, signing, and how they relate to the launch mechanisms of ClickOnce.

A key pre-requisite for doing this is that the administrator who will be placing the application on the target machine will need to have the publisher certificate that will be used to sign the production application available. Usually in large organizations the developers will not have access to the company's real certificate to do their development anyway, it will be up to the IT Administrator to get that certificate and do the final signing of the applications anyway.

Step 1: Move your application files to the target machine.
Assuming you have published your application with Visual Studio to your local machine or another test server in your development environment, the application files are contained in the virtual directory or folder that you specified as the Publish Location within Visual Studio. The deployment manifest, Bootstrapper setup.exe, publish.htm deployment page, and version specific deployment manifests are located in the root folder. For each version you published to that location, there is a subfolder that contains the application manifest and application files for that version. You might do this by zipping up the appropriate files and folders and just giving the zip file to the administrator who will put it into production.

To move the current version into production, you will need to copy the deployment manifest, setup.exe, version-specific manifest and sub-folder for the version you want to publish to the target machine deployment folder. You only need to include the publish.htm file if you intend to use that test page directly to expose the application to end users. But if you are going to put a link to the deployment manifest in some other page or send a link via email, you don't need to include the publish.htm page.

Step 2 (Optional): Make needed changes to application files
If you need to change something in the application files, such as changing a setting in the application configuration file or updating some graphics files, you will need to update the application manifest after modifying the application files themselves. So make the modifications needed in your application files.

Step 3: (Only needed if you did step 2): Update the application manifest file list
If you made any changes to any application files, you will need to refresh the list of files contained in the application manifest. This is because the manifest contains the hash for each file that provides a unique representation of the contents of the file. If you changed the application file, the hash for that file that is in the application manifest is no longer valid and needs to be updated.

- Open the application manifest (.manifest file in the application files folder for the version you are publishing) with mageui.exe.
- Select the Files category in the list on the left side of the window.
- Enter the path to the application files folder for the deployment on the right side.
- You can press the ellipses (...) button to browse to the folder.

Mage Files Pane

This step does not have to be done on the target machine because only relative paths are stored in the manifest from the location of the manifest, but the manifest and the application files need to be located with the same relative folder path as they will be on the target machine (usually the same directory).
- After you have entered the path to the folder, press the Populate button.
-You will be prompted with a warning dialog about the fact that the files will be renamed with a .deploy extension.
- Click Yes in this dialog.

Renaming Files Warning

Step 4: Sign the application manifest
If you make any changes to the application files and update the application manifest as described in step 3, or if you just need to re-sign the application manifest with a production certificate that is different than the one that was used in development, then you will need to sign the manifest with Mage. To do so:
- Open the .manifest file with mageui.exe if not already open from step 3.
- Press the Save button in the toolbar, and you will be presented with the signing dialog shown below.

Signing Dialog

- Provide the path to the certificate file and the certificate password at the top of the dialog, or select the certificate from your personal certificate store at the bottom of the dialog.
- Click OK to sign the manifest with the selected certificate.

Step 5: Update the application manifest reference in the deployment manifest
If you performed step 4 and signed with a different certificate than the one used to
originally generate the deployment manifest, you now need to update the application reference in the deployment manifest. The application reference is a strong reference to the application manifest from the deployment manifest, including path information as well as the public key token from the digital signature in the application manifest. That signature is generated using the publisher certificate, so if you change the certificate, you have to update the application reference.

To update the application reference, do the following:
- Open the deployment manifest (.application file) in mageui.exe
- Select Application Reference from the list of categories on the left of the window
- Press the Select Manifest... button and navigate to the application manifest (.manifest file) for the version that you are deploying.

Application Reference UI

Step 6: Update the Deployment Provider
If you are moving the application to a different server than the one where you first published the application from Visual Studio, you will need to update the deployment provider URL that is embedded in the deployment manifest. To do so, perform the following steps:
- Open the deployment manifest in mageui.exe if it is not already opened from step 5.
- Select Deployment Options from the list of categories on the left side of the window.
- Change the URL labeled Start Location to reflect the URL users will use to launch the application from the client machine. This setting is saved as the deployment provider in the deployment manifest.

Deployment Provider

Step 7: Sign the deployment manifest
- Click the Save button in the toolbar.
- Enter the path and password for the publisher certificate file at the top of the signing dialog, or select the certificate from the list of certificates at the bottom. This should be the same certificate used to sign the application manifest.
- Click OK to re-sign the manifest.

At this point, your application should be ready to go from the client.



.NET | ClickOnce | Languages and Tools

Saturday, May 20, 2006 2:43:05 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Slides and Demos from SDC Netherlands

I gave four talks at the Software Developers Conference in Netherlands this week. This is a very fun and interesting conference that is put on by a large user group organization called Software Developers Network, run by Remi Caron and Joop Pecht.

This conference is one of the most enjoyable conferences I get to do anywhere in the world. It is amazing how professional and well run this conference is, especially when you consider that it is being put on by a user group organization and it is better run than many U.S. conferences put on by companies that are supposed to specialize in this kind of event. All of the user group members that run the conference are volunteers, and yet the quality and professionalism that comes out of that is outstanding.

The attendees are hard core, ask great questions, and make the event fun for the speakers as well. For those of you who attended and find your way to this post for the slides and demos - thanks!

You can grab the slides and demos here:

Build Smart Client Data Apps with Windows Forms 2.0:  Slides   Demos
Build Custom Data Bound Objects and Collections:  Slides   Demos
Present Rich Tabular Data with the DataGridView Control:  Slides   Demos
Drive Application Behavior with Application and User Settings:  Slides   Demos



.NET | ClickOnce | Community | Data Binding | Languages and Tools | Speaking | Travel

Saturday, May 20, 2006 2:35:03 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, May 13, 2006

DevTeach Slides and Demos

I spoke at DevTeach  in Montreal Tue-Thu of this week and had a great time as always. If you haven't checked out this conference, you should plan on signing up next year. Great location, great speakers, very well done conference with lots of hard core sessions.

If you attended one of my sessions and want to get the slides and demos, here you go:

NET371 - Drive App Behavior with Application and User Settings:  Slides   Demos

NET391 - Custom Bound Objects and Collections:  Slides   Demos

NET463 - Advanced ClickOnce:  Slides   Demos

MusicLibrary Database Creation Script:   Script



.NET | ClickOnce | Community | Data Binding | Languages and Tools | Speaking | Travel

Saturday, May 13, 2006 6:09:02 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, May 8, 2006

DC Advanced Master Class

I taught a public Advanced .NET Master Class in Reston VA last week. Had a great time, great bunch of students. One of the things that makes teaching the most fun is answering questions, and this was a lively group with the questions. Thanks to all of the students who attended.

A lot of the demos that I give during class are part of the downloads available on our site at http://www.idesign.net. If you want the live demos that I did on the fly, you can download them here:

Live Demos



.NET | Languages and Tools | Speaking

Monday, May 8, 2006 2:43:41 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, April 25, 2006

Mid-Atlantic Code Camp time again! - 10 June

We will be running a Code Camp at the Microsoft Reston training center on 10 June all day. This is a great FREE event with great speakers teaching you hard core topics on .NET coding. We are looking for speakers, so if you are interested in sharing your knowledge with the local community, you can find the call for speakers here as well as registration information if you just want to attend and soak up knowledge.

Come on out and participate in the DC area developer community!

 



Community | Languages and Tools | Speaking

Tuesday, April 25, 2006 10:01:56 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, April 15, 2006

Process Identity and Working Directory for Partial Trust ClickOnce Apps

People always ask me "How can you write a whole book on ClickOnce?" because they envision the standard 5 minute demo of what ClickOnce is and does and think that is all there is to it. The fact is there is just a plethora of variations, hidden behaviors, specialized scenarios, and things people want to do with ClickOnce that are far more than 5 minute answers. The book keeps growing the more I get into it.

One of these things that snuck up and bit me recently (unfortunately in a live demo at VS Connections) due to a gap in my knowledge was the way partial trust apps run on the client machine.

First some background on ClickOnce and application files. Any file you add to your project and set the file Build Action property to Content will be added to the Application Files (under the Publish tab in project properties) with a Publish Status of Include, depending on the file type. MDF files (SQL Express), mdb, and XML files will get marked as Data Files instead of Include. Include means the file will be deployed to the application client cache folder under the user profile (C:\Documents and Settings\<username>\Local Settings\Apps\<obfuscated goo>\), and Data File means it will be deployed to a separate data folder associated with that app, also buried in the obfuscated goo under the user profile. The data files are treated differently for updates (beyond the scope of this post) and the folder is accessible through the ApplicationDeployment.DataDirectory property.

If you deploy an app with ClickOnce, and the app manifest requests Full Trust, then when the app runs it simply gets launched by the runtime directly - the app executable is the executable process that runs. It runs from the deployed client cache directory. As a result, with a full trust app, you can access files that you deploy with your app, marked with a Publish Status of Include, with a relative path such as ".\MyImage.jpg". The current working directory when your executable starts is the folder it was launched from, and so everything works out.

Then you decide that you want to be more security concious, and switch your ClickOnce security settings to only require partial trust (lets say LocalIntranet zone). Suddenly your app stops working complaining that it can't find the file.

So what's going on there??

The problem is that the executable process is actually different when you run a ClickOnce app under partial trust. When you configure a ClickOnce deployed app to request less than full trust, the process that actually launches is AppLaunch.exe. This process loads your executable assembly into an AppDomain which it has cranked down the CAS security on to your requested permissions, and your app runs from that appdomain under partial trust. This is similar to what Visual Studio 2005 does to enable partial trust debugging with the <appname>.vshost.exe that is the debug process by default.

So how does that screw up your paths? AppLaunch.exe is running from the .NET directory under C:\WINDOWS\Microsoft.Net\Framework\v2.0.50727\, and so the current working directory for your app loaded into that host process is that folder. Naturally your application files have not been deployed there, so your relative paths for locating the files fail.

OK, so next thought is "there's gotta be an API that I can call to say 'give me my app's deployed directory'". Unfortunately, that thought would be incorrect.

So what's the solution? Simple - don't ever deploy a file to the application directory (Publish Status = Include) that you need to access explicitly through a path (i.e. to load that file as a bitmap, xml file, etc.). If you need to do that, you should mark it as a Data File, and access it by adding the file name to the ApplicationDeployment.DataDirectory path. You can also use Application.UserAppDataPath property, results in the same thing when you are ClickOnce deployed.

Just wish I had known that before doing that demo on the fly in a way I had not done it before in front of a live audience... :)



.NET | ClickOnce | Languages and Tools

Saturday, April 15, 2006 2:26:01 AM (GMT Daylight Time, UTC+01:00)
Comments [6]  | 


 # Tuesday, April 11, 2006

Great new WCF demos available on the IDesign web site

If you are starting to get your hands dirty with Windows Communication Foundation (WCF), you can get some great samples to help you get started from our website at http://www.idesign.net/ on the downloads tab.

http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11

 



.NET | Community | Languages and Tools | WinFx

Tuesday, April 11, 2006 3:29:14 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Slides and Demos from DevConnections Last Week

I presented four sessions at DevConnections last week and have been a little remiss on getting the slides and demos posted, but here they are:

Secure ClickOnce Deployments:  Slides   Demos

Connecting Smart Clients with WCF: Slides   Demos

Drive Application Behavior with User and Application Settings:  Slides   Demos

Build a Data Access Layer with Enterprise Library Data Access Block:  Slides  Demos



.NET | ClickOnce | DevConnections | Languages and Tools | Speaking

Tuesday, April 11, 2006 3:26:41 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, March 24, 2006

C# Code Snippets Library

If you didn't happen to notice it in your Visual Studio Start page RSS feed, this is very cool. They have put out a very comprehensive Code Snippets library for C#, available here:

http://msdn.microsoft.com/vstudio/downloads/codesnippets/default.aspx

When I teach our Master Class or Advanced Master Class at IDesign, I often get the question of why Visual Basic has a ton of code snippets and why C# only has a couple dozen. I always feel like I am apologizing for the C# team or it is tempting to make a joke at the VB guys's expense and say they need them more, which I really don't believe but is usually got for a laugh (or a few death threats from the VB guys). :)

The fact is we C# guys need them just as bad and should use Code Snippets and other forms of Code Generation such as CodeRush and CodeSmith to the max. Resources like www.gotcodesnippets.com help a lot for not always needing to create one from scratch for every specialized situation you find yourself repeating, but this library gets us even closer with somewhat "out of the box" capabilities.

It includes all kinds of code snippets from collections, to data access to creating data types, cryptography, security, and Windows Forms common needs. These can not only help you avoid writing repetitive code over and over, they give you completed code samples for a lot of situations where you may not have ever written that kind of code before.

Thanks to whoever created this at Microsoft!



.NET | Languages and Tools

Friday, March 24, 2006 2:29:40 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, March 13, 2006

Data Binding Talk in San Diego - Slides and Demos

I gave a talk on Data Binding with Windows Forms 2.0 at the San Diego .NET Developers Group on Tuesday 7 Mar.

Here are the slides and demos:  Slides   Demos



.NET | Community | Data Binding | Languages and Tools | Speaking

Monday, March 13, 2006 6:30:14 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, February 27, 2006

What to do when BindingNavigator Raises Exception on AddNew

I got a great question from a reader recently. It's essence reads like this:

If I set up drag and drop data binding to a table that has non-nullable columns, and then press the Add New button twice in the BindingNavigator, I get an unhandled exception on the thread. Since all of the code involved in that call chain is in .NET code and assemblies, how can I handle the exception to keep it from blowing up my app?

If you are not already familiar, to get to this point, you have to create a data bound UI using the Data Sources window, or by hooking up the controls manually. What you end up with after dragging a collection from the Data Sources window onto a form is:

  • A DataGridView or Details form of individual controls
  • A BindingSource component that is set as the data source of the grid or the individual controls
  • A BindingNavigator control that is hooked up to the BindingSource component.

If your data source is a typed data set in the same project, you also get a table adapter instance and data set instance as members on the form, and a Form.Load event handler that fills the appropriate table of the data set so that the app functions without any hand written code. If your data source is coming from a different assembly (an Object data source), then it will be up to you to go retrieve an instance of the collection type and set it as the DataSource property on the BindingSource at runtime to complete the data binding chain.

The way the BindingNavigator gets hooked up, it just points to the BindingSource component and uses the API exposed by a BindingSource to navigate forward and back and to add and delete items from the underlying collection. When you press the Add New button on the BindingNavigator, it calls the AddNew method on BindingSource. The BindingSource passes the call to the underlying collection if it implements the IBindingList interface. Calling AddNew usually also implicitly calls EndEdit on the current item if that item type implements the IEditableObject interface, depending on the collection type's implementation of the AddNew method.

So when dealing with a data table as your collection, you are actually bound to its default DataView. The DataView class implements the IBindingList interface, and the DataRowView class (the items in the collection) implement IEditableObject. When a column in the table is set up so that it does not accept null values, the DataRowView implementation of EndEdit will throw and exception when EndEdit is called if the non-nullable columns have not been provided a value.

The call chain that sets all this up for a standard data set based application is that the BindingNavigator calls into the BindingSource and calls AddNew. This calls into the DataView and adds a new row to the table and starts an editing transaction by calling BeginEdit on the row. When you press the AddNew button a second time, EndEdit is called on the first row you added, which, if you haven't filled in the non-nullable columns, will throw an exception. Since the call chain goes from BindingNavigator to BindingSource to DataView to DataRowView, there is no user code in the call chain where you can logically insert an exception handler.

You could handle the situation in a crude form by having an Application.ThreadException handler, which will catch all unhandled exceptions on the thread. However, this doesn't get called until the stack has unraveled all the way back out to the base of the call stack, so it is a little late to be dealing with the exception in a recoverable way.

A better solution is to inherit from the BindingSource component and provide your own implementation to AddNew. The following implementation (thanks to Steve Lasker and Daniel Herling on the product team in Redmond for coming up with this) shows how:

private class MyBindingSource : BindingSource

{

   public MyBindingSource()

      : base()

   {

   }

 

   public override object AddNew()

   {

      object o = null;

      try

      {

          o = base.AddNew();

      }

      catch (System.Exception ex)

      {

          this.OnDataError(

             new BindingManagerDataErrorEventArgs(ex));

      }

      return o;

   }

}

With this in place, you can just handle the DataError event on the BindingSource component to do whatever is appropriate based on the exception.



.NET | Data Binding | Languages and Tools

Monday, February 27, 2006 6:29:04 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Friday, February 24, 2006

Slides and Demos from Connecting Smart Clients with WCF talk last night - Feb CTP lessons learned

I gave a talk on Connecting Smart Clients at the Microsoft Integration and Connected Systems User Group (MICSUG) last night. I discussed and demoed the basics of using Windows Communication Foundation (WCF) to connect applications, using the newly released Feb CTP.

You can get the slides and demos here:  Slides   Demos

In jumping through the hoops yesterday to get my demos running on the Feb CTP, there were a number of changes that I had to get used to compared to previous builds.

The biggest is that if you run svcutil against a service that uses wsHttpBinding to generate a proxy, you get a proxy service contract that uses custom message contracts to wrap the parameters and return values from each operation contract. XXXRequest and XXXResponse classes are defined in the proxy file for each operation, along with an XXXBody class that actually contains the raw parameter/DataContract types.

If you program against the service contract interface like so:

IAccountsManager mgrProxy = new AccountsManagerProxy();

You will have to create the XXXRequest message contract types to wrap all the parameters you pass into the methods, and unwrap any return values from the XXXResponse types. However, they also expose a public method on the proxy class directly that encapsulates these details so that you can deal directly with the underlying parameters and return values.

So instead of calling IAccountsManager.GetAllAccounts for example, you will have an easier time calling AccountsManagerProxy.GetAllAccounts.

This is true for wsHttpBinding because of the message level security involved in the default binding. If you use basicHttpBinding, or turn down the security on the wsHttpBinding, then you will get more straightforward service contract interface definitions on the client side proxy.

The resulting proxy and service contract look like the following:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

[System.ServiceModel.ServiceContractAttribute()]

public interface IAccountsManager

{

// CODEGEN: Generating message contract since message part accountNo requires protection.

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountsManager/CreateAccount", ReplyAction="http://tempuri.org/IAccountsManager/CreateAccountResponse")]

CreateAccountResponse CreateAccount(CreateAccountRequest request);

// CODEGEN: Generating message contract since message part GetAllAccountsResult requires protection.

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountsManager/GetAllAccounts", ReplyAction="http://tempuri.org/IAccountsManager/GetAllAccountsResponse")]

GetAllAccountsResponse GetAllAccounts(GetAllAccountsRequest request);

// CODEGEN: Generating message contract since message part fromAccountNo requires protection.

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountsManager/Transfer", ReplyAction="http://tempuri.org/IAccountsManager/TransferResponse")]

TransferResponse Transfer(TransferRequest request);

}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

public interface IAccountsManagerChannel : IAccountsManager, System.ServiceModel.IClientChannel

{

}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

public partial class AccountsManagerProxy : System.ServiceModel.ClientBase<IAccountsManager>, IAccountsManager

{

public AccountsManagerProxy()

{

}

public AccountsManagerProxy(string endpointConfigurationName) :

base(endpointConfigurationName)

{

}

public AccountsManagerProxy(string endpointConfigurationName, string remoteAddress) :

base(endpointConfigurationName, remoteAddress)

{

}

public AccountsManagerProxy(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :

base(endpointConfigurationName, remoteAddress)

{

}

public AccountsManagerProxy(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :

base(binding, remoteAddress)

{

}

CreateAccountResponse IAccountsManager.CreateAccount(CreateAccountRequest request)

{

return base.InnerProxy.CreateAccount(request);

}

public void CreateAccount(int accountNo, string name, decimal initialBalance)

{

CreateAccountRequest inValue = new CreateAccountRequest();

inValue.Body = new CreateAccountRequestBody();

inValue.Body.accountNo = accountNo;

inValue.Body.name = name;

inValue.Body.initialBalance = initialBalance;

CreateAccountResponse retVal = ((IAccountsManager)(this)).CreateAccount(inValue);

}

GetAllAccountsResponse IAccountsManager.GetAllAccounts(GetAllAccountsRequest request)

{

return base.InnerProxy.GetAllAccounts(request);

}

public BankingBusinessLayer.Account[] GetAllAccounts()

{

GetAllAccountsRequest inValue = new GetAllAccountsRequest();

inValue.Body = new GetAllAccountsRequestBody();

GetAllAccountsResponse retVal = ((IAccountsManager)(this)).GetAllAccounts(inValue);

return retVal.Body.GetAllAccountsResult;

}

TransferResponse IAccountsManager.Transfer(TransferRequest request)

{

return base.InnerProxy.Transfer(request);

}

public void Transfer(int fromAccountNo, int toAccountNo, decimal amount)

{

TransferRequest inValue = new TransferRequest();

inValue.Body = new TransferRequestBody();

inValue.Body.fromAccountNo = fromAccountNo;

inValue.Body.toAccountNo = toAccountNo;

inValue.Body.amount = amount;

TransferResponse retVal = ((IAccountsManager)(this)).Transfer(inValue);

}

}



.NET | Community | Languages and Tools | Speaking | WinFx

Friday, February 24, 2006 3:04:57 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

.NET Rocks and DNRtv episodes up

I recorded a DNR and DNRtv last week in New London and they are already up on the site.

You can download/listen to the .NET Rocks! epsidode here: http://www.dotnetrocks.com

And the DNRtv here: http://www.dnrtv.com

In the DNR episode, we talk about data binding, ClickOnce and a few other related topics.

This DNRtv shows how to do some of the data binding stuff in the designer. Keep your eyes out for another episode in a week or so on ClickOnce deployment.



.NET | ClickOnce | Community | Data Binding | Languages and Tools | Speaking

Friday, February 24, 2006 2:45:20 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, February 22, 2006

Debugging SQL Express Apps - Beware VS Copy To Output Directory default

Here is a little trick that has bitten me on more than one occasion, and just bit someone who attended my data binding session in NYC the other night.

Here is the setup to be bitten by the defaults in Visual Studio:

- Add a SQL Express database to your project

- Edit the schema, add some tables, etc.

- Write some code / data binding that uses the database

- Run a debug session adding records or modifying ones you created through the designer.

- Save the changes from your running debug session.

- Shut down the app and run another debug session, and your changes are no longer there.

First instinct at this point is "there is something screwed up with my data binding / data access code". That instinct may be wrong (although we are all good at writing bugs as well).

When VS adds the MDF file to your project, it places it and its related LDF file in the project root folder, and add them to your project in solution explorer. The file properties for the MDF file include Build Action = Content, and Copy To Output Directory = Copy Always.

What is happening is that your changes are being persisted to the copy of the MDF file that was placed in your build output directory (bin\debug) on the first debug run. Then on the second debug run, the unchanged MDF file from the project root folder is copied down into the build output folder, overwriting the one that was there with your changes from the previous run. As a result, it looks like your changes were not persisted when in fact they were (or may have been if your code was correct).

The solution is that whenever you add a SQL Express DB to your VS project, you probably want to change the Copy To Output Directory property for the file to Copy If Newer.



.NET | Data Binding | Languages and Tools

Wednesday, February 22, 2006 1:21:46 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, February 20, 2006

.NET Rocks! and .NET Rocks! TV Episodes coming up
I went up to New London this week and taped two episodes of DNRtv and one DNR with Carl and Richard. The DNRtv episodes should go up in the next two weeks, one on data binding and one on ClickOnce deployment. The DNR will air on 22 March. Check them out!

.NET | ClickOnce | Community | Data Binding | Languages and Tools | Speaking

Monday, February 20, 2006 6:10:56 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Data Binding with Windows Forms 2.0 Slides/Demos from NYC.NET

I gave a talk on data binding in NYC this Thu night. Had a great time. Lively crowd as always, lots of good questions and interaction.

Here are the slides and demos:

Slides    Demos



.NET | Community | Data Binding | Languages and Tools | Speaking

Monday, February 20, 2006 6:06:58 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Saturday, February 4, 2006

TDC Class Demos
For the folks from my Master class in CA this week, here are the live demos. Anyone's welcome to grab them, most have project names that indicate what was being demoed.

.NET | Languages and Tools | Speaking

Saturday, February 4, 2006 1:28:28 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, January 19, 2006

Fundamentals of Windows Presentation Foundation talk at ONETUG last night

I gave a presentation on WPF last night in Orlando to ONETUG. Great group, lots of good questions, had a lot of fun.

Here are the slides and demos:  Slides   Demos



.NET | Languages and Tools | Speaking | WinFx

Thursday, January 19, 2006 2:08:05 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Data Binding with Windows Forms 2.0 Table of Contents

A couple people have suggested that I post the table of contents for my book to my blog since it is not yet available on Amazon.

Here it is:

Foreword xxi

Preface xxiii

Acknowledgments xxxv

About the Author xxxvii

Chapter 1: Building Data-Bound Applications with Windows Forms 1

What Is Data Binding? 2

Your First Data-Bound Windows Forms 2.0 Application 3

Data-Binding Landscape 14

Data Sources 15

Data Objects and Collections 16

DataSets or Not, That Is the Question... 18

Data-Bound Controls 20

Layered Application Architecture 21

What Is a Smart Client? 27

Where Are We? 28

Chapter 2: Working with Typed Data Sets and Table Adapters 31

A Quick Review of DataSets 31

The Quest for Type Safety 34

Typed Data Set Internals 37

Creating Typed Data Sets 41

Creating Typed Data Sets with the Data Set Designer 42

Typed Data Set-Generated Code 49

Introduction to Table Adapters 52

Filling and Updating a Typed Data Set with a Table Adapter 56

Connection Management 58

Adding Transaction Support to a Table Adapter 62

Adding Helper Data Access Methods 66

Basing Table Adapters on Stored Procedures or Views 67

Adding Queries to Table Adapters 69

Creating Typed Data Sets with Command Line Tools 77

Using Typed Data Sets in Your Code 78

Where Are We? 79

Chapter 3: Introducing Data Binding in Windows Forms 81

The 40,000-Foot View of Data Binding 81

Binding Data Collections to a Grid 86

Binding Data Collections to Multi-Valued Controls 88

Binding Data to Individual Controls on a Form 90

Data Paths Within Data Sources 92

Synchronizing Data Between Controls 96

Smarter Data Containment 97

Paging Through Data 99

Master-Details Data Binding 104

Updating Data Sources Through Data Binding 106

Where Are We? 108

Chapter 4: Binding Controls to Data Sources 111

Getting to Know the BindingSource Component 111

Simple Data Binding with Binding Sources 112

Chaining Binding Sources for Master-Details Data Binding 116

Navigating Data Through a Binding Source 121

Manipulating Data Through a Binding Source 122

Using a Binding Source as a Data Storage Container 124

Filling a Binding Source with a Data Reader 126

Sorting, Searching, and Filtering Presented Data with a Binding Source 128

Monitoring the Data with Events 131

Restricting Changes to the Data 133

Underneath the Covers of Data Binding for Complex Types 134

Binding an Image Column to a PictureBox Control 141

Binding a DateTime Column to a DateTimePicker 142

Binding a DateTime Column to a TextBox 144

Binding a Numeric Column to a TextBox 145

Automatic Formatting and Parsing Summary 147

Going Beyond Built-In Type Conversion with Binding Events 148

Handling the Format Event 154

Handling the Parse Event 156

Completing the Editing Process 157

Making the User’s Life Easier with AutoComplete 160

Data Binding Lifecycle 162

Smarter Child-Parent Data Binding 163

Binding to Multiple Copies of Data 165

Updating Parent Data-Bound Controls from Child Data-Bound Controls 168

Synchronizing Many-to-Many Related Collections 172

Where Are We? 176

Chapter 5: Generating Bound Controls with the Visual Studio Designer 177

Working with the Data Sources Window 177

Adding Data Sources to a Project 179

Choosing the Type of Data Source 180

Adding a Database Data Source 181

Adding a Web Service Data Source 185

Adding an Object Data Source 186

Generating Bound Controls from Data Sources 189

Selecting the Bound Control Type 196

Customizing the Bound Control Types 196

Binding Existing Controls to Data Sources 199

Behind the Scenes: Designer Code and Data Sources Files 202

Other Designer Data-Binding Code Generation 205

Setting Control Data Binding Through the Properties Window 206

Generating Data Bindings with Smart Tags 210

Generating Master-Details Data-Bound Controls with the Designer 214

Where Are We? 216

Chapter 6: Presenting Data with the DataGridView Control 217

DataGridView Overview 218

Basic Data Binding with the DataGridView 219

Controlling Modifications to Data in the Grid 221

Programmatic DataGridView Construction 222

Custom Column Content with Unbound Columns 226

Displaying Computed Data in Virtual Mode 233

Using the Built-In Column Types 241

Built-In Header Cells 255

Handling Grid Data Edits 256

Automatic Column Sizing 259

Column and Row Freezing 262

Using the Designer to Define Grids 263

Column Reordering 266

Defining Custom Column and Cell Types 269

Utilizing Cell-Oriented Grid Features 277

Formatting with Styles 281

Where Are We? 284

Chapter 7: Understanding Data-Binding Interfaces 285

What Does Data Binding Have to Do with Interfaces? 286

The IEnumerable and IEnumerator Interfaces: Supporting Iteration Through Collections 289

The ICollection Interface: Controlling Access to a Collection 295

The IList Interface: Enabling Data Binding 298

The IListSource Interface: Exposing Collections of Collections 303

Property Descriptors: Allowing Dynamic Data Item Information Discovery 305

The ITypedList Interface: Exposing Data-Binding Properties 307

The IBindingList Interface: Providing Rich Binding Support 310

The IBindingListView Interface: Supporting Advanced Sorting and Filtering 323

The ICancelAddNew Interface: Supporting Transactional Inserts in a Collection 325

The IRaiseItemChangedEvents Interface: Providing Item Modification Notifications on Collections 327

The IEditableObject Interface: Supporting Transactional Item Modifications 328

The INotifyPropertyChanged Interface: Publishing Item Change Notifications 329

The ICustomTypeDescriptor Interface: Exposing Custom Type Information 332

The ISupportInitialize Interface: Supporting Designer Initialization 334

The IDataErrorInfo Interface: Providing Error Information 330

The ISupportInitializeNotification Interface: Supporting Interdependent Component Initialization 337

The ICurrencyManagerProvider Interface: Exposing a Data Container’s CurrencyManager 341

Where Are We? 341

Chapter 8: Implementing Custom Data-Bound Controls 343

Extending Framework Data-Bound Controls 344

Creating a Grouped Column DataGridView 345

Using Custom Controls 350

The User Control Test Container 352

Developing Data-Bound Container Controls 353

Building a Filtered Grid Control 354

Adding Data-Binding Capability to a Custom Control 357

Supporting Designer Initialization of Data Binding 359

Specifying Binding Properties on a Control 360

Supporting Delayed Initialization with ISupportInitialize 362

Dynamically Determining the Properties of a Data Source 367

Autocompleting Input in a TextBox Control 371

Autosizing Columns in the Grid 375

Winding Up the Filtered Grid Example 376

Building a Custom Data-Bound Control from Scratch 379

Building a Data-Bound Charting Control for Decision Support 379

Coding a Data-Bound Custom Control 384

Adding Editing Support to a Custom Data Bound Control 391

Where Are We? 397

Chapter 9: Implementing Custom Data-Bound Business Objects and Collections 399

Defining and Working with Data-Bound Business Objects 400

Defining and Working with Data-Bound Business Object Collections 405

.NET Framework Generic Collection Classes 406

The CustomBusinessObjects Example 408

Setting the Textual Data-Binding Behavior of Custom Objects 415

Supporting Transacted Object Editing with IEditableObject 416

Supporting Object Edit Notifications with Property Change Events 420

Supporting Object Edit Notifications with INotifyPropertyChanged 423

Using BindingList<T> to Create Rich Object Collections 424

Creating a Custom Collection Type Based on BindingList<T> 426

Managing Transacted Additions to a Collection 439

Raising Item Changed Events 441

Adding IBindingListView Functionality 443

Binding to Business Objects Through the Data Sources Window 453

Where Are We? 455

Chapter 10: Validating Data Input and Handling Errors 457

Windows Forms Validation 458

Handling Validation Events 459

DataGridView Validation Events 462

Validation Up the Control Hierarchy 463

Displaying Validation Errors with the ErrorProvider Control 464

DataGridView Error Displays 467

DataGridView DataError Event 468

Controlling Validation Behavior with the AutoValidate Property 471

Validation down the Control Hierarchy 472

Extended Validation Controls 474

Capturing Data Errors on Data Sets 475

Providing Error Information from Custom Objects with IDataErrorInfo 479

Data Concurrency Resolution 483

Where Are We? 484

Appendix A: Binding to Data in ASP.NET 487

ASP.NET Page Processing Basics 489

Data Binding in ASP.NET 1.X 490

Data-Binding Overview in ASP.NET 2.0 498

Data Sources 499

Data-Binding Expressions 508

GridView Control 509

DetailsView Control 512

FormView Control 514

Master-Details Binding 515

Hierarchical Binding 518

Where Are We? 519

Appendix B: Binding Data in WinFx Applications 521

WinFx UI Programming and Capabilities Overview 522

Writing a Simple WinFx Application 525

WinFx Data Binding 101 532

Data Contexts and Data Sources 536

What About XAML? 537

Binding a Collection to a Grid with Templates 541

Control Styling in WinFx 543

Where Are We? 545

Appendix C: Programming Windows Forms Applications 547

Your First Windows Forms Data Application 548

Creating Windows Forms Applications with Visual Studio 554

Windows Forms Designer-Generated Code (New in 2.0) 563

A Brief Tour of the Windows Forms Architecture 567

The Dawn of .NET Execution—The Main Method 570

Handling Control Events 574

Displaying Other Forms 576

Containing Forms Within a Parent Form 577

Common Data Display Controls 578

Creating a Custom User Control 586

Laying Out Controls on a Form 589

Setting Tab Order 596

Command and Control of Your Windows Forms Applications (New in 2.0) 598

Where Are We? 600

Appendix D: Accessing Data with ADO.NET 601

Relational Data Access 603

The Ubiquitous DataSet 607

Loading Data Sets from a File 609

Creating a Data Set Programmatically 611

Loading Data Sets from a Database 613

Loading a DataTable with a DataReader 619

Master-Details DataSets 621

Retrieving Data with Stored Procedures 623

Updating the Database Using Data Sets 624

Handling Concurrency 628

Updating with Data Sets and Stored Procedures 632

Searching Data Sets 637

Merging Data from Multiple Data Sets 639

Working with Data Views 641

Working with Transactions 643

Scoping Transactions with System.Transactions 647

Client-Side Transactions 650

Data Set and Data Adapter Events 651

Reading Data into Business Objects 654

XML Data Access 658

Working with the XmlDataDocument Class 659

Working with the XPathDocument Class 663

Loading Data into an XPathDocument 664

Querying XML Data 665

Navigating an XML Document 667

Where Are We? 670

Index 671



.NET | Data Binding | Languages and Tools | Publishing

Thursday, January 19, 2006 1:58:00 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, January 18, 2006

Data Binding with Windows Forms 2.0 Talk in Sarasota last night

I gave a talk on data binding at the Sarasota FL .NEt Users Group last night. Had a great time, and it was especially fun to present this topic this time since it was the first time presenting on data binding since my book came out. Gave away a couple copies. It was also great to go have some beers with the group members afterwards, including fellow MVPs Stan Schultes and David Hayden.

You can grab the slides and demos here:  Slides   Demos



.NET | Community | Data Binding | Languages and Tools | Speaking

Wednesday, January 18, 2006 2:16:15 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Data Binding with Windows Forms 2.0 is out!

It was a very cool feeling to have a box of my books delivered to me on Friday. After starting way too early on it and rewriting many of the chapters multiple times as the capabilities evolved in Visual Studio 2005 and .NET 2.0, it felt very good to finish the writing a couple months ago. But having the finished product show up on my doorstep was very cool.

So stop reading this and go buy one dammit! :)



.NET | Data Binding | Languages and Tools | Publishing

Wednesday, January 18, 2006 2:10:01 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, January 12, 2006

VS 2005 DC Launch Event

I co-presented the Smart Client session at the DC Launch event yesterday at the Washington Convention Center with Marc Schweigert, a Microsoft Developer Evangelist for the Federal Sector. We covered a lot of good material on Windows Forms 2.0 capabilities including data binding and ClickOnce, two topics close to my heart since I have written/am writing books on them. I also spent most of the day in the Ask the Experts booth along with other local DC area experts like Sahil Malik, Randy Hayes, G. Andrew Duthie, Darrell Norton, Jonathan Cogley and Vishwas Lele. Besides being a great opportunity to catch up with all these guys and exchange ideas, it was a great day talking to developers from the area and seeing how much enthusiasm there is around the availability of VS 2005 and .NET 2.0. Most of the people there had spent little to no time looking at the new stuff, so there was the usual "wow!" reaction when they saw all the great features and capabilities that are now available to them.

I think we ended up with over 2000 attendees at the event, with about a thousand or so sticking around to the bitter end for our session, which was last up at 4:30-5:45.

The folks at Microsoft that put together the event (Darryl Schaffer in particular) did a great job organizing and running the event.



.NET | Community | Languages and Tools | Speaking

Thursday, January 12, 2006 8:47:01 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, January 5, 2006

Data Binding with Windows Forms 2.0 Sample Code Posted

I posted all the sample code for my book Data Binding with Windows Forms 2.0 on the book Web site at http://www.softinsight.com/databindingbook. The samples are available in both C# and VB, even though all the code in the book is in C#. The book should be hitting the shelves very soon and is already selling well on Amazon.

I also posted instructions for running the samples if you do not have a non-default instance of SQL Server or don't have Northwind on your machine yet, also how to run the samples with SQL Server 2005 Express, Visual C# 2005 Express and Visual Basic 2005 Express.

Happy Data Binding!



.NET | Data Binding | Languages and Tools | Publishing

Thursday, January 5, 2006 3:06:29 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, December 1, 2005

Adding a Drop-Down List (ComboBox) Column of Lookup Values in a DataGridView

A common requirement and question that is very easy to solve with the DataGrid is the need to have a column or columns in a grid that contain a drop down list of lookup values from a related table. For example, in Northwind, we have the Products table with a foreign key column SupplierID that relates the to Suppliers table. The values in the Suppliers table could be treated as a list of lookup values for editing the supplier associated with a product:

Application image

When a supplier is selected from the drop down list, it should set the SupplierID column value for that row in the products table. This is very easy to achieve through the Windows Forms designer and the smart tag for a DataGridView control.

Do the following to try it out:

1. Create a Windows Forms Project.
2. Add a data source to a data set that contains Products and Suppliers tables from the Northwind database. This could be any kind of Data Source (Database, Object, Web service), but for simplicity for trying out the designer, just use a database one which adds the typed data set into the Windows Forms project. Products is the table of data we will display in the grid, and Suppliers is the lookup table related through a foreign key column in the Products table that we want to display as a combo box of selectable values in the grid.
3. Drag and drop Products from the Data Sources window onto the form. This will generate the grid, a data set instance, a table adapter to fill it, a BindingSource component hooked up to the data set and the Products table within it, a grid hooked up to the products binding source, and a binding navigator hooked up to the binding source.
4. Click on the grid smart tag (little triangle on upper right border of control).
5. Select Dock in Parent Container.
6. Select Edit Columns.
7. Select the SupplierID column in the list on the left.
8. Select the ColumnType property and set it to DataGridViewComboBoxColumn.
9. Select the DataSource property and navigate down through the data source tree through Other Data Sources > Project Data Sources > NorthwindDataSet > Suppliers table.

data sources property editor
10. Select the DisplayMember property and select CompanyName.
11. Select the ValueMember property and select SupplierID.
12. Click OK to close the Edit Columns dialog.
13. Run the app and observe that you get the drop down list of suppliers. Selecting a supplier actually changes the SupplierID column value for that row in the products table to the appropriate foreign key value.

You can download a completed sample that was generated with these steps here.



.NET | Data Binding | Languages and Tools

Thursday, December 1, 2005 3:05:10 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, November 30, 2005

Launching unmanaged applications with ClickOnce

The question came up from several attendees at my MSDN Webcast on ClickOnce yesterday:

"Can I launch a XXX application using ClickOnce?" (fill in XXX with VB6, MFC, etc. - non-.NET applications)

The answer is yes, you will just have to employ a little trick.

What you need is a simple little launcher application that IS a Windows .NET application. So do the following:

  1. Create a new Windows Application project with VS 2005.
  2. Delete the Form1 from the project.
  3. Add the unmanaged EXE and any supporting files to the VS 2005 project, which makes them part of this application from a ClickOnce perspective. As a result, they will get deployed with this application to its cache folder and can be executed by this launcher app.
  4. Edit the Program.cs file Main method and delete the current method body (which launches the application and the form) and replace it with code to launch the unmanaged executable. This just requires a single line of code: Process.Start("MyUnamangedApp.exe");

Note: You will need to give the launcher app full trust in the ClickOnce security settings.

Note2: If the unmanaged app relies on ActiveX or COM objects, those need to be added to the project as well, and you will need to add a reference to the COM DLL's to the project to get their reg-free COM information added to the manifest. See this article for more details.

You can download a sample implementation here.



.NET | ClickOnce | Community | Languages and Tools | Speaking

Wednesday, November 30, 2005 3:29:32 PM (GMT Standard Time, UTC+00:00)
Comments [1]  | 

Demos from ClickOnce MSDN Webcast

For those who attended or are interested, here are the demos from my MSDN Webcast on ClickOnce yesterday.

You can find the webcast link for on-demand viewing here.

For the demo that went awry demonstrating on-demand updates, the little mistake I made was that I said that if you turn off automatic updates (Check for updates option at top of Updates dialog), then you need to put in an Update location, which is true. But what I was doing was fully qualifying the path to the deployment manifest, which is incorrect. What you need to put is just the URL to the root folder where the deployment manifest resides. VS will automatically append the deployment manifest file name. So when I was putting in:

http://localhost/ClickOnceOnDemand/ClickOnceOnDemand.application

I should have just been putting

http://localhost/ClickOnceOnDemand/

Another little tidbit I didn't mention is that you will need Full Trust for on-demand updates, which is unfortunate because it means the app has to request full trust even though it may not be doing anything privileged beyond on-demand updates.



.NET | ClickOnce | Languages and Tools | Speaking

Wednesday, November 30, 2005 2:31:21 PM (GMT Standard Time, UTC+00:00)
Comments [4]  | 


 # Tuesday, November 29, 2005

WCF Config file intellisense... why hath thou forsake me?

In previous builds of WCF (Indigo), you had to have a particular namespace included in your config file. Specifically, instead of the default root element of:

<configuration>
<!-- The rest of your config settings -->
</configuration>

You needed to have:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<!-- The rest of your config settings -->
</configuration>

By doing that in previous builds, you got intellisense for the schema elements and attributes of the <system.serviceModel> element, letting you discover the right entries to get features like transactions, security, bindings and so on correctly configured.

When I installed the Nov CTP, I was immediately lost because my intellisense seemed to have gone away. If you add a WinFx Service from the Web Site templates, the web.config still has the namespace shown in the second config snippet above. But the trick is that it is no longer needed, and in fact confuses VS on what schema elements to expose through intellisense. The system.serviceModel schema elements are now merged with the C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas\DotNetConfig.xsd schema as part of the VS extenstions install, so they are there by default now in the config file intellisense.

Thanks to my colleague Juval Lowy for discovering this fact and giving me back my intellicrack!



.NET | Languages and Tools | WinFx

Tuesday, November 29, 2005 8:02:24 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

DataGridView Webcast demos

Here are the demos from my MSDN Webcast today on the DataGridView control.

You can find the sample DataGridView chapter for my book here.

You can view the webcast on demand through the links here.



.NET | Community | Data Binding | Languages and Tools | Speaking

Tuesday, November 29, 2005 7:44:11 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, November 24, 2005

Slides and demos from Boulder .NET

I gave a talk on connecting smart clients with WCF on Tuesday at Boulder .NET. Had a good turnout desipte the proximity to the holiday and had a good time.

The talk covered the fundamentals of connecting applications with WCF since most of the people there had never seen anything on WCF. Then I moved into some of the specific client concerns when using WCF, similar to my talk at VSConnections.

You can get the slides and demos here:  Slides   Demos



.NET | Community | Languages and Tools | Speaking | WinFx

Thursday, November 24, 2005 3:24:32 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Sunday, November 20, 2005

Interface-based Programming example employing the Factory pattern

When I demonstrate the use of interface-based programming in a class, I always give a demo of using interface-based programming combined with a factory pattern to add dynamic behaviors to an application. This is basically a scaled down version of what the provider model in ASP.NET 2.0 and the Enterprise Library do to allow you to externally configure components that will be called by the framework at runtime. ASP.NET actually uses abstract base classes instead of interfaces because they also provide some shared implementation, but the concepts are basically the same.

 

I use a simple little example of a client that defines an IDog interface (in a separate interface only assembly that it can share with component providers) that specifies the contract that providers are expected to implement. I then show how to build components separately that the client has no specific type information about, and load and invoke the behavior defined in those components dynamically through a factory and based on the interface definition that is the contract for how those components expose their behavior and some configuration file entries that the factory can use to load and instantiate the types. The client is able to do this without requiring any code modifications to accept new components, and can even have new behaviors added at runtime without needing to restart the application.

 

I have repacked the demo I normally give in class to:

Make it a little cleaner

Separate out the factory into a generic factory in a separate assembly that could be reused for any project

Use the new Settings features in the .NET 2.0 framework to enter the type information into a configuration file instead of using a separate XML file like I used to.

 

The factory method looks like the following:

 

public static T[] ConstructType<T>() where T : class

{

   // Refresh the config cache in case the config file has been edited at runtime

   Settings.Default.Reload();

   // Load the collection of components from the string collection in config

   StringCollection componentTypeInfoColl = Settings.Default.Components;

   // Create a list to add the components to as they are created

   List<T> components = new List<T>();

   // Loop through the config strings trying to create instances of the appropriate type

   foreach (string componentTypeInfo in componentTypeInfoColl)

   {

      try

      {

         // Config entries should be in the form:

         // Fully.Qualified.TypeName, AssemblyName

         // Split into its two parts

         string[] typeInfo = componentTypeInfo.Split(',');

         // Dynamic load the assembly

         Assembly assem = Assembly.Load(typeInfo[1].Trim());

         // Dynamic instance creation

         T instance = assem.CreateInstance(typeInfo[0].Trim()) as T;

         if (instance != null)

         {

            components.Add(instance);

         }

      }

      catch { } // Just ignore invalid types

   }

   return components.ToArray();

}

 

So the only things you need to know to use this as a factory for other purposes than this demo is that it expects the type information to be entered in the client configuration file with an application settings section like the following:

 

<configuration>

    <configSections>

        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >

            <section name="DynamicFactoryLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

        </sectionGroup>

    </configSections>

    <applicationSettings>

        <DynamicFactoryLibrary.Properties.Settings>

            <setting name="Components" serializeAs="Xml">

                <value>

                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">

                        <string>Animals.Dog, Animals</string>

                      <!--

                        <string>Animals.GermanShepherd, Animals</string>

                        <string>Animals2.Shitzu, Animals2</string>

                        -->

                    </ArrayOfString>

                </value>

            </setting>

        </DynamicFactoryLibrary.Properties.Settings>

    </applicationSettings>

</configuration>

 

I’m just using a StringCollection as the type for the component type collection, so each component that you want to add to the collection should be added to the section in the form:

 

<string>Animals.Dog, Animals</string>

 

You can see a couple of additional components commented out for dynamically adding them into the application (even while it is running). The type information uses a standard convention for specifying type information through a config file: specifically the fully qualified type name of the type, followed by a comma, followed by an Assembly name to load it from.

 

You can grab the whole sample here.

 

To demonstrate the example in action:

  • First build the InterfaceBasedProgramming solution, which builds the interface contract assembly, the factory library, and the client application. The default client config file has all of the type information for available components commented out.
  • Open the build output folder of the client (InterfaceBasedClient\bin\debug) and run the client by double clicking on InterfaceBasedClient.exe.
  • Push the button and observe that you get nothing because no types have been provided or plugged in though the config file yet. Leave the client running.
  • Next open the Animals solution, build it, and copy the build output (Animals.dll) from the bin\Debug folder into the client’s bin\Debug folder.
  • Edit the InterfaceBasedClient.exe.config file through an editor, and uncomment the Dog type information as shown in the snippet of config file above, save the file.
  • Hit the button in the client again, you should see a standard Dog Bark (through a message box).
  • Edit the config file again, uncommenting the type information for a GermanShepherd (which is also defined in the Animals assembly), and save.
  • Push the button again and you will see that type is dynamically used from the already loaded assembly.
  • Go open the Animals2 solution and build it.
  • Copy the Animals2.dll from its bin\Debug folder into the bin\Debug folder for the client.
  • Edit the config file for the client again to uncomment the type information for the Shitzu type, and save.
  • Click the button in the client again and you should see all three types of dogs bark. 


.NET | Architecture | Languages and Tools | Speaking

Sunday, November 20, 2005 4:16:02 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

.NET Systems Programming class dynamic demos

For the students from my recent class in Sweden, you can download all the demos I did dynamically (as opposed to the ones you already have in your demos folder and available on our site at www.idesign.net) from the following link:

http://www.softinsight.com/downloads/Linsoft05ClassDemos.zip

 



Languages and Tools | Speaking | Travel

Sunday, November 20, 2005 3:43:04 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Friday, November 11, 2005

WCF Talks: Event Driven Applications and Connecting Smart Clients

I gave two WCF (Indigo) talks at DevConnections today:

Build Event Driven Applications with Indigo:   Slides   Demos

Connecting Smart Client Applications with Indigo:  Slides   Demos

In the Event Driven Applications session I cover creating list based subscription services with direct callback services in the clients, using duplex channels to set up callbacks, and a Pub-Sub implementation that gives loosely coupled events that I will have more information on here in the near future.

In the smart client session, I covered client concerns with respect to channel selection, asynchronous calls, sessions, transactions, callbacks, security, and peer-to-peer.

Good time!



.NET | DevConnections | Languages and Tools | Speaking

Friday, November 11, 2005 2:41:25 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Secure ClickOnce Demployment Talk at DevConnections yesterday

My second session of the day yesterday at DevConnections was on ClickOnce deployments, and specifically the various security protections and options that ClickOnce offers for preventing unauthorized applications from being able to run through a ClickOnce launch.

You can grab the slides and demos here:  Slides   Demos

Some of the key takeaways from this session were the following:

  • ClickOnce provides a simple, powerful, and easy to use mechanism for deploying smart client applications with minimal maintenance effort and IT Admin involvement
  • ClickOnce provides runtime security protections through the Code Access Security (CAS) infrastructure of .NET to prevent applications launched from ClickOnce from being granted permissions to perform any operations or access any resources that the application was not specifically allowed to do.
  • ClickOnce app default permissions are determined by the launch URL and how it maps to built-in CAS location-based code groups (MyComputer, LocalIntranet, Internet, TrustedSites, UntrustedSites).
  • If the application manifest requests permissions greater than those that would be granted based on the CAS location-based code groups, permission elevation needs to occur.
  • By default, permissions can be elevated in one of two ways: user prompting or trusted publishers.
  • If an application is launched through a link to a deployment manifest that is signed by a publisher certificate that is not in the Trusted Publishers certificate store on the client machine, the user will be prompted by default and can accept or reject the application. If they accept it, the permissions for that application will be elevated to whatever permissions the application manifest has requested.
  • If an application is launched that was signed with a publisher certificate that is in the client machine's Trusted Publishers certificate store, then no user prompting will occur and the application permissions will be automatically elevated to whatever the application manifest requests because it is coming from a trusted source identified implicitly by IT admin when they installed the publisher certificate in the Trusted Publishers store.
If you want to prevent the user from ever being prompted and only allow applications from trusted publishers to be launched through ClickOnce (a good idea in an enterprise environment), then you should create the registry key discussed in the slides from the session and set the string values to Disabled for all the zones.

.NET | ClickOnce | DevConnections | Languages and Tools | Speaking

Friday, November 11, 2005 2:33:37 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, November 9, 2005

Build Custom Data Bound Business Objects and Collections Talk at DevConnections this morning

I just got finished doing my first talk here at DevConnections in Vegas and I think it went pretty well. Great crowd, good questions, fun topic.

You can grab the slides and demos here: Slides   Demos

The talk highlighted how to define custom objects and collections to make them suitable for data binding, mostly for Windows Forms, but some of it is applicable to ASP.NET as well.

The key takeaways from the talk are:

  • Implement INotifyPropertyChanged on any business entitity type you define that you expect to use in data binding scenarios. This interface defines a contract for the objects to raise PropertyChanged events whenever a property is set on the object. It allows containing collections or bound controls to be notified when the contents of the data object change, which helps with keeping controls synchronized in a form.
  • Use BindingList<T> to create strongly typed collections of objects that support rich data binding. It provides full implementation of IList, ICollection, IEnumerable and their generic strongly typed counterparts for whatever type parameter you provide, and it provides a partial implementation of the IBindingList interface. The part that it implements is firing ListChanged events when items are added or removed from the collection. It also looks at the objects type that you provide as a type parameter, and if it implements INotifyPropertyChanged, the collection will subscribe to the PropertyChanged event on each object and raise ListChanged events with a change type of PropertyChanged whenever the contents of an object in the collection change. These features make BindingList<T> collections work seamlessly with data binding to multiple controls and keeps the controls all in sync.
  • Use my BindingListView<T> class (in the demos and in my book) to get a generic container that supports sorting (both IBindingList based single property sorts and IBindingListView multi-property sorts), searching, and filtering.

If you were there at the end and saw the on-the-fly demo where I didn't see the saving behavior that I thought I had just implemented, I tracked down the problem. the changes were actually being saved. It was just the way I hooked up the data binding I wasn't seeing those changes.

In the demo, I used the data sources window to generate a Details view (control collection) bound to a collection of Album data. I changed one of the controls in the collection which was bound to a GenreID property on the Album objects to a ComboBox. I then used the Data Sources window to add data binidng to a Genre object collection to populate the list of Genres in the combo box. This sets up the ComboBox to have its contents determined by the Genre collection, but its SelectedValue property is bound to the GenreID property on the current item in the Album collection - generally exactly what you want to be able to edit a property on one object collection item through a lookup list of values in another collection of objects. The problem was that after I selected a new value in the combo box and saved the changes, then restarted the app, I wasn't seeing the modified value set for the Album I was viewing in the other controls.

It turns out the problem was just the order that I did the initial binding of the control collection and the combobox BindingSources. In the form load I had added the following two lines of code to bind the control collection and the combo box binding sources:

albumBindingSource.DataSource = Album.GetAlbums();
genreBindingSource.DataSource = Genre.GetGenres();

The problem is that when you set the DataSource, that is when it intializes the bound controls. So I was initializing the data bindings for all of the controls based on the album data, then intializing the combo box of Genres with a new set of data. That set the SelectedIndex of the ComboBox back to zero, so I wasn't seeing the actual value of the Genre for the current Album, I was just seeing the first Genre value in the Genre collection. The fix is simply to do the initial binding in the reverse order:

genreBindingSource.DataSource = Genre.GetGenres();
albumBindingSource.DataSource = Album.GetAlbums();

Then it works as expected.

Some resources I mentioned in the talk, as well as some additional ones I gave related to after-session questions:

My Book: Data Binding in Windows Forms 2.0, Addison Wesley, January 2006
http://www.amazon.com/exec/obidos/ASIN/032126892X/qid%3D1124482085/sr%3D11-1/ref%3Dsr%5F11%5F1/102-3039504-6850510
Rocky Lhotka binding refresh problem post:
http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=d8306469-7e76-4734-9811-777498808b85
Rocky Lhotka article on binding to business objects: Windows Forms Object Data Binding in .NET 2.0, 15seconds.com, http://www.15seconds.com/issue/040614.htm
My recent article on The Server Side .NET: Build a Data Access Layer with the Visual Studio DataSet Designer, The Server Side .NET, Oct 2005, http://www.theserverside.net/articles/showarticle.tss?id=DataSetDesigner
My recent article in CoDe magazine: Tackle Complex Data Binding in Windows Forms 2.0, CoDe Magazine, July/Aug 2005, http://www.code-magazine.com/Article.aspx?quickid=0507051

Enjoy!



.NET | Data Binding | DevConnections | Languages and Tools | Speaking

Wednesday, November 9, 2005 8:26:45 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

ClickOnce user privilege requirements discussion
Great post by my colleague Michele from IDesign following a discussion we had on ClickOnce permissions and what users are allowed to do. Check it out!

.NET | ClickOnce | DevConnections | Languages and Tools

Wednesday, November 9, 2005 4:26:54 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Tuesday, November 8, 2005

Las Vegas Bound - Impressions of WCF

I'm catching a flight early tomorrow morning to Vegas for VS Connections and am really looking forward to it. VS Connections in particular, and DevConnections in general (the overall conference event) is well run, in great locations, and always has a lot of great content that I can benefit from as well.

I've been spending most of my recent prep time fine tuning the demos for my two WCF sessions, Build Event Driven Applications with Indigo and Connecting Smart Client Applications with Indigo. The more I work with Windows Communications Foundation (aka "Indigo"), I am struck by a number of things:

  • I am impressed by how capable Indigo is.
  • I am awed by how elegant and simple solutions are to complex aspects like security, transactions, queuing, callbacks, and so on.
  • I am dumbfounded by how hard it is to figure out how to get to those elegant and simple solutions.

The last bullet is not really a criticism of what they have come up with, it is just the nature of the beast. I would draw on an analogy from my flying days to explain why this is so. Imagine the cockpit of a WW I fighter aircraft. You probably have half a dozen or less simple dials and gauges, and a stick and throttle. Imagine trying to use that set of controls on an aircraft that can fly at high subsonic speeds at high altitude carrying hundreds of passengers for 12 hour transoceanic flights. Not going to work too well. This is basically where you were at with past technologies to build complex, distributed, heterogenous, connected enterprise systems. It could be done, but the end result was not going to be pretty and it was going to take you a long time to get there.

Now with WCF, it is more like climbing into the cockpit of a 777. There is a technological elegance to everything that is there. But there are still hundreds (if not thousands) of individual switches, controls, displays, electronic gages and dials, menu driven control panels, etc. A great deal of human engineering has gone into everything that is in there so that for any given common task, there are only a couple of relevant controls that you have to touch and put into place to get the job done. The challenge is in knowing which one of those hundreds of knobs and dials to tweak.

The same is true for WCF. Microsoft has created an incredibly powerful and technologically advanced platform that is well adapted to building large distributed enterprise systems. In order to do that, there needs to be hundreds of switches and knobs that you can throw to address different scenarios. The downside to that is bullet number three above - you have to learn which switches and knobs are relevant for a given task, and in what order to throw them.

This is somewhat aggravated right now in that we are only at Beta 1 of WinFx (and its parts WCF, WPF, and WinWF), and the names, shapes, and locations of all the knobs and switches is constantly changing as they work on that human engineering task of trying to make it easier to use. Meanwhile the documentation and samples are seriously lagging, so working with it right now is a little like stepping into that 777 cockpit without any labels on the controls. When you say to yourself, "I just need transactions and certificate based security", it is kind of like saying "I just need to call the flight attendant at the second aft flight station". Simple to describe, but God help you in figuring out which switches and knobs to throw. At least there are not really any destructive ones that you can throw by accident. If you get it wrong, your app may not work, but you would have to go out of your way to write some code that would do bad things when WCF fails to let you communicate.

I'm looking forward to continuing to work with this technology and learn what all those knobs and buttons are for. Learning all the controls of the aft cockpit of the F-14 to run the weapons system, navigation systems, communications systems, and other tasks was one of the funnest things I have done in my life. The fact that we got to do that while strapped to a couple of 50K lb + of thrust zorching through the sky pulling G's and landing on the carrier certainly helped make it interesting. Sitting at a computer leaves a little to be desired in that department, but the learning challenge is still just as fun.



.NET | Architecture | DevConnections | Languages and Tools | Speaking | Travel | WinFx

Tuesday, November 8, 2005 7:13:55 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Thursday, October 27, 2005

Production versions of VS 2005 up on subscriber downloads
Get yer RTM here, hot fresh RTMs...

.NET | Languages and Tools

Thursday, October 27, 2005 6:25:16 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, October 24, 2005

Upcoming DevConnections Talks

I'll be speaking at Visual Studio Connections (part of DevConnections) in Las Vegas from 5-8 November. This is a great and growing conference that happens twice annually in the US, usually Orlando in the spring and Las Vegas in the fall, that I have been privileged to speak at for the last couple years. If you haven't been to one yet, you ought to be hammering your boss for permisson/funding to attend for the following reasons:

  • It will rapidly and time-effectively expose you to new solution technologies you might not get a chance to explore on your own
  • You will get concentrated advanced training in current and future technologies, getting you up to speed on them in far less time than you can achieve on your own
  • You will get presentations from the top speakers in the business
  • You will get a chance to network with peers in the industry, learn from others experiences employing .NET technologies, which will make you more effective at employing them yourself
  • You will have a lot of fun (OK, maybe don't tell your boss this...)

You can learn a lot peripherally from the conference too by reading the DevConnections blog here. There are posts from other speakers as they develop their talks and their own observations and experiences at the conference.

I'll be presenting the following sessions:

VSM356: Build Custom Data Bound Business Objects and Collections
VSM351: Secure Smart Client ClickOnce Deployments
VID306: Build Event-Driven Applications with Indigo
VID309: Connect Smart Client Applications with Indigo

If you make it to the show (and you should!!), stop by and say hi!

 



.NET | Architecture | ClickOnce | Community | Languages and Tools | Speaking | DevConnections

Monday, October 24, 2005 9:48:04 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Two Upcoming MSDN Webcasts: Part of the "Best Of" Series

I've got two MSDN Webcasts coming up at the end of November, both part of the "Best Of" series that they are doing surrounding the launch of VS 2005 for those Webcasts focused on .NET 2.0 and VS 2005 that got the highest scores in the last year.

You can click through here to get to the webcasts:

Click Through for Webcasts

The two I am giving will both be on 29 November:

Presenting Rich Rich Tabular Data with the DataGridView Control
Tuesday, November 29, 2005
10:00 A.M.–11:00 A.M. Pacific Time

Deploy Smart Client Applications with ClickOnce
Tuesday, November 29, 2005
1:00 P.M.–2:00 P.M. Pacific Time

Check them out!!



.NET | ClickOnce | Community | Data Binding | Languages and Tools | Speaking

Monday, October 24, 2005 6:59:35 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

IDesign Site Facelift
We just got a new site up and running for IDesign. You can check it out at http://www.idesign.net. Much nicer look and feel, and a lot easier to access the many resources we have available there, such as our download library, articles, events on the homepage, and RSS feeds for dynamic content like events.

.NET | Community | Languages and Tools | Speaking

Monday, October 24, 2005 6:42:37 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, October 12, 2005

Building Smart Client Data Applications with Windows Forms 2.0

I gave a talk at LexDotNet in Lexington KY last night on building smart client data apps. It really boils down to a similar talk to my Tackle Complex Data Binding with Windows Forms 2.0 talk, but with a slightly different approach and angle. I did mostly a large progressive demo where I started out with the simple and impressive data binding capabilties for working directly with a database in your Windows Forms app. Then I explained why you should never do that in a serious production application and stepped through how to migrate the functionality to a three or four layer/tier architect without giving up any of the capability of the data binding features in Windows Forms.

Here are the slides and demos that I used.



.NET | Community | Data Binding | Languages and Tools

Wednesday, October 12, 2005 8:58:14 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, September 29, 2005

On-Demand Updates with ClickOnce

ClickOnce supports both automatic updating and on-demand updates. The default model checks for updates automatically at application launch (when connected), and applies those updates immediately. There are a number of options available for installed applications (available online and offline), including whether to check automatically at all, whether to do it on a background thread, whether to do it on a timed interval, and other options.

 

However, sometimes you may want to do updates on demand, either as the only update model, or in combination with automatic updating in the background on a periodic interval. To do that, you will need to use the ClickOnce API defined in the System.Deployment framework assembly.

 

The main class you will use to support on-demand updates is the ApplicationDeployment class defined in the System.Deployment.Application. You will typically add code in response to a user action (such as selecting a Check For Updates menu item) that goes out and checks to see if updates are available, and if so retrieves them. You will then need to restart the application to have those changes applied.

 

A simple but common pattern to accomplish this is something like the following:

 

// First check to see if we are running in a ClickOnce context

if (ApplicationDeployment.IsNetworkDeployed)

{

   // Get an instance of the deployment

   ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;

 

   // Check to see if updates are available

   if (deployment.CheckForUpdate())

   {

      DialogResult res = MessageBox.Show("A new version of the   

         application is available, do you want to update?",

         "Application Updater", MessageBoxButtons.YesNo);

      if (res == DialogResult.Yes)

      {

         // Do the update

         deployment.Update();

         DialogResult res2 = MessageBox.Show("Update complete, do you

            want to restart the application to apply the update?",

            "Application Updater", MessageBoxButtons.YesNo);

         if (res2 == DialogResult.Yes)

         {

            // Restart the application to apply the update

            Application.Restart();

         }

      }

   }

   else

   {

      MessageBox.Show("No updates available.", "Application Updater");

   }

}

else

{

   MessageBox.Show("Updates not allowed unless you are launched through ClickOnce.");

}

 

There are of course asynchronous versions of the CheckForUpdate and Update methods if you want to avoid blocking your UI while this happens.

 

The project settings you will need may not be completely apparent. The first important setting is that you need to change the update behavior of the ClickOnce deployment to stop automatically checking for updates if you are doing only on-demand updates. You do this through the Publish tab of the project properties settings, Updates button, shown in Figure 1.

 

Publish settings

Figure 1: ClickOnce Update Behavior Settings access

 

When you click that button, the dialog in Figure 2 will show with default settings selected as shown.

Update Settings defaults

 

Figure 2: ClickOnce Update Settings Dialog

 

What you will want to do for a pure on-demand updates application is to uncheck the box that says the application should check for updates at the top. The other trick that is not apparent but required is that you have to specify an Update location at the bottom or you will get an obscure error message when you try to launch the application on the client. So you should set up the update settings like shown in Figure 3.

Modified update settings

Figure 3: ClickOnce On-Demand Update Settings

 

With those settings in place, when you publish your application out and the client launches it, they can invoke the code shown earlier to check for and apply updates on-demand.

 

If you wanted to combine on-demand updates with periodic background checking for updates, you can do that by leaving updates enabled, but you will need to select the option to check for updates after the application starts. You will then want to configure the frequency of checking using the options in the middle of the dialog.

 



.NET | ClickOnce | Languages and Tools

Thursday, September 29, 2005 10:49:06 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Generating a good stored procedure CRUD Layer with CodeSmith

If you are not already using CodeSmith to avoid repetitive coding tasks, you should really take a look at it. One of the things I use it for frequently is to generate a clean stored procedure layer on top of my tables for doing standard CRUD (SELECT, INSERT, UPDATE, DELETE) operations on those tables.

Specifically, what you usually need for most tables in your database are:
- A SELECT proc that returns all rows
- A SELECT proc that takes a primary key value and returns the corresponding row
- An INSERT proc that adds a row to the table
- A DELETE proc that removes a row
- An UPDATE proc that modifies a row

I actually prefer to just have a single SELECT proc that takes a primary key parameter that defaults to NULL. If that parameter is NULL, it returns all row, otherwise it returns just the one row requested. That saves on the number of adapters/commands you have to create to do SELECTs.

In combination with these procs, you will want to add a column to your tables if at all possble that can be used for optimistic concurrency checking. You can use a datetime column that gets updated with every modification to a row, a timestamp column, or a uniqueidentifier with the rowguid property set to get it to auto-update.

If you use this pattern or want to, I wrote a CodeSmith template that will code generate all the stored procs for you. You feed it a table name and the name of the column that is used for optimistic concurrency checking. It will then generate the appropriate stored procs to ensure everything gets updated correctly based on the optimistic checking column type. You can download it here.
http://www.softinsight.com/downloads/StoredProcsForConcurrencyColumnTables.zip
Also in that zip is another template that will let you generate all the procs for all the tables in your database. It will skip any tables that do not have the concurrency column name specified, or that do not have a primary key.

This pattern also happens to work beautifully with typed data sets and table adapters in VS 2005.

As an example, if you add a Modified datetime column to the Employees table in Northwind, and set its default value to the getdate() function, you now have a good column that can be used for optimistic concurrency checking, as long as you wrap it in stored procs that update the Modified column on updates. The template I wrote generates the following code with the click of a button:

/****** Object:  Stored Procedure dbo.DeleteEmployees    Script Date: Wednesday, September 28, 2005 ******/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[DeleteEmployees]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[DeleteEmployees]
GO

/****** Object:  Stored Procedure dbo.GetEmployees    Script Date: Wednesday, September 28, 2005 ******/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SelectEmployees]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SelectEmployees]
GO

/****** Object:  Stored Procedure dbo.InsertEmployees    Script Date: Wednesday, September 28, 2005 ******/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[InsertEmployees]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[InsertEmployees]
GO

/****** Object:  Stored Procedure dbo.UpdateEmployees    Script Date: Wednesday, September 28, 2005 ******/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[UpdateEmployees]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[UpdateEmployees]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS OFF
GO
------------------------------------------------------------------------------------------------------------------------
-- Date Created: Wednesday, September 28, 2005
-- Created By:   Generated by CodeSmith
------------------------------------------------------------------------------------------------------------------------

CREATE PROCEDURE dbo.DeleteEmployees
 @EmployeeID int,
 @Modified datetime
AS

DELETE FROM [dbo].[Employees]
WHERE
 
 [EmployeeID] = @EmployeeID
 AND [Modified] = @Modified
GO

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
------------------------------------------------------------------------------------------------------------------------
-- Date Created: Wednesday, September 28, 2005
-- Created By:   Generated by CodeSmith
------------------------------------------------------------------------------------------------------------------------

CREATE PROCEDURE dbo.SelectEmployees
 @EmployeeID int = NULL
AS

 IF (@EmployeeID IS NOT NULL)
 BEGIN
  SELECT
   [EmployeeID],
   [LastName],
   [FirstName],
   [Title],
   [TitleOfCourtesy],
   [BirthDate],
   [HireDate],
   [Address],
   [City],
   [Region],
   [PostalCode],
   [Country],
   [HomePhone],
   [Extension],
   [Photo],
   [Notes],
   [ReportsTo],
   [PhotoPath],
   [Modified]
  FROM
   [dbo].[Employees]
  WHERE
   [EmployeeID] = @EmployeeID
 END
 ELSE
 BEGIN
  SELECT
   [EmployeeID],
   [LastName],
   [FirstName],
   [Title],
   [TitleOfCourtesy],
   [BirthDate],
   [HireDate],
   [Address],
   [City],
   [Region],
   [PostalCode],
   [Country],
   [HomePhone],
   [Extension],
   [Photo],
   [Notes],
   [ReportsTo],
   [PhotoPath],
   [Modified]
  FROM
   [dbo].[Employees]
 END

GO

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

------------------------------------------------------------------------------------------------------------------------
-- Date Created: Wednesday, September 28, 2005
-- Created By:   Generated by CodeSmith
------------------------------------------------------------------------------------------------------------------------

CREATE PROCEDURE dbo.InsertEmployees
 @LastName nvarchar(20),
 @FirstName nvarchar(10),
 @Title nvarchar(30),
 @TitleOfCourtesy nvarchar(25),
 @BirthDate datetime,
 @HireDate datetime,
 @Address nvarchar(60),
 @City nvarchar(15),
 @Region nvarchar(15),
 @PostalCode nvarchar(10),
 @Country nvarchar(15),
 @HomePhone nvarchar(24),
 @Extension nvarchar(4),
 @Photo image,
 @Notes ntext,
 @ReportsTo int,
 @PhotoPath nvarchar(255),
 @Modified datetime OUTPUT,
 @EmployeeID int OUTPUT
AS

SET @Modified=getdate()
INSERT INTO [dbo].[Employees] (
 [LastName],
 [FirstName],
 [Title],
 [TitleOfCourtesy],
 [BirthDate],
 [HireDate],
 [Address],
 [City],
 [Region],
 [PostalCode],
 [Country],
 [HomePhone],
 [Extension],
 [Photo],
 [Notes],
 [ReportsTo],
 [PhotoPath],
 [Modified]
) VALUES (
 @LastName,
 @FirstName,
 @Title,
 @TitleOfCourtesy,
 @BirthDate,
 @HireDate,
 @Address,
 @City,
 @Region,
 @PostalCode,
 @Country,
 @HomePhone,
 @Extension,
 @Photo,
 @Notes,
 @ReportsTo,
 @PhotoPath,
 @Modified
)
SET @EmployeeID = @@IDENTITY

 

GO

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS OFF
GO
------------------------------------------------------------------------------------------------------------------------
-- Date Created: Wednesday, September 28, 2005
-- Created By:   Generated by CodeSmith
------------------------------------------------------------------------------------------------------------------------

CREATE PROCEDURE dbo.UpdateEmployees
  @EmployeeID int,
  @LastName nvarchar(20),
  @FirstName nvarchar(10),
  @Title nvarchar(30),
  @TitleOfCourtesy nvarchar(25),
  @BirthDate datetime,
  @HireDate datetime,
  @Address nvarchar(60),
  @City nvarchar(15),
  @Region nvarchar(15),
  @PostalCode nvarchar(10),
  @Country nvarchar(15),
  @HomePhone nvarchar(24),
  @Extension nvarchar(4),
  @Photo image,
  @Notes ntext,
  @ReportsTo int,
  @PhotoPath nvarchar(255),
  @Modified datetime OUTPUT
AS
DECLARE @CurrentModified DateTime
 SET @CurrentModified = getdate()
UPDATE [dbo].[Employees] SET
 [LastName] = @LastName,[FirstName] = @FirstName,[Title] = @Title,[TitleOfCourtesy] = @TitleOfCourtesy,[BirthDate] = @BirthDate,[HireDate] = @HireDate,[Address] = @Address,[City] = @City,[Region] = @Region,[PostalCode] = @PostalCode,[Country] = @Country,[HomePhone] = @HomePhone,[Extension] = @Extension,[Photo] = @Photo,[Notes] = @Notes,[ReportsTo] = @ReportsTo,[PhotoPath] = @PhotoPath,[Modified] = @CurrentModified
WHERE
 [EmployeeID] = @EmployeeID
 AND [Modified] = @Modified

SET @Modified = @CurrentModified
GO

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


 



Community | Languages and Tools

Thursday, September 29, 2005 10:44:02 PM (GMT Daylight Time, UTC+01:00)
Comments [5]  | 

Smart Client Deployment with ClickOnce talks in St. Louis and KC

I gave a talk on ClickOnce in both St. Louis and Kansas City Monday and Tuesday evening this week and had a really good time. After the St. Louis talk I was able to go out for a beer with Bill Evjan, Scott Spradlin, and some of the other group members, which is always a great chance to network while I am there. KC was more of a quick strike since I had to fly out first thing in the morning to head to the MVP summit in Seattle.

The code samples and slides can be downloaded here.



.NET | ClickOnce | Community | Languages and Tools | Speaking | Travel

Thursday, September 29, 2005 10:42:26 PM (GMT Daylight Time, UTC+01:00)
Comments [2]  | 


 # Wednesday, September 14, 2005

System.Transactions and connection pooling

Update: I had put this post up yesterday and then accidentally deleted it while trying to do an update due to a technical inaccuracy. Sorry if you get a duplicate post, if so use this one. The technical inaccuracy had to do with the section describing when the transaction is promoted to the DTC.

---------------

One of the reviewers of my Data Binding in Windows Forms 2.0 book raised a question regarding System.Transactions and connection pooling that is important to understand.  I didn’t go into detail on this issue in the book (because it is not a data access book, it is a data binding book… you know completely different layers, hopefully separated by a business layer…).

 

The discussion centered around the following code snippet:

public void ExecuteTransaction()

{

   CustomersTableAdapter adapter = new CustomersTableAdapter();

   // Start the transaction

   using (TransactionScope scope = new TransactionScope())

   {

      CustomersDataSet.CustomersDataTable customers;

      customers = adapter.GetData();  // First query

      customers[0].Phone = "030-0074321";

      adapter.Update(customers);      // Second query

      scope.Complete();               // Commits the transaction

   }

}

 

The code above opens a transaction scope and performs two queries within that scope. The call to Complete on the scope votes to commit the transaction. If there is no ambient transaction when this call is executed, a new transaction will be created when the scope is constructed. If there is an ambient transaction, this scope will be enlisted in the ambient transaction, and will not be committed until its enclosing transaction is committed.

 

The misunderstanding was that the reviewer thought that in order to scope the transaction across two queries (GetData and Update on the table adapter), Microsoft had implemented it by keeping the connection open, which would be a bad thing from a connection pooling perspective.

 

<UpdatedSection> 

The truth is that transactions in System.Transactions have scope greater than a single connection. If the queries run against a single connection to a SQL Server 2005 database, then a lightweight transaction will scope the queries through that connection. If the queries run against more than one connection instance (as is likely with the code above or most multi-query scenarios) or any other resource manager other than 2005 at this point (i.e. SQL 2000, Oracle, MSMQ, etc.), then the transaction will auto-promote to a DTC transaction, which can obviously scope multiple connections.

 </UpdatedSection>

 

In the code above, the connection is opened and closed automatically by the data adapter that is encapsulated in the table adapter for each of the calls (GetData and Update) in the same way as in .NET 1.1, regardless of the target database. The close doesn’t really close the connection, it puts it back on the connection pool. The transaction scope is greater than each connection and can span both connections, <UpdatedSection> after promotion to the DTC</UpdatedSection>.

 

In case you want to see it in action, you can download a simple sample here that demonstrates this fact. This sample makes similar calls to the above, but adds a partial class extenstion and method to the table adapter allowing you to check the connection state in between calls:

namespace SystemTransactionsSample.CustomersDataSetTableAdapters

{

   public partial class CustomersTableAdapter

   {

      public bool IsConnectionOpen()

      {

         return Connection.State == System.Data.ConnectionState.Open;

      }

   }

}

 

If you insert a call to IsConnectionOpen on the adapter between GetData and Update, you will see that the connection is in fact in a closed state between calls, even though the transaction is alive and uncommitted.

 



.NET | Languages and Tools

Wednesday, September 14, 2005 5:53:15 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, August 30, 2005

Data Binding a ComboBox to a child collection

One of the most frequent questions I get regarding data binding is how to hook up a combo box with a data bound list of selections from a related table or collection, and have selections in that combo box set a corresponding value in the related collection. For example, in the following form, the main collection is the Products table from Northwind. The textboxes are displaying a couple of the columns from that table, and the combo box is displaying the supplier name from the related Suppliers table. Products contains a foreign key column with a SupplierID that makes the link.

Data bound form

The code required to hook all this up in .NET 2.0 is very simple, although maybe slightly difficult to discover on your own. The solution below binds the controls to two BindingSource components, which is the new way of doing data binding in .NET 2.0. The BindingSource component provides a layer of indirection between your bound controls and their data sources that makes synchronizing bound controls easier, allows you to switch out the data source without needing to re-initialize bindings, and exposes a number of useful events to monitor what is going on in bound data sources in your code.

Basically all you need to do is get your data and set that as the data source on the two binding sources. Then set up a normal ComboBox data binding on the ComboBox with the DataSource, DisplayMember, and ValueMember properties. You then add a simple binding to the control's DataBindings collection (an instance of a Binding object) that ties the SelectedValue property on the ComboBox to the corresponding foreign key property/column in the parent collection:

// Retrieve the data for products and suppliers into a data set or custom collections

// Set up the data bindings for the textboxes on the form to their binding source

// i.e. m_ProductNameTextBox.DataBindings.Add("Text", m_ProductsBindingSource, "ProductName", true);

// Set the BindingSource.DataSource property for the textboxes on the form

m_ProductsBindingSource.DataSource = m_Products; // some collection of products

// Set the binding properties for the combo box

m_SuppliersBindingSource.DataSource = m_Suppliers; // some collection of suppliers

m_SuppliersCombo.DataSource = m_SuppliersBindingSource;

m_SuppliersCombo.DisplayMember = "CompanyName";

m_SuppliersCombo.ValueMember = "SupplierID";

// Add a simple binding for the combo box SelectedValue property to the other collection

m_SuppliersCombo.DataBindings.Add("SelectedValue",m_ProductsBindingSource,"SupplierID");

The ComboBox databinding takes care of setting the SelectedValue property on the ComboBox whenever the current item in the parent collection changes.

The steps to regenerate the displayed sample in the Visual Studio 2005 designer are as follows:

  • Create a Database Data Source (typed data set) through the Data Sources window to Northwind with Products and Suppliers tables in it.
  • In the Data Sources window, change the control mapping for the Products table to Details (drop down the list of controls by selecting it and dropping it down)
  • Set the control mapping for the SupplierID column of Products to ComboBox
  • Set the control mapping of other columns you don’t want to display to None.
  • Drag and drop the Products table onto a form. A binding source, binding navigator, the textboxes and the combobox will be generated with their labels.
  • Select the ComboBox in the designer.
  • Go to the Properties grid and select the (DataBindings) property (Advanced) subproperty. Select the ellipses (…) to get the dialog up.
  • The Text property will have a Binding set up for it. Remove that by selecting the Binding drop down and selecting None at the top of the list.
  • Select the SelectedValue property in the Advanced Bindings window and select the productsBindingSource.SupplierID as the bound column. OK out of there.
  • Go back to the Data Sources window and drag the Suppliers table onto the ComboBox. This will hook up the DataSource, DisplayMember, and ValueMember properties.

Hope that is helpful to those groping around with similar data binding scenarios out there.



.NET | Data Binding | Languages and Tools

Tuesday, August 30, 2005 6:22:36 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Data Binding in Windows Forms 2.0 - Final Manuscript Done!

Phew! After a year and a half of trying to keep pace with the changing betas and writing the book on top of a full schedule of consulting, training, and speaking at conferences and user groups, I am finally done. I submitted the final manuscript to production on Friday. Now I just have to respond to any questions and reviews during the production phase, convert the code samples to VB for download, and I can call this one a wrap.

You can order the book here (available January 2006):

http://www.amazon.com/exec/obidos/ASIN/032126892X/qid=1124482085/sr=11-1/ref=sr_11_1/102-1031358-5664119

We will have a teaser chapter out at PDC that will also be available for download as a PDF containing part of the chapter on the DataGridView control. I'll put up a link to that as soon as it is available.

Now I am start devoting my attention to my next book, Smart Client Deployment with ClickOnce, also part of the Addison Wesley .NET Development series. I hope to knock this one out in the next 6 months, so it should hit the shelves mid 2006.



.NET | Languages and Tools | Publishing | Data Binding | ClickOnce

Tuesday, August 30, 2005 5:50:53 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, August 2, 2005

Advanced .NET Master Class Oct 17-21, Reston VA

I'll take the opportunity here for some shameless self-promotion...

If you are an intermediate to advanced developer who already has some .NET experience and are looking to take it to the next level, you might want to check out our Advanced .NET Master Class, which I will be teaching in Reston, VA from 17-21 Oct. This is a public offering of a high-demand course that we normally only offer onsite for larger development teams. You can find the full class description here. This will be a well-timed, comprehensive, in-depth coverage of developing enterprise applications in .NET 2.0. I cover a huge amount of material including advanced language features in C#, assemblies and versioning, serialization, multi-threading, transactions, security, Enterprise Services, and Remoting.

If you are interested, contact us through this link to obtain more information.



.NET | Architecture | Community | Languages and Tools | Speaking

Tuesday, August 2, 2005 12:34:46 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, July 29, 2005

Speaking and Drinking in Tampa last night

I had a great time speaking at the TampaBay .NET Users Group last night. We had a great turn out and it was a fun crowd. About 20 of us retired to a nearby bar afterwards for some suds and good conversation. Apparently they do that fairly regularly at their group. That is definitely the largest interactive mass of people I have encountered at a user group that goes out and really networks and has a good time together after the meeting on a regular basis.

Thanks for having me down guys and gals!!

The talk was on ASP.NET 2.0 Data Binding, and was a little rough since it was the first time I had given this talk. But hopefully people still got a lot out of it. I did all the demos on the fly, and as a result, a few of them didn't work out because I decided to take a few little side trips that I had not practiced, which is never a good idea on stage with new material.

If you are interested, here are the slides and outcome of the demos.



.NET | Community | Languages and Tools | Speaking | Travel

Friday, July 29, 2005 11:47:30 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, July 8, 2005

Smart Client Offline Data Caching and Synchronization Demos
Here are the demos from today's talk. Enjoy!

.NET | Architecture | Languages and Tools | Speaking

Friday, July 8, 2005 3:24:15 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

In Depth Windows Forms Demos

Here are the demos from my session today on In Depth Windows Forms. Thanks to the Windows Client team in Redmond for provided such great demo code and instructions that you can follow on your own.

Get them here.



.NET | Languages and Tools | Speaking

Friday, July 8, 2005 9:18:26 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, July 6, 2005

Data Binding Demos from TechEd Europe today
For those who want the demos from my session on data binding in Windows Forms 2.0 at TechEd Europe today, here they are.

.NET | Architecture | Languages and Tools | Speaking | Travel

Wednesday, July 6, 2005 3:59:59 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, July 5, 2005

Using User Settings in Partial Trust

In my previous post on ClickOnce custom install steps, I talked about how to read and write custom settings from Isolated Storage. One thing I purposely avoided mentioning there (because I needed to get confirmation on some facts from the product team at Microsoft) was the use of the new User scoped settings in .NET 2.0 and Visual Studio 2005.

If you are not already aware, the approach to config files has changed quite a bit in .NET 2.0. When you create a project in Visual Studio 2005, you can add custom settings through the project property pages (Settings tab), and those will be persisted in your config file and available to you at runtime. Additionally, strongly typed properties are added to a Settings class that is created by the designer so that you can access those settings programmatically with code like this:

string myCustomString = Properties.Settings.Default.MyCustomString;

The Settings class is declared in a child namespace of your project namespace called Properties, and the Settings class has a singleton property called Default that you use to get a reference to the one and only one instance of the Settings class for your app. From there, you just access the settings in your config file through named strongly typed properties.

That on its own would be a big win from a design time and compile time perspective, but the full story is even better. For one thing, you can designate whether settings are scoped to the application or to the user. If scoped to the application, then the settings go in your application configuation file as usual (<appname>.exe.config or web.config as appropriate). If scoped to the user, the settings go into a slighly obfuscated directory under the user's profile, under <username>\Local Settings\Application Data\.

The other thing about user settings is that all the properties for them that get exposed through the Settings class are both read and write. So you can set the properties, call Save on the settings class, and your changes will be written out to the user config file:

Properties.Settings.Default.MyCustomString = "SomeNewValue";

Properties.Settings.Default.Save();

So for the scenario I was describing in the previous post about writing out a flag to indicate when it is no longer the first time you application has run, a boolean user setting is cerrtainly a prime candidate for a place to put that. And if you read the docs for user settings, you will see that it says that you can write to user settings in partial trust, so it should be a winner for ClickOnce deployed apps as well. The reason I held off on mentioning it in the other post is a typical story:

User Settings do not work in partial trust in Beta 2.

If you try to write out user settings (call Save) in a partial trust environment in Beta 2, you will get a FileIOPermission security exception thrown. The thing I was waiting for confirmation on was that this will be fixed for RTM, and the answer was yes. So for production apps releasing after RTM, you can do all your ClickOnce custom settings through user settings, and not have to write explicitly to IsolatedStorage. There may still be some scenarios where you want more explicit control over the I/O process, in which case Isolated Storage is still your best option for a ClickOnce app to minimize your permission requirements.



.NET | Languages and Tools

Tuesday, July 5, 2005 10:04:14 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, July 4, 2005

How to handle prerequisites and custom install steps for a ClickOnce Deployed Application

UPDATE:  There was one little hitch with the code I presented earlier in this posting... it didn't work in partial trust because the BinaryFormatter and serialization require security permissions that are not granted in partial trust. At the end of the posting is the new code that does work fine in partial trust, but only works for built-in basic types in .NET (int, string, bool, etc.) because a custom XmlSerializableHashtable was required to get things working. The full code can be downloaded here. It is also available on the IDesign web site, download tab at http://www.idesign.net/. The code below has been updated to show the full source of the helper class and the XmlSerializableHashtable, which was adapted from the one in the Configuration Management Block. One of the other improvements that were made at my colleague Juval Lowy's prompting was to make the Read and Write methods generic so that they could read and write in a type safe way instead of using object parameters and return types, which was an excellent suggestion.

-----------------

 

These are some common questions I get about ClickOnce:

 

"My app depends on XXX, how can I ensure it is on the user’s machine before trying to launch my ClickOnce app?"

 

"I need to do XXX the first time the app is run, how can I do this from ClickOnce?"

 

Prerequisite Detection

The answer to the first question is twofold. First, there is the issue of detection. There is no general way to do prerequisite detection across the board. It is going to depend a lot on what those prerequisites are. In some cases, you may be able to use WMI, in others, File I/O to look for some known signature in an expected folder. In almost all of these approaches, you are going to need highly elevated permissions on the box, both from the perspective of the user that executes the application, and second from a Code Access Security (CAS) perspective.

 

Probably a better way is to have some startup code in your application that only runs once for a given version that attempts to use the APIs (directly or indirectly) of the prerequisites that you depend on. If that attempt fails, catch the exception and notify the user that they are lacking the respective prerequisite. If it is MDAC or SMO or something like that, try to use the calls that your app uses that calls through those layers (to do something trivial and non-destructive obviously). I’ll talk about strategy for managing one-time steps like this in your ClickOnce apps towards the end of this post.

 

Prerequisite Installation

The second part of the answer to the question on dependencies is to use the bootstrapper. This is a new feature in .NET 2.0 that is not technically part of ClickOnce, but ClickOnce capitalizes on it for getting prerequisites deployed. Using the bootstrapper, you can wrap up all the MSI installs that need to be run for prerequisites for your app into one setup.exe that an admin needs to run on the client box just once. It will run each of the prereq setup packages as needed, and then you should be good to go to run your ClickOnce app.

 

If your deployment environment is a controlled intranet environment, then managing this through group policy/SMS/basic client machine configuration control should be sufficient. You have an admin for your domain somewhere that has configuration control over the user’s desktops, get them to roll out the prereqs necessary to support your application. If your target audience is open internet users, then you will have to provide them a link to the bootstrapper setup.exe that they run first (and they will have to be an admin on the box to do so), and then they can run your ClickOnce app.

 

One-Time Setup Steps

The answer to the second question – how to do one-time actions for your ClickOnce app before it runs – is actually fairly simple to solve, even though ClickOnce provides no direct mechanisms for doing so. By design, ClickOnce does not allow you to configure or run any custom install steps as part of the ClickOnce deployment. The idea is that there should be no way the act of deploying a ClickOnce app to a client machine will corrupt other applications or other user data on that machine. If they opened the Pandora box of allowing custom install actions, there would be no way to guarantee that. However, once your app is on the machine and executing, it can do whatever it was designed to do, provided it has sufficient CAS permissions and that the user is authorized to access whatever resources they are trying to access.

 

For example, say that the first time you run your application, you need to prompt the user for the name of the database server and database name (obviously a power user requirement – something more simple would be just prompting them for their name and initials like Office apps do the first time they are run). Once you prompt the user for that information, you need to store it somewhere. You also have to have logic in your app to know to only prompt the user for that information the first time the app is run, so you need a flag somewhere to detect when that is the case.

 

Well, one of the simplest ways to do this is to use the data you are collecting for these situations as the flag themselves. If it is some other kind of one time action you need to run that doesn’t generate stored data, then you will need a separate flag that is easy to read and check at app startup. So all you need to do is have some internal startup code in your app that checks for the first time run flag, or checks for the presence of the needed data, and does appropriate prompting if not.

 

Once you have collected the data, you need to persist it for the next run, whether it is a simple first-time-run flag, or whether it is the database server and database name example mentioned above. You could just write it out to some file in your application directory, but that is going to require File I/O permission. You app will not have that permission by default in a ClickOnce deployed app on the internet or local intranet, unless you deploy it requesting elevated permissions. You should avoid asking for more permissions than you really need, and if this is the only File I/O your app does, then a better choice is to use Isolated Storage.

 

Reading and writing to Isolated Storage is permitted in both the Internet and Local Intranet CAS zones for AppDomain isolation, so you don’t need any elevated permissions to be able to read and write your config settings there. There is a new level of isolation in .NET 2.0, scoped to the application level (as opposed to the assembly and AppDomain levels present in earlier versions of .NET). Application scoped isolated storage settings will be accessible regardless of the version of your application when ClickOnce deployed, so you won’t lose these settings when the application is updated. However, if you want your app to check for pre-reqs each time the app is updated, maybe writing that flag to an appdomain scoped isolated storage is exactly what you want, because then the setting will be refreshed for each update.

 

Writing to isolated storage is fairly straightforward. You create an instance of an IsolatedStorageFile scoped to the appropriate isolation level through the exposed factory methods. You then create an IsolatedStorageFileStream, and from there it is just straight I/O against a stream, the same as you would do for a normal file in .NET.

 

I wrote a little helper class to make this as easy as possible to read and write settings from isolated storage, both in ClickOnce and non-ClickOnce applications. The IsoStoreSettingsHelper is shown below. To use this as is, you will need to set a reference to the System.Deployment.dll assembly in the framework, and will need the using statements shown below. The Read and Write methods take the name of file you want to use or create for storing settings within isolated storage. The Read method attempts to read a named setting from the specified file name in isolated storage. If the file does not exist, does not contain a hashtable, or the setting key specified cannot be found, then null will be returned. Otherwise the value from the hashtable will be returned. When write is called, it will add the specified key/value pair to the settings file, and will create it if it does not already exist.

 

The code dynamically selects either isolation by domain or isolation by application based on whether the application has been ClickOnce deployed. The reason for this is that application isolation depends on an identity for an application that is only present in a ClickOnce deployed app. So you cannot use application isolation unless you are running through ClickOnce. It checks for this with the IsNetworkDeployed property on the ApplicationDeployment class.

 

UPDATED CODE:

IsoStoreSettingsHelper class:

 

using System;

using System.IO;

using System.IO.IsolatedStorage;

using System.Deployment.Application;// Need to add reference to System.Deployment.dll framework assembly

 

namespace IDesign.Utilities

{

   public static class IsoStoreSettingsHelper

   {

      /// <summary>

      /// Reads a setting from isolated storage.

      /// Assumes isolation by domain for non-ClickOnce deployed apps.

      /// Assumes isolation by application for ClickOnce deployed apps.

      /// </summary>

      /// <param name="fileName">The name of the settings file to use.</param>

      /// <param name="key">The key name of the setting to look up.</param>

      /// <returns>The value stored in the file if found, the default value for the type otherwise.</returns>

      public static T Read<K,T>(string fileName,K key)

      {

         try

         {

            IsolatedStorageFile isoFile = OpenIsoStoreFile(fileName);

            string[] files = isoFile.GetFileNames(fileName);

            if(files.Length == 0 || files[0].Length == 0)

            {

               // File does not exist, return default

               return default(T);

            }

            // File exists, deserialize the settings

            using(Stream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, isoFile))

            {

               XmlSerializableHashtable settings = XmlSerializableHashtable.Load(stream);

               if(settings == null)

               {

                  return default(T);

               }

               return (T)settings[key];

            }

         }

         catch

         {}

         return default(T);

      }

 

      /// <summary>

      /// Write a setting to an isolated storage setting file.

      /// Assumes isolation by domain for non-ClickOnce deployed apps.

      /// Assumes isolation by application for ClickOnce deployed apps.

      /// </summary>

      /// <param name="fileName">The name of the settings file to use.</param>

      /// <param name="key">The key name of the setting to look up.</param>

      /// <param name="value">The value of the object to store.</param>

      public static void Write<K,T>(string fileName, K key, T value)

      {

         try

         {

            IsolatedStorageFile isoFile = OpenIsoStoreFile(fileName);

            XmlSerializableHashtable settings = null;

            // First try to read in existing settings is there are any

            using(Stream stream = new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, isoFile))

            {

               try

               {

                  settings = XmlSerializableHashtable.Load(stream);

               }

               catch

               {

               }

               if(settings == null)

               {

                  settings = new XmlSerializableHashtable(); // Create empty one for new settings

               }

            }

            //Add the new setting to the collection

            settings[key] = value;

            //Now write the collection back out

            using(Stream writeStream = new IsolatedStorageFileStream(fileName,FileMode.Create,isoFile))

            {

               settings.Save(writeStream);

            }

         }

         catch

         { }

      }

 

      static IsolatedStorageFile OpenIsoStoreFile(string fileName)

      {

         IsolatedStorageFile isoFile = null;

         if(ApplicationDeployment.IsNetworkDeployed)

         {

            isoFile = IsolatedStorageFile.GetUserStoreForApplication();

         }

         else

         {

            isoFile = IsolatedStorageFile.GetUserStoreForDomain();

         }

         return isoFile;

      }

   }

}

 

XmlSerializableHashtable class:

using System;

using System.Collections;

using System.Xml;

using System.Xml.Serialization;

using System.IO;

 

namespace IDesign.Utilities

{

   // Support storage of .NET primitives

    [XmlInclude( typeof(string) )]

    [XmlInclude( typeof(bool) )]

    [XmlInclude( typeof(short) )]

    [XmlInclude( typeof(int) )]

    [XmlInclude( typeof(long) )]

    [XmlInclude( typeof(float) )]

    [XmlInclude( typeof(double) )]

    [XmlInclude( typeof(DateTime) )]

    [XmlInclude( typeof(char) )]

    [XmlInclude( typeof(decimal) )]

    [XmlInclude( typeof(UInt16) )]

    [XmlInclude( typeof(UInt32) )]

    [XmlInclude( typeof(UInt64) )]

    [XmlInclude( typeof(Int64) )]

    public class XmlSerializableHashtable

    {

 

         #region Nested Class--Entry

 

         /// <summary>

        /// Represents an entry for the hashtable

         /// </summary>

         public class Entry

         {

             private object m_EntryKey;

             private object m_EntryValue;

 

             /// <summary>

             /// Default constructor, needed by serialization support

             /// </summary>

             public Entry(){}

 

             /// <summary>

             /// Construct the Entity specifying the key and the entry

             /// </summary>

             /// <param name="entryKey"></param>

             /// <param name="entryValue"></param>

             public Entry( object entryKey , object entryValue )

             {

                 m_EntryKey = entryKey;

                 m_EntryValue = entryValue;

             }

 

             /// <summary>

             /// Return the key

             /// </summary>

             [XmlElement("key")]

            public object EntryKey

             {

                 get{ return m_EntryKey; }

                 set{ m_EntryKey = value; }

             }

 

             /// <summary>

             /// Return the entry value

             /// </summary>

             [XmlElement("value")]

            public object EntryValue

             {

                 get{ return m_EntryValue; }

                 set{ m_EntryValue = value; }

             }

         }

 

         #endregion

 

         #region Declarations

            

         private Hashtable m_HashTable;

 

         #endregion

 

         #region Constructors

 

         /// <summary>

         /// Default constructor

         /// </summary>

         public XmlSerializableHashtable()

         {

             m_HashTable = new Hashtable();

         }

 

        

         /// <summary>

         /// Creates a serializable hashtable using a hashtable

         /// </summary>

         /// <param name="ht"></param>

         public XmlSerializableHashtable( Hashtable existingHashTable )

         {

         m_HashTable = existingHashTable;

         }

 

        

         #endregion

 

 

         #region Public Methods & Properties

 

      /// <summary>

      /// Indexer to access the underlying Hashtable

      /// </summary>

      /// <param name="key">The key for which you want to retrieve the value</param>

      /// <returns></returns>

      [XmlIgnore]

      public object this[object key]

      {

         get

         {

            lock (m_HashTable.SyncRoot)

            {

               return m_HashTable[key];

            }

         }

         set

         {

            lock (m_HashTable.SyncRoot)

            {

               m_HashTable[key] = value;

            }

         }

      }

 

      /// <summary>

      /// Save the hashtable to an output stream

      /// </summary>

      /// <param name="outputStream">The stream to write to</param>

      public void Save(Stream outputStream)

      {

         XmlSerializer serializer = new XmlSerializer(typeof(XmlSerializableHashtable));

         serializer.Serialize(outputStream,this);

      }

 

      /// <summary>

      /// Load a hashtable from an input stream

      /// </summary>

      /// <param name="inputStream">The stream from which to load</param>

      /// <returns>A new instance of an XmlSerializableHashtable</returns>

      public static XmlSerializableHashtable Load(Stream inputStream)

      {

         XmlSerializer serializer = new XmlSerializer(typeof(XmlSerializableHashtable));

         return serializer.Deserialize(inputStream) as XmlSerializableHashtable;

      }

     

      /// <summary>

         /// Returns the contained hashtable

         /// </summary>

         [XmlIgnore]

         public Hashtable InnerHashtable

         {

             get{ return m_HashTable; }

         }

 

         /// <summary>

         /// Used to serilalize the contents of the hashtable

         /// </summary>

         public Entry[] Entries

         {

             get

             {

            lock (m_HashTable.SyncRoot)

            {

               Entry[] entries = new Entry[m_HashTable.Count];

               int index = 0;

               foreach (DictionaryEntry entry in m_HashTable)

               {

                  entries[index] = new Entry(entry.Key,entry.Value);

                  index++;

               }

               return entries;

            }

             }

 

             set

             {

                 lock( m_HashTable.SyncRoot )

                 {

                      m_HashTable.Clear();

                      foreach( Entry item in value )

                      {

                          m_HashTable.Add    (item.EntryKey,item.EntryValue);

                      }

                 }

             }

         }

        

         #endregion

    }

}

 

 

 



.NET | Languages and Tools

Monday, July 4, 2005 10:49:38 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, June 29, 2005

ClickOnce certificates in a nutshell

I have gotten a lot of questions surrounding the use of certificates in ClickOnce. Here are the key facts to understand:

  • You must sign your ClickOnce manifests with an Authenticode certificate. VS 2005 will do this for you when you publish an application.
  • Authenticode certificates are not the same thing as an SSL certificate or an X509 client certificate used for authentication purposes, even though they are all based on the same technology.
  • You can generate your own certificate using Visual Studio, or the makecert command line utility. In this case, you are both the publisher represented by the certificate and the certificate issuing authority. You will sometimes see this referred to as a self-signed certificate.
  • A third party issued certificate (i.e. Verisign, Thawte) is the preferred approach. These companies are already configured in Windows as trusted root certificate authorities (CA), and because they are third party verified, there is an additional level of implied trust associated with them.
  • If you are part of a large enterprise domain and you have a domain CA, that CA can issue you a publisher cert for your domain that you can use, and your publisher certificate can be pushed out to client machines through group policy or SMS.
  • If user prompting is acceptable for elevating privileges (based on the permissions requested by the application in its manifest and the permissions that would be granted by code access security based on the launch URL), then there is no need to install any certificates on the client side.
  • If you want to avoid user prompting, you need to install your publisher certificate in the Trusted Publishers store on the client machine.
  • At runtime, certificate checks are only done against the local certificate stores on the client machine. Specifically, the certificate used to sign the manifests is checked for in the Trusted Publishers store, and the issuer of that certificate is checked for in the Trusted Root Certificate Authorities store.

If you want more information on configuring certificates and how they work at runtime, you should check out my article on MSDN Online:

http://www.msdn.microsoft.com/library/en-us/dnwinforms/html/clickoncetrustpub.asp

 



.NET | Architecture | Languages and Tools

Wednesday, June 29, 2005 12:54:46 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, June 22, 2005

Interview with Roy Osherove
Roy and I had a great long interview/discussion on a myriad of .NET topics back a couple of months, and he has it all edited and posted now. You can find it here.

.NET | Architecture | Community | Languages and Tools | Speaking

Wednesday, June 22, 2005 7:48:04 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Extending ASP.NET Slides and Demos from DevTeach Yesterday

I gave my session on extending ASP.NET with custom handlers and modules at DevTeach in Montreal yesterday. If you attended or want the slides and demos, here you go:

Slides

Demos



.NET | Languages and Tools | Speaking

Wednesday, June 22, 2005 7:45:53 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, June 19, 2005

Slides and demos from DevTeach today

I'm speaking this week at DevTeach, a nice little conference in Montreal Canada. Today I presented three sessions, two on ClickOnce and one on Data Binding in Windows Forms 2.0.

Here are the slides and demos:

ClickOnce:    Intro Slides   Security Slides   Demos

Data binding: Slides   Demos



.NET | Languages and Tools | Travel

Sunday, June 19, 2005 11:17:20 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, June 16, 2005

ClickOnce On-Demand Update Bug in Beta 2

In case you stumble and fall over this like I did, there is a bug in Beta 2 for configuring ClickOnce on-demand updates through the API. Normally if you wanted to support on-demand updates in a ClickOnce application, you would set it to not check for updates through the Updates settings in the Publish category of project properties in a Windows Forms project. You would then write code like the following in your application to support an on-demand update check (either programmatically or based on user request):

using System.Deployment.Application;

public partial class Form1 : Form

{

      private void OnDemandUpdate(object sender, EventArgs e)

     {

      if (!ApplicationDeployment.IsNetworkDeployed)

      {

         MessageBox.Show("This application deployment does not support network updates.");

          return;

      }

      ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;

       Cursor currCursor = this.Cursor;

      this.Cursor = Cursors.WaitCursor;

      if (deployment.CheckForUpdate())

      {

         deployment.Update();

         this.Cursor = currCursor;

         DialogResult result = MessageBox.Show("Update Complete. Restart?", "ClickOnce On-Demand Update",
            
MessageBoxButtons.YesNo);

         if (result == DialogResult.Yes)

        {

            Application.Restart();

         }

      }

      else

      {

         MessageBox.Show("No updates available");

      }

      this.Cursor = currCursor;

   }

However, if you did this in Beta 2, you get an exception when this code runs with an IllegalOperationException saying this application cannot be updated programmatically. The workaround in Beta 2 is to tell the app to check for updates, set it to do so after the application starts, and set the subscription period (how often to check for updates) to a long value, such as 50 weeks. Be careful, because another bug is that VS will let you set an illegally large value for this subsciption, such as 512 weeks. If you do so though, you will get a deployment error because ClickOnce will see a schema violation, and if you try to edit the manifest with MaGe, it will crash with an unhandled exception. This should all be fixed by RTM, but are things to be aware of if you are playing with ClickOnce now or especially if you will be going to production with an application that uses this capability.

 

Saurabh Pant has a good post summarizing the specific settings that go in your manifest for this here.



.NET | Languages and Tools

Thursday, June 16, 2005 3:09:21 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Smart Client Offline Data Caching and Synchronization Demos

Here are the demos I gave in my TechEd session on Friday of last week. Sorry it took me a bit to get them posted. Call it post-conference-traumatic-stress-letdown-syndrome that made me go stupid.

Smart Client Offline Demos



.NET | Architecture | Languages and Tools | Speaking

Thursday, June 16, 2005 2:03:39 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Get a FREE copy of VS 2005 and SQL 2005 at DevConnections in Vegas

This is pretty cool. Hopefully by now you have heard that Microsoft officially announced the release date for Visual Studio 2005 and SQL Server 2005 as 7 November. What you may not have noticed is that is the opening day of the DevConnections conference in Vegas. Well, if you were not sure whether you should come to this outstanding conference before, maybe this will change your mind: you will get a free fully licensed copy of Visual Studio 2005 and of SQL Server 2005. The specific versions they are going to give out has not yet been determined, but hopefully they will be generous and go with Pro/Standard at least. They will also have a live broadcast of the Microsoft launch event in San Francisco, at which either Bill Gates or Steve Balmer will be speaking.

And if you happen to come to the show, come check out the talks I'll be giving, which include:

- Connect Smart Client Applications with Indigo

- Build Event Driven Applications with Indigo

- Secure Smart Client ClickOnce Deployments



.NET | Languages and Tools | Speaking

Thursday, June 16, 2005 1:57:55 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, June 8, 2005

Me and My, This and That

VB programmers have a pretty cool feature to wave in the faces of C# programmers in 2005 with the My feature... or do they? If you are not familiar with the My feature, it is a new keyword in VB2005 that you can type, and when you hit the . (dot) key, you will have instant access to a ton of common things such as the file system, user identity, network, and so on through some easy to use properties.

So VB has Me and My, why shouldn't C# have this and That? My colleague Juval has implemented a That class that exposes all the capabilities of My from VB to C# developers. It uses the same syntax and approach as My, just type That. and navigate through the object heirarchy to find the features that you want.

That in action

You can find the code for That on our downloads page at IDesign: http://www.idesign.net. Look for the link on the downloads page to "My for C# 2.0", or you can grab it here.

All My (and That) do is give you shortcut access to the most common features that people code against. Ultimately, you can achieve the same thing by finding the appropriate class in the .NET framework and invoking its functionality. But My (and now That) make it a lot quicker and easier to code up common scenarios.

In case you are a hard core C# guy who thinks this is just a joke and are thinking that there is no point, consider if you find some VB 2005 code in a sample that does what you want, but they are making extensive use of the My feature. How do you port that code to C#? Without the That class, you will have to rewrite anything that is using My. With the That class, you can just migrate it directly with little to no syntax conversion. The same would be true if you were going to migrate a complex VB 2005 app to C#.

Obviously since That is kind of a play on words, and we provide you the source code, you could change That to My and have the same name for the class as in VB. But That kind of has a nice ring to it. :)

Hats off to Juval for throwing this together in the wee hours



.NET | Languages and Tools

Wednesday, June 8, 2005 11:18:08 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, June 5, 2005

Back in Conference Land at TechEd

I just got back from Holland Thursday after speaking at SDC there, and now I am in Orlando to speak at TechEd. These things are nothing but fun, but man, the travel can get crazy.

I had a great time last night joining in with the crowd at the Party with Palermo, which evolved from a loosely organized geek dinner into a great gathering of speakers, RDs, MVPs, and attendees in the Peabody hotel restaurant and bar. Today there are a collection of overlapping events that I plan to try to attend portions of, including some MVP events, the INETA summit, and some of the pre-con sessions.

The rest of the week is already pretty packed. My breakout session is not until Friday, but I have a bunch of other things I am participating in / presenting as well:

Tuesday 7 Jun:

3:15-6:15 PM- proctoring Juval Lowy's Instructor Led Lab (ILL) on Generics (DEV20/DEV20R)

9:00 - 10:00 PM - Preparing for Indigo Birds of a Feather (BoF) given by Juval

Wednesday 8 June:

8:30 AM-11:30 AM- proctoring Michele Leroux Bustamante's ILL on Iterators (DEV23/DEV23R)

7:00-11:00 PM Influencer Party

9:00-10:00PM Leading BoF session on Smart Client Deployment (BOF051)

Thursday 9 June:

3:15 - 6:15 PM - Giving System.Transactions ILL (DEV 22/22R)

Friday 10 June:

10:15 AM -12:00 PM - Answering Q&A questions through LiveMeeting for Juval Lowy's Simulcast session Being More Productive with the .NET Framework (DEV325)

1:00 - 2:15 PM - Presenting CLI440 Smart Client Offline Data Caching and Synchronization

 

Those are just the items that warrant an unchallenged block on my calendar. There are a ton of other events mixed in there as well to keep the week packed. I also need to get some more work done on my book this week getting the second half of the book up to date with Beta 2 and ready for Tech review, and also want to try to blog a few technical posts about stuff I am working on. Hmm, when is thattime expansion device going to be on the market??



.NET | Architecture | Community | Languages and Tools | Speaking | Travel

Sunday, June 5, 2005 1:23:24 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, June 2, 2005

Northwind No Mas? Not so fast

UPDATE: I just realized the link that I refer to is not in here. Here it is:

http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&displaylang=en

I was informed by my friends Richard Campbell and Steve Forte the other day in Holland at SDC that Northwind will not ship with SQL Server 2005. I was a little bummed, because I have used it for a lot of the samples in my book because I was told by certain contacts at Microsoft that it would ship with 2005, and I wanted to maintain backwards compatibility with folks who have not migrated to SQL Server 2005 yet (I think Whidbey adoption will be much faster in development shops than SQL Server 2005 for licensing reasons).

Well, just in case this is a surprise to you to, and you want to be able to add Northwind to SQL Server 2005 after you install it, here is a link to the sample DBs (Northwind and Pubs) as scripts that should work fine with 2005 as well.



.NET | Languages and Tools

Thursday, June 2, 2005 10:09:22 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, May 31, 2005

Slides and Demos from SDC 2005 Netherlands

I gave 4 sessions at the Software Developers Conference 2005 in Arnhem, Netherlands yesterday and today. Great little conference and a lot of fun to get to speak at.

Here are the slides and demos from the sessions:

Smart Client Offline Data Caching and Synchronization:  slides   demos

Extending ASP.NET with Custom Handlers and Modules:  slides   demos

Smart Client Communications with the Middle Tier: slides   demos

Tackle Complex Data Binding with Windows Forms 2.0:  slides   demos



.NET | Architecture | Languages and Tools | Speaking | Travel

Tuesday, May 31, 2005 11:49:47 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, May 20, 2005

I'm in Visual Studio - I'm Somebody now

This is kind of cool. Fire up Visual Studio today, and my article on Configuring ClickOnce Trusted Publishers is the third item in the list of MSDN resources on the start page. I've arrived in life. I can die happy now. :)

http://msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnwinforms/html/clickoncetrustpub.asp

 



.NET | Languages and Tools

Friday, May 20, 2005 6:11:07 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, May 13, 2005

David Chappell on Indigo
I attended a developer dinner put on by the local Microsoft office (G. Andrew Duthie specifically) last night that was truly excellent. David Chappell was the speaker and I enjoyed his talk immensely, as I do all his talks. The talk was a basic intro to Indigo, and even though I was up to speed already on most of the content, it is always entertaining and educational to watch a masterful speaker spin his web. He did a great job explaining some of the more complex aspects of Indigo in ways that anyone could get. He has been doing a road show with this talk across the country and will be going to Atlanta next, so if you have a chance to see it there, you should.

.NET | Community | Languages and Tools

Friday, May 13, 2005 11:33:14 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, May 8, 2005

Slides and demos from Mid-Atlantic Code Camp

For those who attended, I hope you had a good time! Andrew did a great job putting the code camp together, and it seemed to go well all day.

Here are the slides and demos I gave:

Smart Client Offline Data Caching and Synchronization: Slides   Demos

Secure Smart Client Deployment with ClickOnce:  Slides   Demos

Complex Data Binding in Windows Forms 2.0: Slides    Demos



.NET | Community | Languages and Tools | Speaking

Sunday, May 8, 2005 7:17:50 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, May 1, 2005

Configuring ClickOnce Trusted Publishers Article up

My article on Configuring ClickOnce Trusted Publishers went live this week on the Smart Client Developer Center on MSDN Online:

http://www.msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnwinforms/html/clickoncetrustpub.asp

 



.NET | Architecture | Languages and Tools

Sunday, May 1, 2005 9:00:50 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, April 27, 2005

Fun time at Tulsa.NET UG

I gave a talk at Tulsa .NET Users Group on Monday 25 Apr on Windows Forms 2.0 Data Bining and had a great time. The group is large and growing, standing room only with over 40 folks. The group is well led by Caleb Jenkins, he is a great MC and keeps the group very dynamic and motivated.

Here are the slides and demos.



.NET | Community | Languages and Tools | Speaking | Travel

Wednesday, April 27, 2005 4:19:18 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Philly Code Camp wrap up

It took me a few days to get to it, but here are the slides and demos from Sunday's talks at Philly Code Camp:

Smart Client Offline Data Caching and Synchronization: Slides   Demos

Secure Smart Client Deployment with ClickOnce:  Slides   Demos



.NET | Community | Languages and Tools | Speaking

Wednesday, April 27, 2005 4:13:03 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, April 24, 2005

3 Down, 2 to go

I'm speaking at the Philly Code Camp this weekend, and gave three talks today, and two tomorrow.

As promised to the attendees, here are the slides and demos from today for:

DataGridView Control: Slides   Demos

Complex Data Binding in Windows Forms 2.0: Slides    Demos

Extending ASP.NET with Custom Handlers and Modules: Slides   Demos

 



.NET | Community | Languages and Tools | Speaking

Sunday, April 24, 2005 1:40:23 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, April 18, 2005

Get yer Red Hot Beta 2 here...

Whidbey Beta 2 is up on subscriber downloads! Start yer engines!



.NET | Languages and Tools

Monday, April 18, 2005 3:53:37 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, April 13, 2005

Extending ASP.NET talk slides and demos from Texas

I had a great time speaking at the Austin .NET Users Group and Texas A&M .NET User Group last night and today, giving my talk on Extending ASP.NET with Custom Handlers and Modules

For those that attended, or others that are interested, here are the slides and demos that I gave. If you have grabbed earlier versions of these from when I have given the talk in the past, you may want to grab the demos again since I added a custom handler demo that does watermarking of images that I wrote on the plane ride to Texas monday.



.NET | Community | Languages and Tools | Speaking | Travel

Wednesday, April 13, 2005 1:11:52 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, April 11, 2005

Speaking at Austin .NET and Texas A&M .NET User Groups

If you are a Texan and live in the Austin or College Station area, come on out to the Austin .NET Users Group on 11 April or the Texas A&M .NET Users Group on 12 April to see my Extending ASP.NET with Custom HTTP Handlers and Modules talk. I will be covering the ASP.NET processing pipeline, how/why to create custom handlers as endpoints for ASP.NET requests, and how to create custom modules to perform per-request processing across your application.

Hopefully them Aggies won't throw a lynching party afterwards since I am a boat school graduate...



.NET | Languages and Tools | Speaking | Travel

Monday, April 11, 2005 2:35:13 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, April 5, 2005

Deploying and Launching non-Whidbey Apps with ClickOnce

A common question when I give talks on ClickOnce is whether you can deploy legacy applications with ClickOnce. The answer depends on how legacy you mean.

If you have an existing managed (.NET) application that will run fine against the .NET framework version 2.0, then you can deploy it using ClickOnce, without needing to rebuild the application using Visual Studio 2005. To do so, you will have to create the directory structure in which to place your application on the deployment server, and can then use the MAGE tool to author and sign application and deployment manifests for the application.

The thing to realize is that when your application is deployed this way, it will be launched inside the host process created by ClickOnce (currently named AppLaunch.exe), which loads the .NET rumtime version 2.0 to host the application. Based on the way .NET runtime and framework unification work, that also means that the version of the .NET Framework class libraries that you will be running against will be the 2.0 versions. If your legacy .NET application uses any features in the framework that have breaking changes between 2.0 and past versions, you might encounter errors when your app is running through ClickOnce that you never experienced before. You also have to realize that the application might be running in partial trust depending on how you configure the security permissions in your application manifest, so that could prevent certain operations in your application that used to work fine when not executed through ClickOnce.

If you app is REALLY legacy (i.e. VB6, MFC, ATL, etc.), as in an unmanaged code executable, then no, you cannot deploy it as an executable through ClickOnce. The MAGE tool takes a look at the executable that you select as the entry point for the application, and won't let you specify an unmanaged executable as the entry point. Without an entry point, you don't have a valid launchable ClickOnce application.

Are there workarounds? Of course!! There are always workarounds. If the unmanaged code you are trying to deploy is in the form of a library, there is nothing stopping you from consuming unmanaged code from a ClickOnce application, provided that the ClickOnce application is granted either full trust, or at least the unmanaged code execution security permission through the application trust for the ClickOnce application deployment. If you really want to launch an unmanaged executable through ClickOnce, you could write a very simple shim managed application with .NET that just does a Process.Start. Again, you will need unmanaged code permission for that to work.

A simple example is available here.



.NET | Languages and Tools

Tuesday, April 5, 2005 1:39:15 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, March 27, 2005

Advanced Fundamentals Tutorial demos and slides

Michele Leroux Bustamante and I presented a full day tutorial on advanced fundamentals of the .NET Framework on Thursday. Here are the slides and demo code.

Michele has posted her demos here.



.NET | Languages and Tools | Speaking

Sunday, March 27, 2005 2:58:43 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, March 23, 2005

Secure Smart Client Deployments with ClickOnce slides and demos

Here are my slides and demos from today's session on ClickOnce security. Within the next couple days I'll write some posts to address the scenarios discussed. If anyone had any complex questions that I deferred, ping me so that I can get them answered here.

Slides    Demos



.NET | Languages and Tools | Speaking

Wednesday, March 23, 2005 7:24:15 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Tuesday, March 22, 2005

Smart Client slides and demos from VS Connections sessions today

If you attended my sessions today at Visual Studio Connections in Orlando, thanks! It was a lot of fun.

 

Here are links to the slides and demos for each session:

Smart Client Communications with the middle tier: Slides     Demos

Smart Client Offline Data Caching and Synchronization: Slides      Demos

Enjoy!



.NET | Architecture | Languages and Tools | Speaking

Tuesday, March 22, 2005 11:59:32 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Sunday, March 20, 2005

Upcoming speaking schedule - VSConnections, TechEd US, DevTeach, SDC Netherlands and more

I'm doing a lot of talks at various conferences, user groups, and code camps over the next few months, mostly on smart client topics. Here is the line up:

Visual Studio Connections - 20-24 March - Orlando, FL:
http://www.vsconnections.com
Smart Client Offline Data Caching and Synchronization
Smart Client Communications with the Middle Tier
Secure Smart Client Deployment with ClickOnce
Advanced .NET Fundamentals Full Day Tutorial

Philly .NET Code Camp - 23-24 April - Philidelphia, PA
http://www.phillydotnet.org/Default.aspx?alias=www.phillydotnet.org/codecamp
Smart Client Offline Data Caching and Synchronization
Secure Smart Client Deployments with ClickOnce
Tackle Complex Data Binding with Windows Forms 2.0
Present Rich Data Interfaces with the DataGridView Control

Tulsa .NET Users Group - 25 April - Tulsa OK
http://www.tulsadnug.org/DesktopDefault.aspx
Tackle Complex Data Binding in Windows Forms 2.0

Mid-Atlantic MSDN Code Camp - 7 May - Reston VA
http://blogs.msdn.com/gduthie/articles/383561.aspx
Secure Smart Client Deployment with ClickOnce
Smart Client Offline Data Caching and Synchronization
Microsoft Application Blocks Chalk Talk

Software Developers Conference - 30-31 May - Arnhem Netherlands
http://www.sdc.nl/default.asp@a1pid=12338pdwl&a1sid=29101225200420.htm
Smart Client Offline Data Caching and Synchronization
Smart Client Communications with the Middle Tier
Tackle Complex Data Binding with Windows Forms 2.0
Extending ASP.NET with Custom Handlers and Modules

Microsoft TechEd - 5-10 June - Orlando, FL
http://www.microsoft.com/teched
Smart Client Offline Data Caching and Synchronization

DevTeach - 19-21 June - Montreal Canada
http://www.devteach.com
Secure Smart Client Deployments with ClickOnce
Tackle Complex Data Binding in Windows Forms 2.0
Extending ASP.NET with Custom Handlers and Modules


 



.NET | Architecture | Languages and Tools | Speaking | Travel

Sunday, March 20, 2005 8:38:06 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Friday, March 18, 2005

Visual Studio Extensibility

Last night I gave a talk on Visual Studio Extensibility to the BaltoMSDN User Group in Hunt Valley Maryland. Great group, had a lot of fun. If you attended or would like to check out the slides and demos, here is a link:

http://www.softinsight.com/downloads/VisualStudioExtensibility.zip


Just to actually put a little technical content on my blog for a change, I thought I would summarize a few key points from the talk.

Extensibility Options:
You have several options for adding functionality to Visual Studio. The first and simplest are Macros. Visual Studio Macros are code that you can either generate with the Macro recorder (similar to recording macros in Office applications) or write yourself through the Macros IDE, a scaled down version of Visual Studio for macro development that you access through the Tools > Macros menu. Macros are a good way to automate simple repetitive tasks to save yourself keystrokes and mouse clicks that you do over and over for a given development task.

The next step up the pyramid are Visual Studio Add-ins, which were the focus of my talk. Add-ins allow you to write .NET components that plug into Visual Studio and can run in the background and handle events fired by VS as the developer interacts with it, and/or invoke custom code based on user keystrokes or command bar/menu button clicks. You can add custom UIs to Visual studio as dialogs, docking windows, or options panes. There are a bunch of good examples available from MSDN at:

http://www.microsoft.com/downloads/details.aspx?FamilyId=3FF9C915-30E5-430E-95B3-621DCCD25150&displaylang=en


To get really rich functionality like you may have experienced from retail developer tools that integrate into Visual Studio, you will need to tap into the Visual Studio Integration Partner (VSIP) SDK. You can download and use the SDK for free, but if you ship any products to customers that you developed with VSIP, licensing fees and restrictions can apply.

I was just made aware of another option that I have not yet explored in depth, but that looks very promising and intriguing. Developer Express, who produce CodeRush and soon Refactor! for Visual Studio .NET, have packaged their core framework for developing add-ins as a reusable class library that you can use to develop extensions to Visual Studio. Basically they hide all the arcane details of the VS object model and the COM interop layers you have to go through for programming straight add-ins and VSIP code, and instead give you a cleaner, managed object model to program against. It is called DXCore and you can get it here:

http://www.devexpress.com/Downloads/NET/DXCore/

I am a huge and vocal fan of CodeRush and now Refactor!, which not only save me a lot of time writing code, they make great motivational demos of the kinds of things you can achieve with extensibility in VS.NET. The fact that DevExpress has made the engine that they build these tools on for other to use is just another great example of the .NET community and I thank them for doing so. I'm looking forward to playing with these capabilities.

Add-in Gotchas:
Some things to be aware of when building Add-ins (not using DXCore)...
- When you create an Add-in project through the wizard, make sure you compile right away before doing anything. This is because the project wizard adds the registry settings to try and load your Add-in the next time VS starts up. If you don't build your project, those reg keys are pointing to a non-existent DLL, and you will get an error message that if you say Yes to, will kill all the reg settings you need to build/debug your Add-in. You can get them back by building and running the setup project that is created by the wizard, but it is a better practice to just do a quick build to get something there for VS to refer to after completing the wizard.
- If you move your project to another machine, those reg keys will not be there to allow you to debug the add-in. The easiest way to get them in place is to build the Add-in project, build the setup project that is part of the solution, run the install, and then rebuild the Add-in project. Running the install will install a copy of the original DLL to the path you specify (typically under Program Files), will reg the DLL for COM interop, and will create the necessary reg settings. Rebuilding the Add-in project after that re-does the COM interop registration, pointing the CLSID in the reg back to your debug version of the DLL, allowing you to proceed with further development and debug.
- When you create an Add-in project it sets up the debugger to launch another instance of Visual Studio in the debugger so that you can try out your add in and hit breakpoints and do debugging in the original instance you ran the debug session from. If you are working out bugs and your add-in is failing to catch all exceptions or is not unsubscribing from events, you can get some weird behaviors because your object may remain in memory in the live VS instance. If you get anything unexpected, shut down all instances of VS and re-open your Add-in solution to make sure all objects get killed and you are working with an uncorrupted instance of VS.
- The code injected by the project wizard when you say you want a Tools menu item only creates that item one time, the first time your add-in is loaded. If the tools menu item is removed or exceptions get thrown in loading your add-in, you will never get your tools menu item loaded. This is because the code that creates in the OnConnection method is contained in a conditional block that checks for the enumerated value ext_ConnectMode.ext_cm_UISetup. If you want to make sure your tools menu item is recreated if it fails the first time, change this to be an || (Or) of the values ext_cm_Startup and ext_cm_AfterStartup. The downside of doing this is that there will be a minor perf hit in loading your add in because an exception will be thrown and caught when it tries to create the command if it already exists, so you may want to revert to the original check for production. But in development environments this will ensure your command gets created and is present repeatably in the face of errors and weird development startup paths.
- The objects and collections in the automation object model are COM components that you are accessing through interop. In many cases to get to the underlying object and get back a valid .NET reference, you have to use the .Object property for objects and the .Item property to access items in a collection. For example, there is an ActiveWindow and ActiveDocument property on the DTE root object of the model that let you get quickly to these items in the environment. However, to get a Window reference or a Document reference variable back from these (respectively), you will need to access DTE.ActiveWindow.Object, not just DTE.ActiveWindow. Likewise, to get into a collection, you will need to index into Item with a 1-based index, such as DTE.Solution.Projects.Item(1).Object to get to the Project object for the first project in the current solution.



.NET | Languages and Tools | Speaking

Friday, March 18, 2005 1:21:56 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, February 7, 2005

Testing ClickOnce Deployments

I had a question from a reader about testing ClickOnce deployments, and I thought I would pass my response along to anyone who is interested.

When you deploy a ClickOnce application, there are two manifests published with the application files to the deployment server: the deployment manifest (<appname>.application in Beta 1) and the application manifest (<appname>.exe.manifest in Beta 1). Bit of a confusing file extension choice if you ask me, but...

The deployment manifest includes information describing the deployment itself, including publisher information and a publish version that should be incremented each time you deploy a new set of files. The application manifest contains information that describes the application as a whole, including the collection of files that compose the application, and the permissions that the application requires.

When the application gets deployed to a client machine, a number of things are created at deployment. If the application publish settings are for it to only be available online, then the application files get cached under some obfuscated directories under the users profile \Documents and Settings\<username>\Local Settings\Apps. Additionally, an Application Trust will be created as part of the User Code Access Security policy for that version of the app. Finally, if the application puslishing properties are set so that application is available offline as well as online, then a Start menu shortcut and an Add/Remove Programs item is added.

The question had to do with had to do with problems they were encountering in repeatedly deploying an app to a client machine for testing. The deploy and launch mechanisms for ClickOnce are designed around the concept that the publish version should be incremented to indicate to a client machine that there is a new version to download. Although it might seem that you could just go delete the files from under the user's cache and redeploy to the same machine, you would also need to make sure all the other stuff mentioned above is also cleaned up.

There are two correct solutions to the problem of repeatedly deploying the same application to the same client machine for testing purposes.

1) Increment the publish version in the deployment manifest for each attempt. This can be done with the mage.exe tool found in the SDK bin folder. This will result in a new clean deployment to the machine each time.

2) Use a virtual machine (VMware is my preference, but VPC is fine too) in snapshot mode, where shutting down the virtual machine discards any changes made in the VM since you ran it. Now you can revert to the snapshot with a clean machine for each test.

If you test be manually deleting the files and artifacts from the user's machine, you are not testing the way ClickOnce was designed to be and should be used. In other words, you are not testing well.



.NET | Community | Languages and Tools

Monday, February 7, 2005 12:51:20 PM (GMT Standard Time, UTC+00:00)
Comments [2]  | 


 # Monday, January 10, 2005

Use BindingList for data bound collections

I finished up another chapter on my book last night. This one was on creating data bound custom business objects and collections. I won't try to reiterate the entire chapter here, but I will pass along one of the key take-aways: use BindingList<T> for custom business object collections if you want to provide rich data binding capabilities in Windows Forms 2.0.

The BindingList<T> generic type is defined in the System.ComponentModel.Collections.Generics namespace in Beta 1, but is getting refactored into System.ComponentModel in Beta 2. Basically this type allows you to create strongly typed collections that implement IBindingList (partially), IList, ICollection, and IEnumerable, with a single line of code:

BindingList<Customer> CustomerCollection = new BindingList<Customer>();

By doing just this, you get a collection that works fine with both Windows Forms and ASP.NET data binding mechanisms, including two-way data binding (presentation and editing) support in Windows Forms, and also will fire ListChanged events whenever items in the collection are added, removed, or replaced. If you want to support events when the contained objects are edited, you will need to implement the INotifyPropertyChanged interface on the object type definition itself (this interface is named IPropertyChanged in Beta 1).

Additionally, if you want to support sorting and searching on the collection, all it takes it to derive a class from your BindingList<T> parameterized type, and override a few base class methods and properties. For example, you could declare a Customer collection and provide searching capability with something like the following:

public class CustomerCollection : BindingList<Customer>
{
   protected override bool SupportsSearchingCore { get { return true; } }

   protected override int FindCore(PropertyDescriptor property, object key)
   {
      for (int i = 0; i < Count; i++)
      {
            Customer c = this[i];
          if (property.GetValue(c) == key)
          {
              return i;
          }
      }
      return -1; // Not found
  
}
}

Very powerful stuff. Sorting is a little more involved, but follows the same process. Override the sort related properties, and provide a sorting algorithm in the ApplySortCore override and you are off and running.

So much easier and more powerful than the old derive from CollectionBase approach. You get type safety, alot of additional functionality, and the efficiency of generic types.



.NET | Languages and Tools

Monday, January 10, 2005 4:09:21 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Saturday, January 1, 2005

Removing duplicate posts from Outlook and Newsgator

I use Newsgator for aggregating feeds into Outlook. Unquestionably the best tool available if you a) read blogs, and b) use Outlook for email or other daily functions.

I also frequently rebuild my laptop where I run Outlook and Newsgator. Being a speaker, trainer, writer, and consultant, I often introduce new software onto my machine, try things out, install and uninstall various betas and things, and I don't always feel like paying the perf penalty of doing it all in a VM. So a lot of software entropy accumulates on my machine, requiring frequent rebuilds, which take all of about 30-60 minutes to get back to a fully loaded and stable development machine baseline thanks to Norton Ghost.

The one thing that has annoyed me in doing this is that every time I rebuild my machine, then reattach Outlook to my Blogs.pst file where my subscribed feeds go, Newsgator redownloads all the latest posts into the subscribed folders, resulting in tons of duplicate posts. This is a pain on two fronts. One, it means that a bunch of posts get added that are marked as unread, even though there are copies of them in there that have been read. I haven't cracked that nut yet. The other problem is just the presence of the duplicate posts in the first place. That means that my blogs.pst file has been getting really big, which complicates my backups, and causes my Lookout and Google Desktop indexes to take longer to build and take up a lot more diskspace.

Enter MAPILAb Outlook Duplicate Email Remover. For a mere $15, this add-in does an outstanding job of scouring your Outlook folders and removing emails (or Newsgator posts, which use the Outlook email type for storage) that are duplicates. Well spent money.



Blogging | Languages and Tools

Saturday, January 1, 2005 2:17:31 PM (GMT Standard Time, UTC+00:00)
Comments [2]  | 

Visual Studio 2005 December CTP and WinForms

I spent a little time in the last week playing with the December CTP of Visual Studio 2005. Specifically, I was hoping to use it on the chapter I was working on for my book.

The Good:

The has been a lot of refactoring going on by the Windows Client team between Beta 1 and Beta 2. Unfortunately some of that has been downscoping and removing features. A lot of stuff has been renamed as well. It looks like most of those changes are in this CTP, so if you want to see something more representative of what the RTM will look like, and a lot closer to Beta 2, then this CTP is good for that.

The Bad

This does not appear to be a very stable release from a Windows Forms development perspective. Just putting together a couple simple data binding scenarios resulted in a bunch of exceptions for things where the designer was doing all the code writing, so it wasn't a lack of understanding of the programming model on my part. So if you want to actually write any significant apps or samples in Windows Forms, I don't think you will want to do it with this CTP.

My strategy for the chapters and samples in my book is still to keep developing on Beta 1 for now, keeping in mind what is changing in Beta 2 (which can be explored with this CTP), and plan on doing a port of everything to Beta 2 as soon as it is available.



.NET | Languages and Tools

Saturday, January 1, 2005 1:55:09 PM (GMT Standard Time, UTC+00:00)
Comments [3]  | 


 # Wednesday, November 17, 2004

Generics performance concerns? Don't sweat it!

Sahil points to the #2 bug report on the MSDN Product Feedback center regarding concerns over the performance of generics. My feelings on this pretty much echo an earlier post I made about performance in general.

Who cares if generics are 1000 or 10000 times slower (which I don’t believe – it might be for first call while the type is dynamically generated and compiled if necessary, but after that the difference should be small)? What matters is whether the performance of your application as a whole is sufficient and meets your specifications. People make this mistake all the time, worrying about the overhead of every instruction, when the real performance of whole applications is usually determined by network/file/database I/O or particular computational processes. That is where you worry about performance – at the places where you have identified through measurement that it needs to be addressed. Everywhere else, do what makes the most sense for maintainable code – and the type safety and reduction of repetitive code declarations provided by generics are huge from that perspective.

 

Bottom line is that even if it is 1000 times slower across the board , I don’t believe that will have a significant impact on the overall performance of most apps that will use generics. You also have to be very careful about making claims like this without substantiating them with actual measurements and the situations under which the measurement was performed. I bet I can set up a loop with a generic collection and an untyped collection of value types where the generic collection would beat the pants off the non-generic collection due to all the boxing/unboxing that has to occur getting those value types in and out through object references. Does that mean that generics are XX times faster than non-generics? No, it means that in one particular scenario (which is probably an immeasurable fraction of the overall computing time of the application) there is a measurable benefit of using one approach over another.

 

Bottom line: Generics have huge benefit. You should plan to use them anywhere you want type safety and don't want to reinvent the wheel. If you have implemented something with them and have MEASURED that to be a bottleneck for performance in your application, then optimize that code... possibly removing the generics. But please people don't start preaching that it is a “best practice“ not to use generics because of “performance“. Ugh.

 



.NET | Architecture | Languages and Tools

Wednesday, November 17, 2004 2:06:47 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Friday, November 12, 2004

Little Rock .NET Users Group Slides and Demos

I had a great time presenting at the Little Rock .NET Users Group last night on my way back to DC from VS Connections in Vegas. I was very impressed with this group. They had a good sized crowd (30-40) in a good little meeting room that was actually inside a Pizza Hut, and are led by a great group of guys. One of the most energetic groups I have seen, and when you consider the population and industry presence in Little Rock compared to the group size, you'll realize these guys are doing a great job of running a user group! There are a lot of times we don't get many more attendees at CapArea.NET, even though we meet in the heart of the tech sector of DC.

I want to thank the group for having me out to speak and pass along the slides and demos.



.NET | Community | Languages and Tools | Speaking | Travel

Friday, November 12, 2004 11:22:47 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, November 10, 2004


 # Tuesday, November 9, 2004

Cool Tablet App - Aureole (not the nipple)

Had a spectacular dinner with my wife Robin last night at one of the swankiest (and priciest) restaurants in the Mandalay Bay hotel in Las Vegas last night. The food was outstanding (one of the top ten I can remember, and we eat out at a lot of great restaurants on travel and in DC).

The restaurant was Aureole, and one of their unique features was the four story high, four sided tower of wine that dominates the center of the restaurant. In order to get your bottle of wine, the wine steward, wearing caribiners, hooks into cables and gets hoisted up to wherever in the stack the bottle may reside.

That in itself was pretty cool, along with the great food, but what was interesting was how they manage presenting their extensive (and frequently changing) selection of wines to the customer. The wine list was brought to us as a Tablet PC running an internal web app that you could use to browse the hundreds of choices of wine, and even get additional background information on any that you are interested in. It had a bookmarking feature so that you could select any that you might be interested in as you browse the entire collection, then review your short list to make your final selection. You did all this with simple point and click with the pen.

My first thought, being a smart client zealot, was that they should have made it a smart client application. But the fact was that it was truly just a browsing app, and used a lot of graphics and animation to enhance the experience that would have been more difficult to achieve in a WinForms app.

I was just happy to see yet another powerful user experience enhanced by tablets and technology.

And the wine and food rocked.



.NET | Hardware | Languages and Tools | Travel

Tuesday, November 9, 2004 3:34:31 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Sunday, August 29, 2004

Reflector, what an awesome tool!

I just have to do a little spontanuous gushing on Reflector due to how extremely useful it is for me while working on my book (Building Windows Forms Data Applications with .NET 2.0). I've been chugging along, and it is going very well. However, I would be lost or taking significantly longer to get things figured out if it were not for Reflector.

I've been using Reflector off an on for a while now, but only recently started using it to figure out the Whidbey bits. It runs just fine against the .NET 2.0 bits, it just takes adding a config file to set the runtime to the .NET 2.0 Beta runtime so that it is happy. Basically, you just need the following in a Reflector.exe.config file in the app directory:

<configuration>

<startup>

<requiredRuntime version="v2.0.40607" />

</startup>

</configuration>

Every time I come across one of those gaping holes in the Beta docs that they just haven't gotten to yet, it just requires firing up Reflector to dive into the implementation code to see exactly what a certain parameter means and how the method is going to use it.

Lutz Roeder: they should have a special community title for people like you who create tools of this caliber and usefulness, and then put them out there for free. Perhaps Microsoft Community Demi-God would be sufficient, perhaps not.

The fact that the tool is very polished and functional beyond just decompiling the IL is just very rich gravy on the steak. I especially love being able to get the Callee graph on something to see where a particular property is used or a method called from.

Thank you, Thank you, Thank you, Thank you.



.NET | Community | Languages and Tools

Sunday, August 29, 2004 5:05:05 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, August 15, 2004

Clearing up the lingo: Whitehorse, Burton, Visual Studio Team System

A lot of people are throwing around the terms “Whitehorse”, “Burton”, “Visual Studio Team System”, “Class Designer” and others and incorrectly mixing and matching the combinations. Here is some information to help make things clear to those who might be a little confused by code-name mumbo jumbo.

Visual Studio Team System (Code-named Burton) is the family of products that will include new software development lifecycle management and design tools. There will be several product offerings in the family, targeting developers, testers, architects, and managers. Each of those will contain a different grouping of lifecycle tools, focused on their individual role in the lifecycle.

Visual Studio Team Architect (Code-named Whitehorse) is one of those products targeted at the Architect role, and contains the Service Oriented Architecture designers for modeling services and infrastructure. These tools are what are really referred to as “Whitehorse”. When you hear or say Whitehorse, you should be thinking SOA tools.

The Visual Studio Class Designer is a modeling tool that will be part of Visual Studio Standard and Professional versions, and all versions of Visual Studio Team System. The Class Designer is not part of Whitehorse. It is a feature of Visual Studio.

So just to put it in a few concise terms programmers should understand:

VSTS != Whitehorse

Class Designer != Whitehorse

VSTS == Burton

Now that we've cleared that up, I can get back to coding. Get it right, people!!!! :)



.NET | Community | Languages and Tools

Sunday, August 15, 2004 1:07:53 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, August 14, 2004

Data Binding Scenarios??

I'm looking for suggestions for some tough data binding scenarios you have or would like to tackle in an application to use as sample cases for my book on WinForms data binding in .NET 2.0. If you have any nasty little scenarios that are not too contrived, let me know and maybe I can solve them and use them in my book.

Thanks!



.NET | Community | Languages and Tools

Saturday, August 14, 2004 7:04:08 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, August 13, 2004

Using Web Services as Data Sources in the Data Sources Window in Visual Studio 2005

The Data Sources Window in Visual Studio 2005 allows you to drag and drop data sources onto a form to generate all of the controls and components needed to use that data source for databinding. The Data Sources Window support binding to databases, Web Services, and custom objects.

The Web Services piece is still a little quirky in Beta 1 because they wisely chose to only let you bind to public properties on an object definition, not public fields. This will hopefully discourage the definition of public fields to expose data from a class, which is a bad idea all around. However, the current client proxy code that gets generated for a Web Service when you create a Web Reference just exposes public fields on the classes generated for objects returned from a Web Service. Thus the Data Sources Window in Beta 1 won't let you see any of the members on the object types returned from the Web Service.

The good news is that the wsdl.exe tool that ships with the .NET 2.0 SDK does in fact create public properties to wrap the members on the objects returned by a web service. So there is a fairly straightforward workaround to get Web Services working with the Data Sources window in Beta 1, detailed below.

1. Go through the Add Data Source wizard, select Web Reference as the type of Data Source, and point it at the WSDL URL for the data source. For example, you would point it at the Amazon Web Service at:

http://soap.amazon.com/schemas3/AmazonWebServices.wsdl

2. After completing the wizard, go check what the namespace is for the generated web procy file. To do this, you need to select Show All Files in Solution Explorer, and drill down to the Reference.cs file that was created under the Web References node for the Web Service. For the example above, that would be <YourApplicationNamespace>.com.amazon.soap.

3. Fire up a Visual Studio 2005 command prompt window, and run wsdl.exe with the wsdl url, an out param to generate the Reference.cs file, and the namespace param to set the namespace from step 2. Example:

wsdl.exe http://soap.amazon.com/schemas3/AmazonWebServices.wsdl /out:Reference.cs /n:MyApp.com.amazon.soap

4. Copy the generated Reference.cs file (or vb if that is your flavor) into the WebServices subfolder created under your project where the existing Reference.cs created by the Add Web Reference process lives, overwriting the existing file. You should see that the file sizes are about double. That is because the wsdl.exe has property wrappers for all the fields that the Add Web Reference one just exposed publicly.

5. Close the Data Sources window. Then close Visual Studio. Then reopen your project in Visual Studio 2005 and reopen the Data Sources window.

you should now be able to drill down into the properties of the data source objects returned from the web methods of the web service, and if you drag them onto a form, proper UI will be generated.



.NET | Community | Languages and Tools

Friday, August 13, 2004 11:21:51 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Demos from today's Windows Forms Data Binding with Data Sources in Visual Studio 2005 MSDN Webcast

Here are the demos from today's MSDN Webcast on using the Data Sources Window in Visual Studio 2005 to generate data bound UI in Windows Forms applications.

One caveat - I accidentally lied about the little demo I showed at the end that was getting album covers from the Amazon Web Service. While it is an interesting little demo, I was mixing it up with the greater project I created it for as far as the involvement of the Data Sources window. This app is actually just a simple Web Service client that takes the values returned through a data set and dynamically generates PictureBox controls to present them. The DataSources window actually has no play in this one. I included the code anyway, if you want to run it, you will have to go get a developer ID for the Amazon Web Service at http://www.amazon.com/gp/aws/landing.html. You will need to plug this in to the agent source file where it says to plug in your id here.

 



.NET | Languages and Tools

Friday, August 13, 2004 10:53:41 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Demos from today's Extend ASP.NET MSDN Webcast

You can download the demos here.



.NET | Languages and Tools

Friday, August 13, 2004 8:40:42 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, August 12, 2004

UIP MSDN Webcast demos

Look here

Thanks!



.NET | Architecture | Languages and Tools

Thursday, August 12, 2004 10:46:16 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Passing Arguments when starting a task in UIP

Version 2 of the UIP application block came out back in April, and included a lot of new functionality. Unfortunately, they also broke one important capability in moving from v1 to v2: the ability to pass in an set of initialization arguments to get a task initialized.

In V1, there was an overload of the UIPManager.StartTask method that allowed you to pass in an instance of a TaskArgumentsHolder object, which itself has a placeholder TaskArguments object reference where you could stuff anything you needed to pass downstream to the task that is being launched, such as user login info, command line or querystring params, etc.

This disappeared in V2 with the move to multiple navigation models. However, the fix is pretty straightforward to get that capability back - it just involves making a minor tweak to the UIP library source code, which is not a problem since you get full source code with the block.

Basically, what you need to do is go into the Navigators folder within the UIP project, and for each navigator type you want to support arguments on, you need to change the visibility of the StartTask method that takes a TaskArgumentsHolder parameter from private to either internal or public:

public void StartTask(TaskArgumentsHolder holder) { ... }

Then go into the UIPManager class, and add an overload for each of the StartXXTask methods that takes a nav graph name and a TaskArgumentsHolder, and have it call the appropriate StartTask on the appropriate navigator:

public static void StartNavigationTask(string navGraph, TaskArgumentsHolder holder)

{

GraphNavigator navigator = new GraphNavigator(navGraph);

navigator.StartTask(holder);

}

As soon as you do that, you are back in business. You can start a task and pass in arguments with something like this:

TaskArgumentsHolder holder = new TaskArgumentsHolder(Guid.Empty,null,"startupargs");
UIPManager.StartNavigationTask("StartupParams",holder);

That's all there is to it.



.NET | Architecture | Languages and Tools

Thursday, August 12, 2004 6:54:14 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Troubleshoot ClickOnce Deployment problems

A tool that many people are not aware of is MaGe - the Manifest Generator tool (mage.exe). It resides under your root Visual Studio 2005 directory SDK folder in the bin subfolder along with the rest of the .NET SDK tools.

ClickOnce deployment (.application) and application (.exe.manifest) manifest files are just XML files with a particular schema that are digitally signed with either a strong name key file (.snk by convention) or a publlisher certificate. That signing process ensures the identity of the publisher as well as making sure that the manifests are not tampered with (say to add a malicious file as part of the application download) after being published.

MaGe allows you to open, edit, and save both types of manifest files. When you save the file, it prompts you for a key file or certificate to re-sign the manifest. The tool is intended for large organizations where the deployment servers will likely be managed by IT folks that are not the developers and not running VS2005, so that they can make updates to the deployed applications and the information that goes into the manifest.

However, MaGe can also be a big help in troubleshooting and understanding your ClickOnce deployments in the development environment, especially while we are still in Beta and sometimes problems occur. One of my collegues was having a problem where he could not launch any of his ClickOnce applications after publishing. We are still trying to track down root cause, but simply opening the manifests in Mage and resaving them fixed the problem.

You saw in a previous post how you can also use MaGe to handle resigning the deployment manifest after making a manual addition to support command line arguments.

Just another good trick to have in your toolbox if you are working with ClickOnce. Hopefully this will really just be a handy tool for admins once we get to release, but for now it is pretty important for devs as well.



.NET | Languages and Tools

Thursday, August 12, 2004 11:31:37 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, August 10, 2004

Harvesting ClickOnce Command Line Arguments

Thanks to Jamie Cool, Microsoft PM for ClickOnce, for providing the answer on a question I am often asked in talking about ClickOnce:

Question: How can I use command line parameters with a ClickOnce deployed application?

To answer that, you need several pieces of information:

1) How do you pass command line arguments to a ClickOnce application?

ClickOnce applications are launched using a URL to the deployment manifest (.application) file. So you use web querystring parameter syntax:

http://mydeploymentserver/MyApplicationFolder/MyApplication.application?param1=foo&param2=bar

2) How do you tell ClickOnce and .NET Security to allow you to use the command line parameters?

Under the covers, you need to add a trustURLParameters=“true“ attribute to the deployment element in the .application (deployment) manifest file. In Beta 2, or at least by release, this should just be a checkbox in the poject properties Publish section. You can do this by dragging the .application file into Notepad.

You then need to open the manifest with the mage.exe tool (located in the <vstudio 8>\SDK\bin folder), and save it again, specifying a key file to re-sign the manifest. If you try to launch the app without doing this, the runtime won't do it on the client machine because it sees that the manifest has been tampered with since it was published.

Make sure to check the .application file again after signing to see if your trustURLParameters attribute is still there. If you screwed up the (case sensitive) name (as I did the first couple times), the Beta 1 mage tool will throw away any attributes it doesn't recognize when you save to re-sign the manifest.

3) How do you harvest the values passed via querystring assuming you have done 1 & 2?

string cmdLine = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0];

This will give you back the entire command line (URL with parameters), so you just need to parse that string for the ? separator between the path and the params, and then parse the remainder for the & and = separators.

Piece of cake!

 

 



.NET | Community | Languages and Tools

Tuesday, August 10, 2004 10:58:37 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

ClickOnce demos from today's MSDN webcast

Download them here.

Enjoy!



.NET | Community | Languages and Tools

Tuesday, August 10, 2004 10:51:10 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, August 9, 2004

DataGridView demos from MSDN Webcast today

Here are some simple demos I presented today in my webcast on the DataGridView control in .NET 2.0. Lots of cool new features for WinForms developers.

Kiss that obnoxious DataGrid goodbye!! There's a new grid in town, yaheer? (Yes it is still fully supported for backward compatibility!)



.NET | Community | Languages and Tools

Monday, August 9, 2004 8:48:33 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, July 26, 2004

Visual Studio Extensibility Demos and Links from today's MSDN Webcast

CMAB MSDN Webcast demos from today

Actually, just go to this post, form when I gave it recently. The demos haven't changed.

Thanks for attending!

 



.NET | Community | Languages and Tools

Monday, July 26, 2004 10:45:37 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

VS 2005 Beta + VS 2003 Side by Side

Once again, Josh has pointed me towards the solution of getting Visual Studio 2005 Beta 1 running side by side with Visual Studio.NET 2003.

In this case, I had a clean Windows XP Pro + SP2 RC2 install, installed VS 2003 + all my add-ins, tools, etc., then installed VS 2005 Beta 1. Whenever trying to debug a Web app after the install, I got:

Unable to start debugging on the web server.”

 In the debug window, it outputs:

Auto-attach to process '[3172] aspnet_wp.exe' on machine 'WINXPPRO-VM1' failed. Error code 0x8013134b.

The solution, found on the forums at asp.net was to simply switch the selected runtime from the new ASP.NET tab in the properties for the default web site in IIS.



.NET | Languages and Tools

Monday, July 26, 2004 12:52:09 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, July 9, 2004

EMAB Demos from todays MSDN Webcast

If you attended my MSDN Webcast today on the Exception Management Application Block thanks for attending! If you didn't, you suck, but can have the demos anyway. :) Just Kidding!!

Luckily I didn't pass out and my computer didn't explode from the heat since my A/C died yesterday and it is 90 degrees out and probably hotter inside right now! Off to Home Depot to buy some temporary relief until the main unit can be replaced (pronounced DOA by the service tech this morning).

Anyway, here is a link to the demo code. Let me know if you have any questions, and enjoy!



.NET | Community | Languages and Tools

Friday, July 9, 2004 10:51:01 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Wednesday, June 30, 2004

MSDN Product Feedback Center

Yes! It is now public so we can talk about it and use it more widespread. The MSDN Product Feedback Center was announced today at TechEd EU, and was the official launch of the center to the public. You can check it out here:

http://lab.msdn.microsoft.com/productfeedback/

Basically this will allow you to submit bug reports direct to the Microsoft Product Teams, track other bugs that have been reported, and get direct feedback on the problems you are having.

This is a great idea, I just hope it works. I don't envy the guys responsible on the product teams for managing this. I can't count the number of times I have people tell me they “found a bug” in some .NET technology, when the “bug” is really just their misunderstanding of how to use it correctly or wanting it to do something it was not designed to do. I just hope the signal to noise ratio is high enough to make it effective.



Community | Languages and Tools

Wednesday, June 30, 2004 3:06:59 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, June 28, 2004

MSDN Webcast CMAB demos

Here is a link to my demos for the webcast today on the Configuration Management Application Block.



.NET | Community | Languages and Tools

Monday, June 28, 2004 8:49:48 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, June 27, 2004

New tools weekend

I have had a number of tools on my “to-do” list for a while now that I wanted to check out and see if they are worthwhile. Let's just say that if I had got off my ass sooner and looked at those tools, I could have easily gotten to other things on my “to-do” list much quicker. I've seen most of these mentioned in various people's blogs, which is how they made it on my list of things to check out. But it really doesn't take hold until you try them out yourself.

First newest favorite tool : CodeRush. Yes, I heard the buzz at TechEd (thanks to a lot of evangelizing by Marc Miller and Scott Hansleman, but didn't get around to checking it out until now. What can I say. WOW. So many features and capabilities, I won't enumerate them here. Just go check it out. Makes your coding experience in VS.NET a whole different (and much more productive) thing.

Next favorite: CodeSmith. Freeware code generation tool, with lots of templates and community support. Way cool. I am so done writing tedious data access, stored procedure, and business object structure code.

Yet another: X1. I blogged about Lookout lst month, which is very cool, free, and does most of what X1 does. Basically it is a google-like search engine for stuff on your machine. X1 does an even better job, working by indexing emails, files, attachments, and contacts on your machine, and making it very fast and easy to find things that I used to spend an inordinate amount of time manually hunting for on my machine. Did I put that in a file, outlook message, or contact? Well, how about answering that in seconds instead of tens of minutes.

Another cool code gen tool: RapTier. If you just want to quickly generate a data access layer for your app, or stored procedures to wrap your tables and views, or generate database documentation, this tool will get you there quick. It too (like CodeSmith) is template driven and customizable, so if you don't like the default output, it is not real hard to customize. I haven't yet decided whether I will use this more than CodeSmith. Will have to see as I use it more on some real projects.

So a few hours invested this weekend playing with new toys is going to pay off handsomely in boosting my productivity. This is one of the things I am loving more and more about the .NET community - the constant growth of capabilities and tools to make the “out-of-the-box” benefits of .NET (which are HUGE compared to other dev platforms) get dwarfed by the benefits of the things you can use in that environment to do your job better, faster, cheaper, and funner.



.NET | Community | Languages and Tools

Sunday, June 27, 2004 3:50:01 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, June 26, 2004

Webcast on the Configuration Management Application Block Monday

Tune in to the webcast if you want to learn how to read/write config data from .config, XML files, SQL Server, or the registry, encrypted or unencrypted.

 



.NET | Architecture | Community | Languages and Tools

Saturday, June 26, 2004 10:25:08 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, June 15, 2004

User Interface Process Application Block MSDN Webcast slides and demos

Hi All,

For those of you who attended - thanks for sticking in there through the webcast server problems. Glad we were able to get running 10 minutes late or so. We were literally one minute from pulling the plug and declaring it a bust when the servers came back up and you all started popping into the room.

Here is a link to a PDF of the slides.

Here is a link to the demos.

Enjoy!



.NET | Architecture | Languages and Tools

Tuesday, June 15, 2004 10:55:11 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, June 13, 2004

Visual Studio 2003 Web Setup project uninstall debris in metabase

Visual Studio 2003 Setup and Deployment projects make it a snap to create an installer package to deploy your web app to a server and get all the files deployed and create a virtual directory in IIS. They even clean up and remove the virtual directory from IIS on uninstall.... or do they?

When you uninstall a VS created web installer using VS or the Add/Remove programs control panel, the files, folder, and vdir go away as you would expect. Unfortunately it apparently leaves some debris in the metabase for the virtual directory that sometimes creates problems for reinstalling the same application. A quick look with MetaEdit after doing an uninstall of one of these projects will reveal under the LM\W3SVC\1\ROOT that there is still vdir entries left around.

Anyone else encounter this or know a workaround, other than to first delete the vdir through IIS manager before running the uninstall? We could of course write a custom uninstall action to clean up the mess left by the VS setup project's uninstall step, but that kind of thing just makes me feel dirty all over.



.NET | Languages and Tools

Sunday, June 13, 2004 5:47:00 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, June 8, 2004

Slides and demos from DevEssentials

Had a great few days in Kansas City at DevEssentials this weekend. For those of you who attended my talks, thanks for coming, hope you got a lot out of it.

Here are download links for the slides and demos for each one:

Configuration Management Application Block

Deploying .NET Applications

COM Interop



.NET | Community | Languages and Tools

Tuesday, June 8, 2004 1:11:45 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, June 7, 2004

Great synapsis of TDD

Jay wrote a great elevator speech length summary of what TDD is and means here.



Languages and Tools

Monday, June 7, 2004 4:06:01 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, June 4, 2004

VS 2005 MSDN Library problem - downloading pages never goes away

Had a problem with the MSDN Library for Visual Studio 2005 May Community Tech Preview (CTP) where it would just shown downloading... in the status bar forever for any topic selected.

After some googling, discovered that the readme on the MSDN VS2005 site is newer than the one on the DVD and addresses the issue:

If you use the external Help viewer with the Visual Studio 2005 Community Technology Preview May 2004, the Help system appears to be frozen when you try to access a topic. (You see the "Downloading..." message in the status bar, the progress bar barely moves, and the Internet Explorer icon continues to spin.)

Workarounds:

In the "C:\Program Files\Common Files\Microsoft Shared\help whidbey\dexplore.exe.config" file, change the following lines:

<supportedRuntime version="v2.0.40507" safemode="true"/>
<requiredRuntime version="v2.0.40507" safemode="true"/>

to:

<supportedRuntime version="v2.0.40426" safemode="true"/>
<requiredRuntime version="v2.0.40426" safemode="true"/>

- or -

Switch the Help settings in Visual Studio to use internal, rather than external Help. To do this, select Options from the Tools menu in either the Visual Studio IDE or the external Help viewer. In the Options window that appears, expand the Help entry and select the General subentry. In the Show Help Using dropdown list, select Internal Help Viewer. Click the OK button.

I recommend you check out the latest readme online if you are encountering any other problems since it looks like that will continue to be a living document:

http://msdn.microsoft.com/vs2005/currentreadme/default.aspx

 



.NET | Community | Languages and Tools

Friday, June 4, 2004 6:15:39 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, June 3, 2004

Extending ASP.NET MSDN Webcast demos

For those of you who joined me in the MSDN webcast today, thanks for your patience with the machine lock ups and not being able to complete the demos live for you. Hopefully the slides and discussion still made it worthwhile for you.

Here is a link to the demos that I was going to show. There are several in there and there is a readme that tells you what is there and how to get it running. If you have any problems getting it going just drop me a note or a comment to this post and I will help you out.

In case you know someone who didn't tune in and would like to be subjected to the same pain, I should be repeating this session on 13 August (and will work out the machine lock ups by then!!).

Thanks, Brian

 



.NET | Languages and Tools

Thursday, June 3, 2004 11:27:07 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, May 28, 2004

TechEd Deployment Slides and Demos

Here are the links to download the demos(1.7MB) and PDF slides (1.4 MB) of my Deploying .NET Applications with Ease talk. Went well, thanks if you attended!



.NET | Community | Languages and Tools

Friday, May 28, 2004 8:31:10 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, May 27, 2004

Microsoft Application Block focus and evolution

I led a Birds of a Feather session last night on the Microsoft Application Blocks that was pretty well attended for being the last timeslot. Most of the people there had not yet used any of the blocks, so it ended up being more of a Q&A than a discussion, but it still went well and was a lot of fun.

Today I attended a session by Wojtek Kozaczynski from the Patterns and Practices team that puts out the blocks. Very good session on the future of the blocks that I wish I had attended before my BoF. They are working on something they are calling the Application Block Library that will be released towards the end of the year. This ties together a number of the existing blocks such as data access, exception management, configuration management, caching and more into a single library that is more consistent with the architecture and interdependencies of the blocks. They are also going to add some functionality to each, improve the documentation and samples to be more consistent and well formatted, and will include an administrative tool that will plug into Visual Studio 2003 and run as an external tool to ease the configuration and management of the blocks through their underlying configuration settings. All very cool stuff.

Bottom line message was to start using the blocks available today, don't wait for the library, but for apps that get started next year you will have a will have a whole new set of blocks to work with that will be even better.

 



.NET | Architecture | Languages and Tools

Thursday, May 27, 2004 2:29:26 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, May 18, 2004

Deploying .NET Application talk at TechEd

If you are hanging out through the last day at TechEd and want to learn more about deploying .NET applications, come check out my talk DEV355 - Deploying .NET Applications. I'll be covering the basics of No Touch Deployment, and then going into detail on using Setup and Deployment projects to create MSI installers for apps of various types including WinForms apps, Web apps, Windows Services, and Enterprise Service components. I'll be showing several examples of creating custom installer classes with .NET code that you can easily plug in as custom actions in your installers to do things like create and populate databases and register and configure Enterprise Service components.



.NET | Community | Languages and Tools

Tuesday, May 18, 2004 1:03:29 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

Microsoft Application Blocks BOF at TechEd

My Birds of a Feather (BOF) session for TechEd got approved. If you are interested in learning more about the Microsoft Application Blocks or share your experiences using them, come join us at 8:30 pm on Tuesday 25 May in room 14A.



.NET | Community | Languages and Tools

Tuesday, May 18, 2004 1:02:29 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

ClickOnce - speaking at Bay.NET on Wed

If you are interested in learning about the future of auto-deployment of smart client applications with .NET, specifically ClickOnce (a new deployment technology in .NET 2.0), and you are in the bay area, come check out my talk this Wed night at the Bay.NET user group meeting. (www.baynetug.org).



.NET | Architecture | Community | Languages and Tools

Tuesday, May 18, 2004 1:01:08 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Monday, May 17, 2004

Lookout rocks

I file every meaningful e-mail I get in a complex folder structure and have a way-to-elaborate scheme for organizing those folders and backing up and archiving them. As a result, I often find myself searching for an email I know I got a few weeks, months, or years ago, and sometimes I don't know exactly where I need to look. Now, I have always liked that Outlook will let you search an entire heirarchy of folders through the advanced search feature, but let's just say the performance of those searches left something to be desired.

I just downloaded Lookout the other day after discovering it from Robert's blog. This tool rocks. Search my entire (800MB) pst for a particular keyword - approximate 500 ms. Try the same thing through Outlook itself, well, go get a workout in, read war and peace, etc.

The cost is free for now (still in preview), but this is a tool I will gladly pay for once released, much like Newsgator. In fact, the too play perfectly together. That is how I remembered where I read about Lookout, a quick search with the tool, 480 ms, and bamm - there it was, of course it was Scoble. I am constantly reading blog entries these days on my tablet while mobile (i.e. the elipse trainer at the gym) and then later wanting to go back and find that post. The speed of Outlook searches previously made that intractable. Now, no sweat.

The impact on your machine is a little disk space. It works by building indices off your message store so that it can accomplish the speedy searches. Very smart. They liken themselves to being the google for email, but really it goes beyond that.

Very cool, you need to check it out if you use Outlook with any regularity.



Community | Languages and Tools

Monday, May 17, 2004 2:59:19 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Friday, May 14, 2004

COM+/Enterprise Service Components are not a legacy technology

I am a firm believer in the use of component based development, and for the middle tier, Enterprise Services is the right way to go for most serious applications. Unfortunately there are a lot of misconceptions about the positioning of Enterprise Services, aka Serviced Components, aka COM+ with respect to .NET development. The biggest of these is viewing COM+ development with .NET as a legacy approach. Another is that when you build COM+ components with .NET, you are doing COM interop. Another is that COM+ is too hard to be worth it. All of these are just wrong.

To really get things in perspective, you have to think of COM+ as what it really is - component services provided by the operating system. In the same way that you use the OS for services such as file and network I/O and access control, when you use COM+, you are really just using component services provided by the OS. So doing COM+ in .NET is no more “legacy” than doing file I/O or network calls using .NET. In fact it is much less so because the level of abstraction and architecture provided by COM+ is far more advanced than those other services provided by the OS. When Microsoft put together COM+, they put together a very forward looking architecture for building robust, scalable, high performance applications.

Building Enterprise Service components is also the best thing you could be doing today to migrate to Indigo tomorrow. Most of the hype surrounding Indigo (and well, just about everything in the last couple years) is about Web Services. And yes, one of the primary scenarios for using Indigo will be to build service oriented applications that happen to communicate using web service protocols. But the thing is that the Indigo programming model abstracts away all the web service goo from you and lets you work with a much more clean and declarative model. It happens to have a declarative model that looks much closer to Enterprise Services programming today than it does to web services programming today. Through configuration, you will be able to control the transport layer and make it act like a web service, Enterprise Services, or .NET REmoting under the covers, but your code will look an awful lot like ES code from what I have seen.

So ES is not legacy by any stretch, it is very current and powerful in its capabilities, and it is very forward looking in terms of what you will build in the future.

What about interop? Well, certainly if you are calling out to a legacy COM component that is running in COM+, you are doing COM interop. But if you build a .NET ES based system, the .NET components do not use COM interop to talk to one another. There is some unmanaged code in the loop for providing those component services from the operating system such as distributed transactions, security, instance management, queuing, loosely coupled events and so on. But there is unmanaged code involved for many other things your apps do that reach outside of their own context, so you shouldn't let that fact drive your thinking about ES. Bottom line is that you need to try things and see if the technology can provide the performance needed for your application, not just blindly avoid things that you perceive to have performance penalties. And the fact is that you can get some huge performance benefits from the instance management features of COM+ and from the speed of the underlying transport if you design your system well.

Finally there is the difficulty of building ES systems. And yes, this is not the kind of technology that your average community college philosophy major can use to throw together a toy app in an afternoon. You have to design your system, consider the communications and calls between components, figure out which services you need to use and how to best use them, and you have to have a lot of discipline and automation in your development and build process to do it right. But the benefits of doing these things are huge on their own and are something you should be doing for critical business applications in the first place, whether you use ES or technology X.

You also have to consider the time/cost payback of using ready-to-use, well tested and proven technology for services like distributed transactions, authentication and authorization at the application, component, interface, and method level, object pooling, just in time activation, queued component method calls, etc. etc. Sure you can build your own mechanisms for these things, but are you really so vain as to think you can build it better than they did? And without spending orders of magnitude more time than it would take to use the services out of the box? Need 2, 10, or a 100 components that call each other, possibly touching many different databases, to all become part of one distributed transaction? Sure thing, just slap an attribute on each class and each public method and you are done with ES. How long would it take you to get this right managing the transactions yourself? A little longer methinks. A security mechanism that can be locked down by the developer with a few attributes at design time based on the spec, but that can be easily modified later on adminstratively if requirements change? Done with ES. Spin your own? Have fun. Dispatch method calls asynchronously through MSMQ to components that you may not even have network access to at the time you execute? Sure thing, with ES a couple attribute, a slightly different instance creation coding pattern, done. Spin your own? Have fun.

Bottom line, people need to get past the fear and misconceptions of Enterprise Service components. If you are building toy apps, go ahead and ignore ES and keep building monolithic or client-server apps that don't scale and are hard to maintain. But if you are building serious business apps for the middle tier and might need any of the services mentioned, then you should be looking at ES as one of your first choices. ES is an incredibly powerful capability that too many companies dismiss out of hand.

If you want to learn more, first, pick up a copy of Juval's book. A strategic .NET-only developer will read every chapter for the concepts and understanding of each of the COM+ services, but will not get wrapped up in the C++ code presented. They will then cross reference the appropriate portion of Chapter 10, which presents just how to use each service with Enterprise Services in .NET.

Also, check out our IDesign Method, which is one of our service offerings for helping companies architect and design their ES systems.



.NET | Architecture | Languages and Tools

Friday, May 14, 2004 9:22:09 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, May 6, 2004

Yet another side-by-side VS 2003 - 2005 installation

Installed VS 2003 and 2005 side by side again and had to do the treasure hunt through google to find all the little fixes to get it all working again, so thought I would consolidate them here.

After installing both:

1) Fix the registry keys so that IIS manager works again.

2) Unregister aspnet_isapi.dll in the v2.0.40301 directory under windows\microsoft.net with regsvr32 -u.

3) Re-register aspnet_isapi.dll in the v1.1.4322 direcoty with regsvr32.

4) Re-install iis from v1.1.4322 with aspnet_regiis -i

5) Reset IIS with iisreset.

After that, life was good with IIS, IIS management, VS web project creation and debugging.



.NET | Languages and Tools

Thursday, May 6, 2004 1:24:02 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Tuesday, April 13, 2004

Hosting multiple communities with the ASP.NET Community Starter Kit

I had a reader of my article ping me today because he was having a hard time finding good concise help on how to set up two (or more) communities in an installation of the Community Starter Kit. Rather than just share it with one, I figured my blog is the perfect medium to share it with many. My response is below.

---

The kit is definitely capable of hosting multiple communities or virtual sites out of a single installation. Basically what it does is it discriminates a different “site” based on the server name used to address it. So to host multiple sites, you will need to have multiple domain names mapped to your server, or be able to discriminate them by subdomain (i.e. the servername in servername.domainname.org). Lets say you want to host ClubAAA and ClubBBB as distinct sites from a single installation. ClubAAA and ClubBBB will have to each have their own domain name or subdomain name, mapped to your server. Then when users come into http://clubaaa.org/default.aspx they see one site, and when they come in to http://clubbbb.org/default.aspx, they see another site, even though those two domain names are mapped to the same virtual directory in IIS, the directory where the CSK was installed. Or they could come in as http://clubaaa.hostingdomain.org and http://clubbbb.hostingdomain.org and those two could be mapped to the same installation folder in IIS.

 

Within the kit, you create two communities using the ISPAdmin interface, which will be at http://localhost/CommmunityStarterKit/ISPAdmin/default.aspx with a default installation. The key thing is to have the domain or subdomain names different. You can play around with this by adding a second community on the local machine. Have one of the communities mapped to a primary and community domain of localhost, and have the second mapped to a primary and community domain of 127.0.0.1. Because the server name part of the URL will be different when you address these two ways, the kit will see them as distinct domains and thus they can be used to discriminate different communities.

 

You can then go tweak the settings for one domain’s appearance to immediately see the effect. Log into the first community (http://localhost/CommunityStarterKit/default.aspx) with the admin name and password, and go to the Admin interface. Select the Edit Sections option, and select the Appearance tab at the top. Change the theme and style to a different named theme than the default Lunar one. Save the changes and return to the site. You should see a different theme. Now change the address in the URL of the browser to http://127.0.0.1/CommunityStarterKit/default.aspx and you should see the old theme.

 

Once you have multiple communities set up like this, any changes made to one site or the other through its admin interface will be partitioned by the settings that get saved in the database based on the server name in the URL that you are using to access the site. Likewise any changes made to the site’s data (events, downloads, discussions, etc.) will be partitioned as well from a presentation perspective. In the DB itself, the data all lives in one set of tables intermixed. But the data is always linked to the community to which it belongs so that when it is rendered out through the engine to the UI, it looks to the user like they are accessing a separate physical site.

 



.NET | Community | Languages and Tools

Tuesday, April 13, 2004 2:04:08 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Thursday, April 8, 2004

VS 2005 CTP IIS problems fixed!

Thanks much to Josh for pointing me here which pointed here which gave the magic incantations and voodoo hex remover to fix the problem I was seeing with IIS after install of VS 2005 CTP.



.NET | Languages and Tools

Thursday, April 8, 2004 12:15:21 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, April 4, 2004

TDD in the real world... for real?

I like Test Driven Development (TDD). It makes sense to me at a conceptual level, it feels right, and it basically formalizes a number of practices I have had for years (but without the discipline to necessarily do it the same way all the time). I think it leads to better software both through finding defects earlier and because it changes the way you approach coding in a good way that makes you think about the client API very closely up front (because your tests are client code).

The one thing I don't like or really just haven't gotten my arms around yet is how to really apply it comprehensively across all the kinds of development I do. For business objects that encapsulate some data and expose operations on that data, TDD is perfect and easy to understand. For things like asynchronous, event-driven services and interactive UI code, I still have a hard time figuring out how to apply TDD.

So when I finally got around to reading the latest MSDN, I was looking forward to the article in there on TDD. I found the article to be well written and thought it did a great job explaining the basics and how to put together TDD test fixtures in .NET and work with NUnit. I was a little dissatisfied with the finish though.

As I read, I started salivating as I got to the section titled “Using TDD in the Real World”. Cool, someone is finally going to go beyond talking about money classes as demonstrate using TDD for something hard... or maybe not. Then it started talking about addressing GUI testing, even better... or maybe not. In the end, the “real world” scenario ended up being a combo box driven by a simple data container class for countries, and the only thing that TDD was demonstrated against was the country list class. Hardly a real world scenario, and how you might test the combo box that uses it was quickly slipped around.

Does anyone out there have any good resource links to using TDD for GUI and/or asynchronous/event-driven scenarios? That is the one area I still need a better clue, but I can't seem to find any good examples or discussion of them.



Architecture | Languages and Tools

Sunday, April 4, 2004 1:09:48 AM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Sunday, March 28, 2004

Side by Side VS.NET 2003 and 2005 CTP

Just for grins, I tried installing VS.NET 2003 and VS.NET 2005 CTP side by side in a virtual machine. I was pleasantly surprised with the results. They both installed fine and seem to run well on their own. Haven't tried any heavy development with either yet, so the true verdict is still out.

Of course, the problem noted in my previous post about IIS management console being broken is even more pronounced in this configuration, because you can't run the integrated debugger for web projects either. You will get an error that says VS can't launch the debugger. I was still able to run the web app and attach the debugger manually though.

Obviously not a recommended approach for a production development box, especially if you are developing web apps, but it was still a much more seamless attempt than when I tried the same with the PDC bits.



.NET | Languages and Tools

Sunday, March 28, 2004 5:24:30 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 

VS.NET 2005 CTP Breaks IIS

Found an unfortunate little side effect of installing the Community Technical Preview (CTP) of Visual Studio.NET 2005 (Whidbey) - IIS management console goes stupid and can no longer display properties of web sites. Good thing Whidbey no longer uses IIS for debugging on the local machine...



.NET | Languages and Tools

Sunday, March 28, 2004 5:19:11 PM (GMT Daylight Time, UTC+01:00)
Comments [0]  | 


 # Saturday, March 27, 2004

VS.NET 2005 Tech Preview 2 Install Complete

I got VS.NET 2005 Tech Preview installed easily. The only hitch - you have to remove the 1.2 version of the framework that the previous tech preview installed.... and Yukon depends on that version of the framework. Hmmm. So no more working with Yukon until they come out with another beta?



.NET | Community | Languages and Tools

Saturday, March 27, 2004 7:11:13 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Sunday, March 21, 2004

Code Expansion in VS.NET Whidbey - Good as QuickCode.NET?

I've been a big fan of QuickCode.NET since it first came out. At $29 a pop, well worth it for the amount of typing it saves me when coding. I have code expansion templates defined for common/tedious tasks such as defining type safe collection classes, adding event accessors to classes to encapsulate event members in C#, and even simple starter chunks of code like adding the block of code to declare an OpenFileDialog and check the return result before accessing the FileName property. I'd much rather type about 10 characters to do that than several lines of code, even with intellisense to help out with each of those lines.

For example, with QuickCode and one of my templates, I can type the following:

coll CustomerALT-Q

and I get a fully implemented type safe collection class with all the Add, Remove, IndexOf, Indexer, etc. members defined on it to only take Customer objects and store them through the CollectionBase class.

Likewise I can type

evtacc EventHandler MyEventALT-Q

And I get a member delegate of type EventHandler and a C# event accessor encapsulating it properly and exposing it as an event named MyEvent.

QuickCode has a nice little editor and runs within VS.NET as an Add-in, and lets you manage the individual templates and copy them to the clipboard as XML and import them from an XML file. You can also add modifiers to the template to help with camel or Pascal casing the emitted variables. All very sweet and easy to work with.

If you use QuickCode.NET and want me to send these to you by the way, just send me an email at brian.noyes@idesign.net.

Now (unfortunately for the vendor of that product), there will be Code Expansion as part of the refactoring support in VS.NET Whidbey. I like the idea of having it integrated with the other refactoring features in Whidbey, and it will be extensible to allow you to define your own expansions through XML files.

I haven't had a chance to use the code expansions a lot in Whidbey yet, and don't know what the final UI will be like for activating them and defining custom templates. Right now the templates all sit in a single XML file down under the VC#\ExTemplates folder, and as far as I can tell, there is no UI for defining your own. I don't know if this will change. If not, I guess the third party vendors still have an opportunity to add value by providing a nice UI for editing the templates and maybe import and export them for backup purposes (which I have found very important with QuickCode for when I rebuild my machine - a regular occurrence).

On one hand I like it when features like this are incorporated into VS.NET because I don't have to go locate and buy a bunch of additional tools once the product comes out to become fully productive in the environment. On the other hand, it is a little bit of a shame to see nice little niche's that vendors have filled with a product evaporate from under them.

As long as the implementation in VS.NET is as good or better, I'll be happy in the long run. But the jury is still out until I see what the final surrounding support set is.



.NET | Languages and Tools

Sunday, March 21, 2004 11:03:16 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, March 17, 2004

Prefer XPathNavigator

I spoke last night at the Central Pennsylvania Users Group in Harrisburg, PA. They have a great group and about 35 folks turned out despite snow and nasty weather. Judy Calla is the group lead and gave a nice little beginners talk on debugging and error handling in .NET applications. I then jumped in with a talk on querying XML data in .NET.

One of the key points I always try to draw out in that talk is to get people familiar with the XPathNavigator model and the differences between the various types of XML documents in .NET (XmlDocument, XmlDataDocument, XPathDocument).

It is a natural fit for people who have worked with MSXML before to settle in and use the XmlDocument class (the W3C DOM implementation in .NET), never going beyond the methods and properties exposed by XmlNode and its derived classes to do their work.

However, I try to get people familiar with the fact that the preferred model for working with XML data in memory in .NET is working through the XPathNavigator, since it can be used across all three of the document types, and especially since it will take on an even more significant role in .NET 2.0 with the introduction of the modifiable XPathDocument. More on that in a minute. I also point out that you can layer an XPathNavigator implementation on top of any hierarchical data that you control, giving it an XML like working model, even though it may have nothing to do with XML itself.

The XPathNavigator base class ( and the concrete implementations provided  by each of the document types) provides a consistent and clean model for navigating and querying XML data. To get one, you just call CreateNavigator on the underlying document instance. What you get back is effectively a cursor into the document nodes that you can move around with the various MoveXXX methods, or you can query the current node and all sub-nodes with XPath expressions. When you query through this model, you have the choice of just passing an XPath expression as a string to the Select or Evaluate method (the former returns a node set result, the latter returns a value result - bool, number, string - if that is what the XPath expression is expected to evaluate to), or you can pre-compile the expression for faster execution if the query will be made more than once.

The XPathDocument class in .NET 1.X is a lighterweight object model than the one in the XmlDocument class and will have less of a footprint in memory for the same XML document in most cases. The big decision point in which of those two document types to pick currently is whether you need write access to the nodes you are dealing with. If the answer is yes, you only have one choice currently, and that is to work with the XmlDocument class. You can and still should do so through an XPathNavigator, but the underlying nodes are still XmlNodes instead of XPathNodes, and are therefore write access. If you are just looking to query and navigate the data to perform processing, then XPathDocument is the better choice because of the lighter weight object model.

In .NET 2.0, the big thing to be aware of is that the XPathDocument class becomes read/write. But more important than that is that any changes you make to the document (modifying, inserting, or deleting nodes) are tracked by the document in a similar fashion to the way the DataSet tracks changes. This means that you can then use the XPathDocument to perform updates to the underlying data store from whence it came. That is huge.

So bottom line, if you are not using XPathNavigator today for working with your XML documents in .NET, you should be. Look into and get used to the model. It will give you better consistency and a migration path to move you XML document processing code from the DOM today to the XPathDocument in .NET 2.0 with minimal changes.



.NET | Architecture | Languages and Tools

Wednesday, March 17, 2004 12:54:29 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Monday, January 26, 2004

My .NET Rocks! Show is online

That moment of trepidation is past. My .NET Rocks! interview is live, and I think it came out pretty well. Checked it out this morning, and at least there was nothing where I was horrified by the way I answered or came across in the end product.

There were of course a number of things that I felt I could have explained better, most of which I thought of 5 minutes after we were done taping, but that is standard for any live unscripted thing like .NET Rocks! In fact, I think that is one of the things I enjoy about .NET Rocks! as a listener, is the fact that it is unscripted, so the conversatioon can take many unexpected turns.

The one “duh, stupid” that I thought of right after the discussion was the question on remoting and had I been looking at what was new there in Whidbey... you would think the Indigo workshop I attended in Redmond a few months ago would have jogged my memory  as to what the remoting story is in Whidbey... it's called Inidigo, and its not part of Whidbey. They are not going to invest any time enhancing or modifying a remote communications protocol that will be subsumed by Indigo a year or so later. Oh, well, those thinking on my feet marks go down a little on that one.

Anyway, it was a cool experience to get on the show, especially since it is getting so big and well known. Thanks to Carl for having me on, and I'll enjoy listening to Carl and Rory on all the future shows.

Carl: Great idea on the live show this Friday, but make sure to tape it still for us offline listeners!



.NET | Community | Languages and Tools

Monday, January 26, 2004 1:12:38 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Tuesday, January 6, 2004

Starting a new book

Just signed a contract with Addison-Wesley to write a book on building data-driven Windows Forms applications with .NET 2.0. Main focus will be on all the new data-bound controls in WinForms 2.0. Lots of really cool stuff there to talk about.

With that and my asp.netNOW DataStream column, my Data and Desktop column in C#Pro, and one other possible book project, I think it is going to be a busy year of writing.

Maybe I should go off to Cayman for a few months to focus... Yeah, that's the ticket. Not make any money consulting, make nothing for one column, little for the other, and maybe someday make a few bucks from the book... sounds like a winning business plan to me.

Should be fun though, I'm looking forward to the experience and hope to deliver the definitive story on data binding for rich client apps in .NET 2.0.

If you have ideas of things you think will be key aspects to cover, please let me know. You might expect to see some posting in the future having something to do with the topic...



.NET | Languages and Tools

Tuesday, January 6, 2004 1:22:25 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, December 24, 2003

Never say Never - why extensibility is a good thing

I had one of those great “I told you so” moments with a consulting customer today. About a month ago, I recommended using the Exception Management Application Block (EMAB) for publishing their exceptions because of the ease of use and extensibility it offered. If you are unfamiliar, the EMAB lets you publish exception information in a catch block to any number of publishers with a single line of code:

catch (Exception ex)
{
ExceptionManager.Publish(ex);
}

Through the config file, you can then wire up zero to many publishers such as the built in Windows Event Log publisher, an XML file, a database, email, and so on. You can modify where the exception information gets published anytime without changing anything but the config file. You can create your own custom publishers and plug them in very easily as well.

So what I had proposed was to create a custom publisher that would log any exceptions to their existing application event log, which is just a SQL Server table that their monitor application accesses, with all the details that come along with the exception (message, stack trace, target, user, date time, etc.). The customer balked because they were intimidated by the block and thought it was too complex for their needs. “We never need to publish anywhere except our event log, and we already have code that does that”. Uh-huh, sure. Never huh?

Today the customer stumbled down a dark and windy road of synchronization nightmares due most likely to a shared data object class that was being hammered on by multiple threads and didn't have complete and safe synchronized access to its members. “Everything worked great in debug mode,  but when we run in release mode, it blows up right away with a null reference exception.”

Oh great, I love these. Where is it blowing up exactly, I asked? “We don't know, we didn't have room in the database fields for the full stack trace, so we just left that out.” Mmm. OK. Brute force time. Lets insert a trace statement in the exception handler to dump the context so we can see what is going on. Oh goody, just inserting trace statements in the method where it is occuring makes the problem go away. Surely no race condition here.

Then the customer ponders - “how can we get more information out about the exception if the exception goes away when we add more code to dump it?” Exactly. Wouldn't it be nice to just wire up a different publisher right now that can dump the full exception - type, message, stack trace, etc. - to an XML file or somewhere else for analysis without having to modify the code. Why yes it would.

Extensibility is your friend, especially when someone else (thank you Microsoft) has implemented it for you. I am absolutely against speculative design. But you also have to be realistic about things that might need to change after you ship and make allowances for them. If there are things you can use like the Exception Management Application Block, or any of the other applications blocks that give you an extensible design that just requires a little extra up front complexity to integrate, think seriously about what it might buy you down the road. We probably could have tracked down the exact cause of the problem today quickly if we just had complete information about the exception. And that information could have been easily obtained, even in release mode, without changing a line of code, if they had used the EMAB instead of a home grown, non-extensible solution.



.NET | Languages and Tools

Wednesday, December 24, 2003 12:24:17 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


 # Wednesday, October 29, 2003

Role Reversal?

I attended an event yesterday at PDC where a member of the C++ product team was discussing the new features for C++ in Whidbey. He kept repeatedly emphasizing that C++ developers are the smartest and most talented developers in the world. There was something oddly familiar about the way he kept defending his existence as a programmer that was feeling sort of deja vu-like.

Then it dawned on me - it seemed an awful lot like in the past when I have heard VB developers getting defensive about their language and their skills when they were around C++ developers, or more recently, VB.NET programmers around C# programmers. It takes on a whiny “no, I'm important, REALLY!!!! Come on, guys!” sort of sound after awhile.

Don't get me wrong, I'm no laguage bigot. I'm primarily a C++ background, with my language of choice being C# these days. I think you should choose whatever language makes the most sense for the task and your skill set. .NET has done an amazing job of leveling the playing field with that respect.

I do sort of question the productivity of using C++ in the managed world though. There are certainly many specialized tasks where C++ has power that the other languages may not. But as always, with power comes responsibility to not misuse it, which is where so much productivity has been lost in the past - chasing down those mis-uses and fixing them.

I just found it amusing (even as a C++ guy myself) to see that C++ guys are having to justify their existance so vigorously in the face of the adoption of C# and VB.NET for the bulk of .NET development.



Languages and Tools

Wednesday, October 29, 2003 10:21:45 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


















May, 2013 (2)
April, 2013 (2)
March, 2013 (2)
February, 2013 (2)
January, 2013 (2)
December, 2012 (3)
November, 2012 (1)
October, 2012 (1)
August, 2012 (2)
June, 2012 (2)
May, 2012 (3)
April, 2012 (1)
March, 2012 (2)
February, 2012 (2)
January, 2012 (1)
November, 2011 (4)
October, 2011 (1)
September, 2011 (2)
August, 2011 (1)
July, 2011 (1)
May, 2011 (5)
March, 2011 (4)
February, 2011 (2)
January, 2011 (3)
November, 2010 (4)
October, 2010 (1)
September, 2010 (5)
August, 2010 (5)
July, 2010 (6)
June, 2010 (8)
May, 2010 (2)
April, 2010 (2)
January, 2010 (1)
December, 2009 (3)
November, 2009 (2)
October, 2009 (3)
September, 2009 (3)
August, 2009 (2)
July, 2009 (3)
May, 2009 (3)
April, 2009 (2)
March, 2009 (1)
February, 2009 (2)
January, 2009 (2)
December, 2008 (1)
November, 2008 (2)
October, 2008 (5)
September, 2008 (4)
August, 2008 (2)
July, 2008 (1)
June, 2008 (2)
May, 2008 (2)
April, 2008 (3)
February, 2008 (6)
January, 2008 (3)
December, 2007 (1)
November, 2007 (1)
October, 2007 (5)
September, 2007 (1)
July, 2007 (3)
June, 2007 (8)
April, 2007 (2)
March, 2007 (4)
February, 2007 (1)
December, 2006 (2)
November, 2006 (9)
October, 2006 (5)
September, 2006 (3)
August, 2006 (2)
July, 2006 (4)
June, 2006 (5)
May, 2006 (10)
April, 2006 (4)
March, 2006 (2)
February, 2006 (12)
January, 2006 (7)
December, 2005 (2)
November, 2005 (15)
October, 2005 (6)
September, 2005 (7)
August, 2005 (3)
July, 2005 (10)
June, 2005 (11)
May, 2005 (7)
April, 2005 (8)
March, 2005 (6)
February, 2005 (2)
January, 2005 (6)
December, 2004 (3)
November, 2004 (5)
October, 2004 (2)
September, 2004 (5)
August, 2004 (13)
July, 2004 (6)
June, 2004 (14)
May, 2004 (17)
April, 2004 (12)
March, 2004 (8)
February, 2004 (10)
January, 2004 (14)
December, 2003 (9)
November, 2003 (13)
October, 2003 (3)

Sign In
Copyright © 2006-2012 Brian Noyes. All rights reserved.

designed by NUKEATION STUDIOS