|
|
These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.
October 2006 - Posts
-
I've blogged several times in the past about how cool IIS 7.0 is. Many of my posts have highlighted some of the rich new ASP.NET and .NET developer opportunities it brings (integrated pipeline, unified web.config configuration, integrated admin tool experience, etc). It is really going to open up huge developer opportunities and provide an immensely customizable web-server for people to use. In addition to focusing on .NET developer features, we are also working hard to enable non-.NET development stacks to easily integrate with the web server. Earlier today Bill Staples (who runs the IIS team) demoed a great new FastCGI module for IIS7 at the ZendCon PHP Conference being held this week: We've been working closely with Zend this past fall on improving PHP support on top of IIS, and with this new module PHP developers will be able to get dramatically better performance, scalability and reliability when running on Windows (sometimes as much as 25x faster than the old PHP CGI module for IIS). They'll also be able to easily integrate with the cool new IIS7 features that are coming (for example: take advantage of the new output caching features), as well as integrate nicely with ASP.NET. For example: You could have ASP.NET provide the membership and role management features for a site, while still writing many pages within it in PHP (since with IIS7 an ASP.NET HttpModule can execute for any request to the web-server, and so the Forms Authentication, Role Management and other features are no longer restricted to urls mapped to ASP.NET). To learn more about the IIS 7.0 FastCGI module and how to use it with PHP, make sure to check out Bill's great tutorial walkthrough here. Rick also has a great blog post about how the module works here. Also make sure to subscribe to Mike's blog and the www.iis.net blog feed here. Hope this helps, Scott

|
-
Eight new tutorials have been added to my Working with Data in ASP.NET 2.0 series. This latest batch of tutorials examines how to edit and delete data from the DataList control. These tutorials follow, in scope, the concepts discussed in the earlier edit/insert/delete-related tutorials that focused on the GridView, DetailsView, and FormView controls. These DataList-specific tutorials, however, do include a look at performing batch updates (a topic lacking from the GridView/DetailsView/FormView-specific ones). As always, each tutorial is available in both VB and C#, includes the full working code as a downloadable ZIP, and can be downloaded as a PDF for offline access.
When I started writing these tutorials I was slated to write 46 in total, and, to date, 43 of the 46 are up at http://www.asp.net/Learn/DataAccess/. (They are also being added to MSDN's website, but at a much more glacial pace.) Anywho, the good news is that I've signed on to author another 29 tutorials over the coming months, which will continue the series and be available at http://www.asp.net/Learn/DataAccess/ as they come online.
Here is the planned outline. The content to be covered is pretty much solidified, but there may be some slight modifications, reordering of sections/tutorials, and so forth. I've actually completed the “set” of tutorials on the SqlDataSource (the first four), and will start hammering out the next set this week, time permitting.
- Accessing Database Data Directly from an ASP.NET Page
- Querying Data with the SqlDataSource Control
- Using Parameterized Queries with the SqlDataSource
- Inserting, Updating, and Deleting Data with the SqlDataSource Control
- Implementing Optimistic Concurrency with the SqlDataSource
- Enhancing the GridView
- Adding a GridView Column of Radio Buttons
- Adding a GridView Column of CheckBoxes
- Inserting a New Record from the GridView’s Footer
- Working with Batched Data
- Batch Updating
- Batch Deleting
- Generating Multiple Details Records Which Copy Multiple Columns of Data From a Common Master
- Working With Binary Files
- Uploading Files
- Including a File Upload Option When Adding a New Record
- Displaying File Information in the Data Web Controls
- Changing the Uploaded File for an Existing Record
- Caching
- Caching Data with the ObjectDataSource
- Caching Data at the Business Logic Layer
- Using SQL Cache Dependencies
- Caching Data at Application Startup
- Data and the Site Map Provider
- Building a Custom Database-Driven Site Map Provider
- Advanced Data Access Layer Scenarios
- Having the Typed DataSet Create Your Stored Procedures
- Integrating Existing Stored Procedures with the TableAdapter
- Techniques for Performing JOINs
- Adding Additional DataTable Columns
- Working with Computed Columns
- Configuring Connection- and Command-Level Settings in the DAL
- Wrapping Database Modifications in a Transaction
- Debugging Stored Procedures
- Protecting connection strings
- Creating SQL Functions and Stored Procedures with Managed Code
|
-
A few people have asked me for a working web site with some of the code from my MasterPage: Tips, Tricks, and Traps article. This download is a web site based on the ASP.NET Personal Web Site Starter Kit and provides a number of the samples from the article.
Samples include a master page base class, and an HttpModule to assign the MasterPageFile property for .aspx web forms at runtime. There is an example of content page to master page interaction through a strongly typed Master property, and an example of master page to content page interaction via an event.

|
-
Luis Abreu is an ASP.NET MVP who has a great blog on the http://msmvps.com blog site. Earlier today he posted a great tutorial post that describes how to use some of the new features in the ASP.NET AJAX Beta1 release to add more robust error handling into your application. I highly recommend reading and bookmarking it for future use. Error handling in an AJAX world can often be tricky -- especially when AJAX call-backs are taking place and a mixture of client and server code is running within an application. In its most recent release, the <asp:updatepanel> control that comes with ASP.NET AJAX now has much more robust error handling and reporting features for you to use. Specifically: 1) You can now handle the "OnAsyncPostBackError" event on the <asp:scriptmanager> control to catch and/or modify an error message that occurs during the processing of an AJAX postback callback on the server. 2) You can now set the "AllowCustomErrors" property on the <asp:scriptmanager> control to enable the standard ASP.NET custom error support to be enabled to redirect a user automatically to an error page when an error occurs (even if it is happening during an AJAX postback). 3) You can now optionally handle client-side JavaScript events on the page to intercept any error message sent back from the server, and perform custom client-side actions as a result (for example: to output the error message to a nicely formatted <div> section instead of performing a pop-up message). Read all about how to take advantage of the above new features from Luis' great tutorial here. Hope this helps, Scott

|
-
I am working on a little side project that happens to be a smart client application and I have gotten around to working out how to deploy and update the application. I have used the Application Updater block in the past and it worked out well, but that is supposed to be replaced by ClickOnce in .NET 2.0. So I started looking into ClickOnce but didn’t really like what I found.
I don’t want to deploy the application directly from the web. I want to have the user download and install an .msi file (or execute it from a CD, etc). This gives me more flexibility into what is installed (I need to switch some resource file settings, etc). More importantly this application is targeted at people who are not very computer savy, so the extra warnings that come with ClickOnce web deployment would scare or confuse them. There are also some limitations around Firefox support (which have been partially alleviated, but still complicate things).
All I really want is something to perform automatic updates, and as far as I can tell there isn’t a way to use the ClickOnce automatic updates framework without deploying your application using ClickOnce.
This is where ClickThrough comes to the rescue. ClickThrough is an extension to the WiX toolkit that makes it very easy to update applications on the fly, similar to the Application Updater Block, but actually uses an RSS feed to check for updates! Its part of WiX v3 which means it is still under development, but I am going to give it a shot anyway.
I haven’t actually gotten it all working yet, but so far it looks very promising.
-James 
|
-
I just added my first article (well, it’s just a stub right now) to Wikipedia. While doing some vanity googling (still beating Uncle Phil) I read about a sailor named James Avery who received the medal of honor during the Civil War. I couldn’t find much about the rest of his life, but hopefully I will un-cover some stuff while digging through the library and can improve the stub.
I forgot to add the stub tag, but 2 minutes after I added it someone else did it for me. (A 16–year old from England no less) Wikipedia is a wonderful thing.
You can check it out here.
-James 
|
-
I've blogged in the past about the great CSS Control Adapters that Russ and Heidi have been working on. These adapters use a new built-in extensibility mechanism in ASP.NET 2.0 called "control adapters" that allow you to plug-in into any ASP.NET server control and override, modify and/or tweak the rendering output logic of that control. The control adapters that Russ and Heidi built provide a pure CSS based rendering (no tables) for all of the ASP.NET Data (GridView, DataList, DetailsView, FormView, etc), Navigation (Menu, TreeView), and Login (Login, CreateUserWizard, ChangePassword, PasswordRecovery, LoginStatus) controls. You can learn more about them and how to use them with your projects from my past tutorial blog post here. Beta3 CSS Control Adapters Release Earlier this week we published the "Beta3" version of the CSS Control Adapters which incorporates more feedback and suggestions, along with a number of new features. Here are some shortcuts to a few cool new highlights: - Go to the Menu sample. Increase your browser's font size. In Internet Explorer use View > Text Size > Larger.
- Go to the CreateUserWizard sample. Navigate with accesskeys. If using Windows, press Alt + e to set the focus to the textbox for the Email address. (In Internet Explorer you must also hold down the Shift key to use the accesskey for the password textbox.)
- Try out the redesigned TreeView sample. Expand several nodes in the tree. Select a node to cause the page to post back. Notice that the tree maintains its expansion, visibly marks the selected node and uses its value to change the page's sample content.
- Play with cascading checkboxes.
- Validate that these pages conform to the XHTML 1.1 Strict standard.
You can learn more and download the free CSS Control Adapters (including both VB and C# versions of the source) from this web-site: http://www.asp.net/cssadapters Hope this helps, Scott

|
-
I decided to give hiddennetwork.com a try and start hosting a job board and job advertisements on my blog. Job boards seem to be all the rage these days and blogging has helped me find some of the best members of our current team. It’s usually the people reading blogs that are passionate about technology and writing code (which are the type of people I always try to hire).
Check out the ads to the right if you are looking for a new job, or if you are an employer you should definitely look into posting your job reqs with hiddennetwork.com.
-James 
|
-
I found a number of folks using a MacBook Pro for .NET Development:
Visual Studio.NET development on OS X w/ Parallels
Anyone using Visual Studio in Parallels on a MacBook Pro? (lots of good comments here)
A few weeks with a MacBook Pro, Parallels, and MSDN Universal
But in the end I decided I wasn’t ready to make “the switch” just yet for a number of different reasons:
- I do almost 100% .NET development
- I don’t want to lose the max power of my hardware while writing code, even though it might be 90% it is still only 90%. (Also it doesn't appear that you can use multiple monitors with Parallels or take advantage of both cores in a dual core)
- I don’t want to deal with the fact that I am a .NET consultant and would be walking into clients with a Mac. I am sure most wouldn’t care, but there are a number of people in the MS/.NET camp who would hold it against me. (I know that is a chicken-*** reason, but I make my money billing as a .NET consultant so I have to be mindful of it)
If I start doing more Ruby development, or become focused more on writing or other projects I might pick up a Mac for those purposes, but I won’t be replacing my main .NET development machine anytime soon.
-James
-James 
|
-
I'm very excited to have the opportunity to present at the North Dallas .NET User Group on November 2nd (next Thursday). I'm going to speaking for a little over 2 hours on a variety of fun topics. My plan right now is to spend the first hour doing a brand new ASP.NET Tips and Tricks talk, and then spend the second hour doing a deep dive into the new LINQ technology that we are shipping next year (and which will dramatically improve data productivity). The event is totally free to attend. I hope to see some of you there! Scott P.S. The following week I'll be presenting 2 keynotes and 2 breakout sessions at the ASP.NET Connections Conference in Las Vegas.

|
-
Now that the Core Duo 2 MacBook Pro is available I am seriously considering picking one up. I was checking out Jim Weirich’s setup at work (yeah, that Jim Weirich) and I was surprised how well XP runs in Parallels. Anybody else out there do some serious development with this kind of setup?
-James

|
-
Joe Developer is working with a simple struct:
struct Point
{
public int x;
public int y;
}
Joe's tech lead asked him to write a method that will return an array of 10,000 initialized points. Joe wrote following code.
Point[] CreatePoints()
{
Point[] points = new Point[10000];
for (int i = 0; i < points.Length; i++)
{
points = new Point();
}
return points;
}
The code doesn't create any runtime errors, but Joe is worried because
his tech lead looked at the code and frowned. What could provoke such a
reaction?
Hint: Joe's lead is a performance nut.

|
-
As noted before I was NOT renewed as an MVP this year, so I was surprised to get a letter today that said the following: "On behalf of the East region, we want to say Congratulations! for your recent award as a Microsoft Most Valuable Professional (MVP) in Visual Developer - ASP/ASP.NET . . . ." I don't think my status has changed, nor should it, but apparently someone at Microsoft believes differently for some reason.

|
-
There is a queuing infrastructure in Windows Workflow that facilitates
communications between workflows and the outside world. Event related
activities, like the HandleExternalEvent and Delay activities, provide
a formalized layer of abstraction over this queuing infrastructure. You
might never need to know that a queuing service exists if you can get
100% of the job done with components from the base activity library.
If you need more flexible messaging, or like Harry, want to work with
a low level API, you can use the queuing service to create queues and
en-queue messages for your own purposes. Before jumping in, it's
worthwhile to study how the built-in activities make use of workflow
queues, particularly workflow queue names. 
If we look at the correlated local service example in the Windows SDK,
we'll find a Parallel activity with two sequences inside. Both
sequences call a CreateTask method and expect a TaskCompleted event to
arrive. A local service we've implemented has to raise this
TaskCompleted event, but the event isn't delivered directly to the
running workflow. Instead, the workflow runtime catches the event. The
workflow instance might be unloaded from memory and living as a
serialized blob in a database table. The runtime will reload the proper
workflow and deliver the event.
If there are multiple workflow instances active, it's easy for the
runtime to find the right instance because of the InstanceId property
on all incoming event arguments (local service communications might
define event arguments that derive from the ExternalDataEventArgs
class).
But how does the workflow know what activity is waiting for the event?
This isn't hard if there is only one activity waiting for an event, but
in this sample we have two activities both waiting for the same event
from the same service.The secret is in the workflow queue names the individual activities
create to wait for the events. If we use GetWorkflowQueueData on the
workflow instance, we can inspect the queue names. A queue name in the
this SDK sample will look like the following:
Message Properties
Interface Type:ITaskService
Method Name:TaskCompleted
CorrelationValues:
001
What we see is that the workflow queue "name" actually contains all
of the information the runtime needs to deliver events to their proper
destination. The name includes the interface and event name, as well as
correlation values when the associated activities have correlation
tokens.
Queue names in windows Workflow are more than just friendly
identifiers. As Harry pointed out, they implement IComparable and are
actually a key piece to how Windows Workflow works with data exchange
services. 
|
-
I've been having some fun playing around with the ASP.NET AJAX Beta release this weekend. Usually when I integrate AJAX functionality into my code I just end up using the built-in server controls that ASP.NET AJAX provides (UpdatePanel, UpdateProgress, etc) and the cool controls in the ASP.NET AJAX Control Toolkit. Scott Hanselman had jokingly called using these AJAX controls "cheating" when he interviewed me two weeks ago for his latest podcast - since they don't require that you write any client-JavaScript for most common scenarios. This weekend I decided to focus my coding on some of the client JavaScript pieces in the ASP.NET AJAX framework that don't use UpdatePanels at all, and to experiment with alternative ways to use the server to easily generate HTML UI that can be dynamically injected into a page using AJAX. In the process I created what I think is a pretty useful library that can be used with both ASP.NET AJAX and other AJAX libraries to provide a nice template UI mechanism with ASP.NET, and which doesn't use or require concepts like postbacks or viewstate - while still providing the benefits of control encapsulation and easy re-use. First Some Quick Background on the JavaScript Networking Stack in ASP.NET AJAX To first provide some background knowledge about the client JavaScript library in ASP.NET AJAX before getting to the template approach I mentioned above, lets first walkthrough building a simple AJAX "hello world" application that allows a user to enter their name, click a button, and then make an AJAX callback to the server using JavaScript on the client to output a message: ASP.NET AJAX includes a very flexible JavaScript network library stack with rich serialization support for .NET data-types. You can define methods on the server to call from JavaScript on the client using either static methods on your ASP.NET Page class, or by adding a web-service into your ASP.NET application that is decorated with the [Microsoft.Web.Script.Services.ScriptService] meta-data attribute and which exposes standard [WebMethod] methods. For example, below is a SimpleService.asmx web-service with a "GetMessage" method that takes a string as an argument: using System; using System.Web.Services;
[Microsoft.Web.Script.Services.ScriptService] public class SimpleService : WebService {
[WebMethod] public string GetMessage(string name) { return "Hello <strong>" + name + "</strong>, the time here is: " + DateTime.Now.ToShortTimeString(); } } ASP.NET AJAX can then automatically create a JavaScript proxy class to use on the client to invoke this method and pass appropriate parameters to/from it. The easiest way to add this JavaScript proxy class is to add an <asp:ScriptManager> control on the page and point at the web-service end-point (this control also does the work to ensure that each library only ever gets added once to a page). I can then call and invoke the method (passing in a value from a textbox), and setup a callback event handler to fire when the server responds using client-side JavaScript code like below. Note: I could get fancier with the JavaScript code to eliminate some of the lines - but I'm deliberately trying to keep it clear and simple for now and avoid adding too much magic: <html> <head id="Head1" runat="server"> <title>Hello World Service</title> <link href="StyleSheet.css" rel="stylesheet" type="text/css" /> <script language="javascript" type="text/javascript"> function callServer() { SimpleService.GetMessage( $get("Name").value, displayMessageCallback ); } function displayMessageCallback(result) { $get("message").innerHTML = result; } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" > <Services> <asp:ServiceReference Path="~/SimpleService.asmx" /> </Services> </asp:ScriptManager> <h1>Hello World Example</h1> <div> Enter Name: <input id="Name" type="text" /> <a href="BLOCKED SCRIPTcallServer()">Call Server</a>
<div id="message"></div> </div> </form> </body> </html> Now when I run the page and enter a name "Scott", the page will use AJAX to call back and dynamically update the HTML of the page without requiring any postbacks or page refreshes. A cleaner approach to generate HTML using templates As you can see from the example above, I can easily return HTML markup from the server and inject it into the page on the client. The downside with the approach I am taking above, though, is that I am embedding the HTML generation logic directly within my server web method. This is bad because: 1) it intermixes UI and logic, and 2) it becomes hard to maintain and write as the UI gets richer. What I wanted was an easy way to perform my logic within my web service method, retrieve some data, and then pass the data off to some template/view class to generate the returned HTML UI result. For example, consider generating a Customer/Order Manager application which uses AJAX to generate a UI list of customers like this: I want to write server code like below from within my WebService to lookup the customers by country and return the appropriate html list UI. Note below how the ViewManager.RenderView method allows me to pass in a data object to bind the UI against. All UI generation is encapsulated within my View and out of my controller webmethod: [WebMethod] public string GetCustomersByCountry(string country) { CustomerCollection customers = DataContext.GetCustomersByCountry(country);
if (customers.Count > 0) return ViewManager.RenderView("customers.ascx", customers); else return ViewManager.RenderView("nocustomersfound.ascx"); } It turns out this wasn't too hard to enable and only required ~20 lines of code to implement the ViewManager class and RenderView methods used above. You can download my simple implementation of it here. My implementation allows you to define a template to render using the standard ASP.NET User Control (.ascx file) model - which means you get full VS designer support, intellisense, and compilation checking of it. It does not require that you host the usercontrol template on a page - instead my RenderView implementation dynamically cooks up a dummy Page object to host the UserControl while it renders, and captures and returns the output as a string. For example, here is the Customer.ascx template I could write to generate the customer list output like the screen-shot above which generates a list of customer names that have links to drill into their order history: <%@ Control Language="C#" CodeFile="Customers.ascx.cs" Inherits="Customers" %>
<div class="customers">
<asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <div> <a href="BLOCKED SCRIPTCustomerService.GetOrdersByCustomer('<%# Eval("CustomerID") %>', displayOrders)"> <%# Eval("CompanyName") %> </a> </div>
</ItemTemplate> </asp:Repeater>
</div> And its associated code-behind file then looks like this (note: I could add view-specific formatting methods into this if I wanted to): using System;
public partial class Customers : System.Web.UI.UserControl { public object Data;
void Page_Load(object sender, EventArgs e) { Repeater1.DataSource = Data; Repeater1.DataBind(); } } For passing in the data to the template (for example: the customers collection above), I initially required that the UserControl implement an IViewTemplate interface that I used to associate the data with. After playing with it for awhile, though, I instead decided to go with a simpler user model and just have the UserControl expose a public "Data" property on itself (like above). The ViewManager.RenderView method then does the magic of associating the data object passed in to the RenderView method with the UserControl instance via Reflection, at which point the UserControl just acts and renders like normal. The end result is a pretty powerful and easy way to generate any type of HTML response you want, and cleanly encapsulate it using .ascx templates. Finishing it Up You can download the complete sample I ended up building here. Just for fun, I added to the above customer list example by adding support for users to click on any of the customer names (after they search by country) to pop-up a listing of their orders (along with the dates they placed the order). This is also done fully with AJAX using the approach I outlined above: The entire application is about 8 lines of JavaScript code on the client and a total of about 15 lines of code on the server (that includes all data access). All HTML UI generation is then encapsulated within 4 nicely encapsulated .ascx template files that I can load and databind my data to from my webmethods on demand: Click here to download the ViewManager.RenderView implementation if you want to check it out and try it yourself. Hope this helps, Scott

|
-
I had the requirement to create a splash screen recently and did some quick searching to see what the recommended method was in .NET and Windows Forms. I found a number of large code samples, controls you can download, but everything seemed too complicated. It shouldn’t be that hard. Then I ran across Eric Gunnerson’s blog post which recommends simply loading the screen in the constructor of your form and then closing it in the Activated event. It’s incredibly simple and works perfectly.
-James 
|
-
We are using NHibernate on a big project at work and one of the optimizations we often find ourselves making is creating a “lighter” object and returning that instead of our full objects for searches and other operations where we return a large number of the same object. This also applies to searches that display fields from a hand-full of objects, for instance you might show a Customer’s first name, last name, their primary address line 1, address zip code, and the date of their last order. You wouldn’t want to return all of these objects and display just the pertinent information, you want to just get the information you are going to show. Especially on search screens that are heavily used throughout the system.
The other day I noticed that in many of our data access calls we were doing something like this: (mocked up code)
1 public List<CustomerResult> GetCustomerSearchResults(CustomerCriteria cc)
2 {
3 using (Repository repository = new Repository())
4 {
5 StringBuilder hql = new StringBuilder();
6 hql.Append("SELECT c.Name, c.Phone,
c.PrimaryAddress.Line1, c.LastOrderDate ");
7 hql.Append("FROM Customer AS c");
8
9 IList result = repository.Session.CreateQuery(hql.ToString())
10 .List();
11
12 List<CustomerResult> results = new List<CustomerResult>();
13 foreach (object[] row in tempList)
14 {
15 CustomerResult result = new CustomerResult();
16 result.Name = row[0].ToString();
17 result.Phone = row[1].ToString();
18 result.Line1 = row[2].ToString();
19 result.LastOrderDate = row[3].ToString();
20 results.Add(result);
21 }
22 }
23
24 return results;
25 }
Technically there isn’t anything wrong with this code (I have omitted null checks, etc for brevity) but it could be much more elegant. A little known feature of HQL is the ability to construct and return a new object as part of the statement, the above HQL becomes “Select new CustomerResult(c.Name, c.Phone, c.PrimaryAddress.Line1, c.LastOrderDate)”. The only requirements for this are:
1) The CustomerResult object needs to have a constructor that matches what is contained in your HQL.
2) If the class you are creating is un-mapped (like our CustomerResult object would be) then you need to Import the class in one of your mapping files. I created a ImportClasses.hbm.xml file for all of these imports:
1 <?xml version="1.0" encoding="utf-8" ?>
2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
3 <import class="CustomerResult, MyAssembly"/>
4 </hibernate-mapping>
My above code can now be refactored to the following:
1 public List<CustomerResult> GetCustomerSearchResults(CustomerCriteria cc)
2 {
3 using (Repository repository = new Repository())
4 {
5 StringBuilder hql = new StringBuilder();
6 hql.Append("SELECT new CustomerResult(c.Name, c.Phone,
c.PrimaryAddress.Line1, c.LastOrderDate) ");
7 hql.Append("FROM Customer AS c");
8
9 IList result = repository.Session.CreateQuery(hql.ToString())
10 .List();
11
12 return ConvertToGenericList(result);
13 }
14 }
Sure some of the code has just been moved to the constructor, but I find it much more readable and maintainable.
-James 
|
-
Last month I posted about the official new name for “Atlas,” and discussed the roadmap plan for shipping a free, fully-supported, v1.0 release that works on top of ASP.NET 2.0 and Visual Studio 2005. Today I am very pleased to announce the first official Beta release of Microsoft ASP.NET AJAX v1.0. You can download it now from the http://ajax.asp.net site. Available on the site are three download options: 1) The ASP.NET AJAX v1.0 “Core” download. This redist contains the features that will be fully supported by Microsoft Product Support, and which will have a standard 10 year Microsoft support license (24 hours a day, 7 days a week, 365 days a year). The download includes support for the core AJAX type-system, networking stack, component model, extender base classes, and the server-side functionality to integrate within ASP.NET (including the super-popular ScriptManager, UpdatePanel, and Timer controls). 2) The ASP.NET AJAX “Value-Add” CTP download. This redist contains the additional higher-level features that were in previous CTPs of “Atlas,” but which won’t be in the fully-supported 1.0 “core” redist. These features will continue to be community supported as we refine them further and incorporate more feedback. Over time we’ll continue to move features into the “core” download as we finalize features in this value-add package more. 3) The ASP.NET AJAX Control Toolkit. This project contains 28 free, really cool, AJAX-enabled controls that are built on top of the ASP.NET AJAX 1.0 “Core” download. The project is collaborative shared source and built by a combination of Microsoft and non-Microsoft developers, and you can join the community or just download it on CodePlex today. Some of the Changes with the Beta There are a number of changes that the team has made with this beta release. A few of the significant changes include: Performance and Download Size Optimizations Previous ASP.NET AJAX CTPs relied on the browser downloading a single large, JavaScript file to the browser that contained all of the features. With this Beta release we have spent a lot of time on factoring out features into multiple files (so you don’t have to download them unless you use them), and in optimizing the bandwidth size of the overall library. The ASP.NET AJAX “Core” download now includes two JavaScript libraries that are used to support all of its features: a) The MicrosoftAjax.js.gz script file contains the core JavaScript type-system, component/control model, JSON networking/serialization stack, and application-serviceas features (Profile + Authentication). It is now 14.8k in size. b) The MicrosoftAjaxWebForms.js.gz script file then adds the support to enable UpdatePanel scenarios and partial page rendering. It is 6.4k in size. These files are only downloaded by a browser once when visiting a site -- they are then cached on the client and reused across all pages and repeat visits. The new size targets should ensure a snappy and speedy experience the first time you hit a site. In addition to optimizing the initial download size of the JavaScript libraries, we have spent time optimizing the network traffic size of client JavaScript callbacks to the server. Controls like the UpdatePanel, UpdateProgress, and Control Toolkit controls no longer emit xml-script by default, and instead just emit 1-2 lines of JavaScript (which can help significantly reduce the network traffic size on the wire). We have also moved from using JavaScript closure-based classes to using prototype-defined classes in the core type system, which we’ve found reduces memory usage for most common application scenarios. Safari Browser Support Previous ASP.NET AJAX CTPs didn’t have great support for Safari (UpdatePanel didn’t work at all). With this Beta we have added Safari as a fully tested and supported browser. We are currently working on adding Opera support as well – although we aren’t ready yet to call it supported with this build (stay tuned for updates). Significantly Better Debugging Support As anyone who has spent a lot of time doing it can attest, debugging JavaScript is often not a lot of fun. We’ve made two significant changes with this Beta that will help improve the debugging experience with the Microsoft AJAX Library considerably: 1) By moving our JavaScript class definitions from being closure-based to prototype-based, you can now use the existing Visual Studio 2005 script debugger (and/or other existing JavaScript debuggers) to better inspect and step through JavaScript objects. Closures previously hid a lot of inspection information. 2) We invested a lot of time putting together an automated JavaScript build environment that enables us to produce two versions of all of our JavaScript files: a retail version that is optimized for performance and download size, and a fully instrumented debug version that is optimized for helping you catch issues with your code during development. Every function within the debug version of our script files now includes parameter and argument validation code that verifies that the function is being passed the correct arguments before running, and that will assert with stack trace information if not. This can help to more easily pinpoint errors with your JavaScript code early, and hopefully significantly improve JavaScript debugging. Note: By default, the decision to use the retail vs. debug versions of the AJAX script libraries is driven by the <compilation debug=”true|false” /> setting within your web.config file. Because this client-side parameter validation code significantly increases the size and performance overhead of the client-libraries, make sure you set debug=”false” before deploying any application (for more reasons on why you should always set debug=”false” when deploying ASP.NET applications, please read this past post of mine). Another Note: Our plan is to have the next version of Visual Studio use the same argument validation metadata that we use at runtime with debug scripts to also drive IntelliSense and syntax checking of JavaScript within the IDE. You can add this metadata to your code to improve validation, error checking, and eventually IntelliSense of your own JavaScript libraries as well. UpdatePanel Improvements The UpdatePanel control have been updated significantly with this Beta release to incorporate customer feedback. In addition to adding Safari browser support, the UpdatePanel control now has new support with this Beta for: a) Client-side script event hooks to let you write client-side JavaScript to more easily participate in callbacks. b) The ability to contain controls within an UpdatePanel that trigger both partial-page postbacks as well as normal postbacks (you now get to choose depending on your scenario). You can also now disabled child controls from causing UpdatePanel postbacks at all. c) The ability to use ASP.NET validation and Wizard controls within UpdatePanel controls (there were some bugs that prevented this before). d) The ability to dynamically create and add UpdatePanel controls into a page, rather than having to statically define them. This is particularly useful for control developers who can now instantiate and use UpdatePanel controls within their composite controls. e) The ability to have multiple UpdateProgress and Animation controls on a page that can run conditionally based on which UpdatePanel callback is occurring. f) The ability to declaratively specify how long to wait before an UpdateProgress control should become visible. This enables you to avoid showing progress status for quick UpdatePanel callbacks. g) Support for screen readers and other accessibility tools with UpdatePanel scenarios to better implement Section 508 standards. Important Beta Note: the UpdateProgress control with the Beta is currently shipping in the "Value-Add" download, so you will need to add this to your site in order to use it. With the next beta refresh it will be moved to the "core" download, and will be a fully supported scenario. Lots of Improvements in the Client Script Library Stack We’ve incorporated a lot of customer feedback and cleaned up, simplified, and enhanced a lot of the client-side JavaScript library APIs. In addition to moving from closures to prototypes, a number of other API cleanup changes have been made including: a) Simpler client JavaScript event model. It is now easier to define and attach events on the client. Object events are also now created on demand to reduce startup time and the size of the working set. b) Simpler Component, Behavior, and Control types. APIs can now be used without first needing to instantiate their related objects, and on-demand semantics have been added to improve performance. c) Client networking improvements. Default callback functions and method-name semantics provide a much easier way to perform common asynchronous callbacks. d) Membership and Profile APIs. Simpler APIs for interacting with the Membership and Profile APIs from client-side JavaScript are now supported. Better Compatibility with other AJAX Libraries One challenge with JavaScript is that collisions between different client-side JavaScript libraries can be ugly. Previous ASP.NET AJAX CTPs defined a global helper function named $( ) that conflicted with other common JavaScript libraries (including Prototype and Scriptaculus). With this Beta we have renamed our $( ) function to $get( ) and made a few other naming changes to help enable multiple independent AJAX libraries to play nicely together on the same page. Source Modification License One common request we have received is the ability for developers to make source modifications to the core Microsoft AJAX JavaScript library (to add a small feature, tweak an implementation, or make a tactical bug fix). We are going to provide a license to explicitly allow custom modification of the libraries, and the ScriptManager API that ships with this Beta now allows you to provide alternative implementations/tweaks of the built-in JavaScript libraries. In addition to allowing you to tweak the libraries for your own applications, the license will also grant redistribution rights so that you can ship them with your own components and extensions. (The one requirement for redistributing your own custom version is that you need to change the namespace to avoid conflicts.) We think the combination of having both full enterprise-level support (with 10-year support services), along with modification redistribution rights is a really powerful offereing that will provide developers with a ton of flexibility regardless of their project type, size, or target audience. Next Steps As you probably noticed from the paragraphs above, there are a number of new features and changes with this Beta. Existing ASP.NET AJAX code will need to be updated to reflect these changes. If you have been using server-side ASP.NET AJAX features, you should find the updates relatively straightforward. These will mostly involve renaming the control prefix from <atlas:> to <asp:>, modifying the trigger syntax for UpdatePanel controls, and making small syntax changes to how extender controls in the Control Toolkit are declared. You can read a migration guide with the details on how to-do this here. If you have created your own JavaScript class types and, or if you interact with the component model directly, you will need to make more significant changes. What we’ve found when updating samples is that the JavaScript changes are not too complicated by themselves – what is frustrating is that JavaScript’s type-less flexibility prevents tool compilation checking, and forces you to update things iteratively to find and fix each change, which can be tedious and annoying. To help with migration from the CTP to the Beta, the ASP.NET AJAX Team has published a detailed document listing the specific changes that have been made and which includes code samples that show before and after versions of common patterns and APIs usages. We will be publishing this document shortly here. The ASP.NET AJAX team will also be monitoring the forums closely over the next few weeks to help people with migration questions and any issues they find. Please post in the forums to get help if you run into any issues, find any bugs, or need any help. We are really looking forward to having lots of people use the Beta and to getting more feedback. We believe the API definitions for the features currently in the ASP.NET AJAX v1.0 Core download are now pretty close to being final, and our plan for the rest of this year will be to keep taking feedback and bug reports, and stabilize and lock down the release. Our plan is to release a beta refresh in a few weeks that incorporates customer feedback, then ship a RC release after that, and then ship it as a fully supported 1.0 release once people feel it is ready. Thanks, Scott

|
-
I spent the summer as a hermit. Here are some events where I'll be presenting over the next three months.
VSLive! Boston (Oct 24 - Oct 27). On Wednesday afternoon, I'll show you
how to bend master pages to do your bidding. There is some great
ASP.NET 2.0 content in this show with the likes of Fritz Onion, Miguel
Castro, Chris Kinsman, and more.
VSLive! Dallas (Nov 14 - Nov 17). One presentation on master pages, and
one presentation to help make sense of web site projects, web
application projects, and web deployment projects.
Central Penn Code Camp (Dec 2). I'll probably do one talk on an ASP.NET topic, and one introduction to Windows Workflow.
CMAP User Group (Dec 5). Every December, the central Maryland user
group has a tips and tricks show. Different presenters each take 20
minutes and show you tools and time saving techniques you'll find
useful in everyday development. Free pizza and door prizes, too!
BaltoMSDN User Group (Dec 18). If you are in Baltimore or
Northern Maryland, come out and support the newest user group in the
area. Topic TBA. 
|
-
On Dave’s recommendation I installed this new Wiki and was thoroughly, and I do mean thoroughly, impressed. I have been using FlexWiki for sometime and I have to say that Screwturn really blows it away. It has built in security, one-click backup, its extremely customizable, and much more.
If you are looking for a wiki (and who isn't?!?!) then check it out.
-James 
|
-
Mike Volodarsky from the IIS 7.0 team recently created a new blog and has been posting up a storm of great IIS 7.0 related posts. Mike owns the "integrated pipeline" and "server core extensibility" aspects of IIS7 - which among other things now allow you to write ASP.NET/.NET HttpModules that can participate in any web request to the server (for example: you could implement forms auth and role security for ASP, PHP, Java requests). This gives you more power than ISAPI extensions/filters today - and best of all you can use any .NET language to build them. I definitely recommend subscribing. If you haven't checked out www.iis.net yet, then I'd also recommend setting aside a few minutes to review some of the great content on it. http://blogs.iis.net aggregates blogs from team members. Here is the RSS feed to subscribe. Hope this helps, Scott

|
-
One misunderstanding I often see is "if I make this member static it will be thread safe". I think this misconception arises because of the boilerplate MSDN documentation that will often say: "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
When a .NET framework class appears with the above documentation, it means a developer took the necessary precautions to make the static member thread safe. Perhaps they added a lock, or used some other synchronization mechanism to ensure thread safety. See: Statics and Thread Safety Part I and Part II.
Marking a class member static doesn't guarantee thread safety. It is up to you to make the member thread safe.
There is one exception to this rule. It's a special case where the static / Shared keyword will guarantee threading magic. Do you know what that is? 
|
-
Earlier today CTP6 of the Visual Studio Team Edition for Database Professionals was made available for free download. VS for Database Professionals has been getting rave reviews, and includes support for database refactorings, schema and data comparisons, database unit testing, and automated data generation. You can learn more about it on its MSDN dev-center and Community page. You can also watch a nice Channel9 video with the team here. Two other data management tools that I've seen posted on http://weblogs.asp.net recently that look very cool and are worth spending time to check out include: MassDataHandler - A free CodePlex project that provides a utility library to help automate data generation for unit testing (it can be used within any unit test framework). Data Dictionary Creator -- A free tool that helps you document SQL Server databases, and helps you keep your documentation in sync with schema changes. Hope this helps, Scott

|
-
People often ask what the aspnet_compiler tool can do. The usual answer is "pre-compile an ASP.NET 2.0 web site". The follow up question is: "What good does that do me?". MSDN says the advantages to compilation in general are:
- Performance
- Security
- Interoperability
- Stability
Let's take these one at a time.
Performance
I say the performance benefits to pre-compiling a site are negligible. Pre-compilation does save some work, but ASP.NET applications in general are slow starters. Think about all the work that happens when the first request arrives. A process has to start. An AppDomain has to load. The cache is empty. The database connection pool is empty. Even if you've precompiled, the JIT compiler has to step in and create native code.
I'm not saying you shouldn't pre-compile a site to save some time. Just don’t' count on seeing a significant reduction in start up time for all applications.
Security
The MSDN article I linked to says "Compiled code is more difficult to reverse engineer than non-compiled source code…". Compilation makes the job more difficult, but all someone needs is the right tools. If you are trying to hide secrets in your source code, then encryption, not compilation, is the way to go. If you want to protect intellectual property then look for good obfuscation tools. Just remember you can't stop reverse engineering, you can only slow it down.
I don't think of pre-compilation as a security benefit, but if you pre-compile an ASP.NET application without the updateable option, you will lock down the application in production. Pre-compilation can strip out all the markup in template files, and no one can easily hand-tweak stuff outside of the configuration management process.
Interoperability
I never thought of interoperability as a benefit of compilation, per se. It seems interoperability between languages is a feature of the platform, not any compiler. I think the documentation is stretching this a bit.
Stability
ScottGu refers to using pre-compilation for "deep verification". A pre-compiled ASP.NET application is stable and verified in the sense that you won't see runtime errors because of syntax problems in markup. If someone checks in a malformed server control tag, you can catch the problem during the build with a compiler error, instead of finding out about the problem in test or production. Stability is arguably the greatest benefit of pre-compilation, and I recommend pre-compiling a web site for this reason alone. .
Summary
When I heard about pre-compilation in ASP.NET 2.0, my thoughts circled around startup performance. As it turns out, pre-compilation will save not only CPU cycles but test and development cycles as well. Pre-compilation is worth the effort, primarily because it requires so little work to setup.
If you want an interactive and user friendly interface for pre-compilation, check out Rick Strahl's ASP.NET 2.0 Compiler Utility.
Web Deployment Projects can do pre-compilation (and a whole lot more), using a standard MSBuild project file.
If you just want to add a quick pre-compilation step to your Team Foundation Server build, use the AspNetCompiler task in the AfterCompile override in TfsBuild.proj:
<Target Name="AfterCompile"> <AspNetCompiler PhysicalPath= "$(BinariesRoot)\Release\_PublishedWebsites\MyWebSite" Debug="false" VirtualPath="/MyWebSite" /> </Target>

|
-
Last year I wrote a little macro to generate a web.sitemap file for ASP.NET 2.0. A few people have been asking about support for Web Application Projects, so I've updated the macro.
Download.
This macro walks through the directories of a web project and adds all the content pages to a ASP.NET 2.0 site map file. If you use URL re-writing or virtual path providers, it won't be able to see those URLs. Chances are you'll need to hand tweak the file afterwards as the macro isn't intelligent enough to devise a good title for each page, but it can save a lot of typing to get started.
To install:
- Open the macro explorer (Alt+F8).
- Right click a macro project and select "New Module…"
- Name the new module SiteMapMacro
- Right click the new module and select "Edit". Clear existing code.
- Paste the code from the download into the new file.
- In the Project Explorer, right click References and add a reference to System.Xml.dll. Close the editor.
Back in the macro explorer, you should be able to right-click the macro to execute it. 
|
-
Three new tutorials have just been added to the Working with Data in ASP.NET 2.0 series. These three focus on master/detail filtering with the DatList and Repeater controls. There's one on filtering with a DropDownList, one with master/detail reporting across two pages, and a third one that illustrates using nested data Web controls.
As always, the tutorials are available in both C# and VB, can be downloaded as PDFs, and whose source code is packaged up into a simple ZIP file (rather than an MSI).
Enjoy!
|
-
I wasn't paying attention when I typed:
mstsc /v:name.domain.net /console
Unfortunately, I was already sitting in front of the very machine I was trying to reach with terminal services. I took over the console, all right - the screen blacked out. I couldn't get Ctrl-Alt-Delete to provoke a response. If it wasn't for the lights on the case I'd have thought the computer died.
It takes 30 seconds or so for the un-credentialed new connection to timeout and return control to the real console.
It's a very long, worrying 30 seconds, though. I just wanted to share my anxiety. 
|
-
Whenever I walk by the summer reading table at Borders or B&N I always noticed this book. I never read it in school, but always wanted to read it. The reviews plastered on the book draw comparisons to Catcher in the Rye, one of my all-time favorites. They couldn’t have been more wrong. There are three ways to look at this book, and every way you look at it the book is only adequate at best (far from a classic).
The first way to look at it is as a period piece about the students that were in school while a war (WWII) was going on. This way Finny would obviously represent the childhood innocence that continues even as the world expects these kids to be adults. Of course it’s hard to hide the fact that most of these kids should have been in the war, their poorer counterparts were most definitely already in the war. From this perspective the book is OK, but far from a classic that should be read by students in school.
A second way to look at it is as a study on human behavior. You have one kid who is incredibly jealous of the other, and acts on that jealously in a malicious way. The problem is that the rest of the book kind of leaves this question un-answered and un-explored. There are much better books that explore human emotions, competitiveness, and jealously.
A third way, and probably the most interesting way, is that this is really all about one kid who has homosexual feelings for his friend and then does him harm because of those feelings. I noticed quite a bit of homo-erotic stuff throughout the book, I remember when I first read the part where Gene is describing Finny’s muscular back while he climbed the tree I laughed and had to read it to my wife. A reviewer on Amazon also pointed out some other suspicious points: a bunch of high school boys that NEVER talk about girls, never to go dances with girls, during the trip to the beach no girl is mentioned just how they talked all night and fell asleep on the dunes. Looking at the book this way actually makes it much more interesting that the other approaches, but ultimately it doesn’t fit very well with the ending.
As a coming of age or human behavior story you are much better off with Catcher in the Rye or Lord of the Flies. As for the third way, while it makes the book more interesting, I doubt it was the author’s intent. Although I don’t know of any, I am sure there are better books available on this topic as well.
-James 
|
-
One of the most popular features in ASP.NET 2.0 was the introduction of the "provider model" for the built-in ASP.NET Application Service APIs. The provider model ensures that the storage/implementation for services like Membership, Roles, Profiles, Health Monitoring, Session State, and Site Navigation is extensible, and it allows a developer to easily plug-in alternative implementations if they want. Earlier this year I blogged about how we shipped the source code for the built-in ASP.NET 2.0 Providers on MSDN, and published 130+ pages of really good documentation that walksthrough their implementation and behavior. If you are looking to adapt the existing providers (which are pretty feature rich and in-depth), then you'll find these whitepapers and source a good resource to check-out. One downside with starting off with the code within the built-in feature-rich/optimized providers, though, is that the source code might be bigger and more complicated then you might like, and the database schema might not map to the database structure you want. Michal Valasek sent me mail earlier today pointing me at a really cool CodePlex project he has started that provides a simplified set of SQL Provider implementations for the ASP.NET Membership, Roles and Profile APIs. These use a nice straight-forward database schema and can be easily adapted for your application and/or integrated into existing tables you might already have. You can download the source code for them here. I definitely recommend checking them out and bookmarking the project - they provide a really great way to get started with custom providers. For learning more about the ASP.NET Provider Model, I also recommend checking out a great Code-Camp presentation that Paul Wilson did complete with a nice provider implementation built with his ORMapper that you can download here. You can also find other non-SQL provider implementations (including ones for MySql, SqlLite, Access and more) via my ASP.NET Security Resources Page. Hope this helps, Scott

|
-
Before this book I somehow have never managed to read a Stephen King from beginning to end. I started one back in high school, but didn’t get all the way through it. Stephen King was hands down the most popular author with most kids in my high school, but I was much more into Tolkein, William Gibson, Lovecraft, Orwell, etc. and just because he was popular was reason enough for me to stay away. Now years later my wife recommended that I read a couple of his better books, and I figured I would give him a try.
And since I always like to start at the beginning I decided to start out with Carrie, his first novel. The book was enjoyable, I wasn’t blown away, but I wasn’t disappointed. The writing style was the most interesting part, how King switches between first person reports, books written years later, and many other perspectives to tell the story. The obvious intent of this approach was to make the novel read much more like a true crime book than anything in the horror genre. It’s definitely different than most of the books I have been reading lately, but a good read.
My wife also wants me to read The Shining and Cujo so I have added those to the list.
-James

|
-
I blogged about an idea to mitigate what I think is the main reason behind the unit testing guideline of a single assertion per unit test. You can read about my idea here. Roy doesn’t agree, he still thinks one assertion per unit test is a good idea.
His main argument is:
“Even if we assume that all the asserts are run, you're essentially running multiple tests on code that has "dirty" state. For example, asserting on the result of a method call may actually change the state of the object under test so that the next call to that method may actually be skewed because of the previous asserts. that's a bad world to be in. having single assert per test means you also know exactly the state of your object before the assert.”
I tried my best to think of an example where I run asserts that actually change the state of what I am asserting on and I can’t think of a single example. If you look back at my original example none of my assertions would change the state of the object. In the rare case where your assertion would modify the state of the object I would gladly right multiple unit tests.
The rest of Roy’s arguments are largely opinion and preference. Roy might prefer 6,000 small tests over 1,800 larger tests, personally I would find that unmanageable. I think if you had a framework that runs all of your assertions you would have no compelling reason to stick to one assertion per test. You might want to follow this rule as a matter of preference, but I don’t think there is a compelling argument.
-James

|
-
Jamie wrote a follow-up post about getting dropped from the MVP program. You can read the original post here, as well as Roy’s post which includes some more details. Jamie showed me how he was getting add-ins to the Express SKUs and it isn’t even anything that special (very clever though), it is a public part of the API. No de-compilation or un-documented API is required.
Jamie mentions that I contacted Josh Ledgard over the matter. Josh is one of the most community minded and level-headed people I know who work at Microsoft. He understood my concern and I feel he did everything that he could to help out, but it was out of his control.
Interestingly the person who Jamie is having so much trouble with is the same individual who made any help with Visual Studio Hacks contingent on removing certain hacks, I blogged about it way back when.
-James 
|
-
My eleventh Toolbox column in the November 2006 issue of MSDN Magazine is now avaiable online. The November issue examines three products:
- BeyondCompare - a top-notch product for comparing and syncing text files, locally or remotely (through FTP, for example).
- Camtasia - many software vendors' websites these days include interactive, Flash-based demos showing their product in action. This can be used both as a selling point and for technical help (a more interactive knowledgebase). Camtasia is a program designed to capture screen interactions, optionally lay over voice or various video edits, and export the resulting creation to any of a variety of formats.
- FCKEditor - a free, open-source rich textbox for ASP.NET.
This month's issue reviewed Len Fenster's book Effective Use of Microsoft Enterprise Library. The Enterprise Library is a set of free, open-source application blocks released by Microsoft that perform a variety of standard tasks - data access, configuration, caching, exception handling, and so on. Len's book looks at the utility of the Enterprise Library, how it can fit into your organization's applications, and how to create your own custom application blocks that fir the same pattern. From the review:
The book is composed of nine content-packed chapters and three appendices, with each application block thoroughly explored in its own chapter. Each chapter begins with an examination of the application block's purpose, followed by a look at its class structure. The author then walks through how to configure an application to use the application block; numerous source code samples illustrate how to work with the application block from code. The book is a must read for those who are using the Enterprise Library or are in the midst of evaluating it.
As always, if you have any suggestions for products or books to review for the Toolbox column, please send them into toolsmm@microsoft.com.
ALSO! Brand new!! You can now read MSDN Magazine online in one of (currently) seven languages: English, German, Spanish, French, Portuguese, Russian, or Chinese! From the homepage you'll find a drop-down list in the upper right corner from where you can select your language preference.
So you can now read Toolbox in Spanish (or French, or Russian, or...)!!
You can keep abreast of the latest Toolbox articles through the column's RSS feed or the Toolbox column category here on my blog.
|
-
Which topic would you like to see me present at the Atlanta Cutting Edge .NET User Group (formerly the C# User Group)? I've given a presentation on Custom Providers in ASP.NET at Code Camp that some have asked me to do again, but it would be a repeat, or I can dig into a little known but powerful specific provider and do a presentation on Logging and Diagnositics in ASP.NET. Those are probably the only two options for now, so please give me your preference on these two, but feel free to suggest other topics if you have a good idea and I'll consider it in the future, although probably not right now.

|
-
-
Simon Muzio recently posted a link to free upcoming webcast talks for .NET. These are free webcast presentations that anyone can join over the web. You can find archived versions of past webcast events on the http://www.asp.net/learn site here. Here is a quick summary of upcoming webcasts over the next two months: Web Talks Date | Title | Speaker | Registration URL | 19-Oct | Live From Redmond: Introducing the Microsoft ASP.NET 2.0 AJAX Extensions | Joe Stagner | link | 26-Oct | Live From Redmond: An In-depth Look at UpdatePanel | Kashif Alam | link | 2-Nov | Live From Redmond: Enriching Existing ASP.NET Applications with ASP.NET 2.0 AJAX Extensions | Richard Ersek | link | 9-Nov | Live From Redmond: Introducing the Microsoft AJAX Control Toolkit | Joe Stagner | link | 16-Nov | Live From Redmond: Building your own Microsoft ASP.NET AJAX control extender. | Joe Stagner | link | 21-Nov | Live From Redmond: Using the Microsoft AJAX Library with “other” server technologies. | Joe Stagner | link | 30-Nov | Live From Redmond: Microsoft AJAX Patterns - Implementing Predictive Fetch with Microsoft AJAX | Joe Stagner | link | 8-Dec | Live From Redmond: An in-depth look at the "ListView" control | Kashif Alam | link | 12-Dec | Live From Redmond: Team development on web applications | Jim Bresler | link |
Smart Client Talks Date | Title | Speaker | Registration URL | 7-Nov | Live From Redmond: ClickOnce Tips and Tricks and what’s new in Orcas | Saurabh Pant | link | 14-Nov | Live From Redmond: Smart Client: Offline Data Synchronization and Caching for Smart Clients | Steve Lasker | link | 28-Nov | Live From Redmond: Client Application Services in Orcas | Saurabh Pant | link | 4-Dec | Live From Redmond: Visual Studio: Developing Local and Mobile Data Solutions with SQL Server Everywhere | Steve Lasker | link | Dec 6 | Live From Redmond: IronPython: Developing agile but rich client applications using Python | Mahesh Prakriya | link |
Hope this helps, Scott

|
-
Vivek points out some surprising behavior with master pages.
Let's say we want to disable ViewState for all pages by default. All we need is an entry in web.config:
<system.web>
<pages enableViewState="false" />
</system.web>
When the ASP.NET runtime generates code for a web form, it will disable ViewState using generated code. The code in the Temporary ASP.NET Files directory for an .aspx will contain a snippet like the following:
private void @__BuildControlTree(some_aspx @__ctrl) { #line 1 "some.aspx" @__ctrl.EnableViewState = false; // ... }
At some point, we may run into a page that requires ViewState. Arguably, we could say that something on the page should be re-written to use ControlState (required) instead of ViewState (optional), but it's easy to override the default configuration on a page by page basis in the @ Page directive:
<%@ Page EnableViewState="true" ... %>
This works - the @ Page directive overrides web.config and EnableViewState=true appears in the generated code….
… but there is a catch.
From what I can tell - some of the same goo responsible for the parsing and code generation of .aspx files also parses and generates the code for .ascx, and .master files. This goo will read the web.config setting and place EnableViewState=false in the code generated for master pages (and user controls, too).
For ViewState to be available to a control, it's parent must have ViewState enabled. Since a master page injects itself as the direct child of the Page object, having ViewState disabled in the master page shuts off ViewState for everything inside the Page.
With ViewState effectively disabled, it appears as if the @ Page directive isn't overriding web.config. It turns out that the @ Page directive does work as we expect. What we don't expect is that the MasterPage would pick up a configuration settings from the <pages> section of web.config and kill ViewState. But should we? The documentation for the <pages> element says:
"Globally defines page-specific configuration settings, such as ASP.NET directives for pages and controls that are within the scope of the configuration file."
Perhaps ASP.NET is working as designed, but I'd say the behavior is not intuitive in this case. 
|
-
The Web Client Software Factory dropped a new build yesterday. This is the first build I've downloaded. I spent about 30 minutes perusing the documentation and reference implementation, and I am shocked!.
My expectations were to open this package and find yet-another-data-access-layer-approach. Ho hum.
Instead, this factory positions itself to address leading issues in today's web development practices.
Some highlights:
- The reference implementation uses a model-view-presenter with controller (MVPC) pattern to maximize the testability of code, and centralize control flow and business logic.
- The docs explain how to implement MVPC using the canonical definition of test-driven development. Write your tests first. Red - green - refactor.
- The project uses "Page flow". Page flow models a user's path through a multi-page task using a Windows Workflow state machine and custom Page activities.
I plan to spend some more time with the factory and keep an eye on the weekly releases. 
|
-
The fact that he is no longer an MVP, and the reason the have revoked his status, completely disgusts me. The MVP program should be a way to reward people for their community involvement, not as a way to punish someone for adding valuable features to one of their crippled products.
-James 
|
-
This time, Joe Developer is building a web application for the company intranet. Most of the site is available to anonymous users, but one directory - the adminPages directory, should only be accessible to users in the machine's local administrators group. Joe added the following to the bottom of his web.config, and is feeling pretty secure.
<configuration> <location path="adminPages"> <system.web> <authorization> <allow roles="BUILTIN\Administrators" /> <deny users="?" /> </authorization> </system.web> </location> </configuration>
Should Joe be worried? 
|
-
Two weeks ago we released the VS 2005 SP1 Beta. You can download it for free by visiting and registering on the Microsoft Connect Site. This release contains several hundred fixes for customer reported bugs with VS 2005. It also includes built-in support for the VS 2005 Web Application Project, which we previously released earlier this year as a standalone download (SP1 adds a few additional features to it, fixes a few bug, and has some additional performance tunings for it). Before installing VS 2005 SP1 (both the Beta and final release), you'll need to uninstall any previous installs of the VS 2005 Web Application Project standalone download that you have on your machine. One bug that we've seen some developers run into is an issue where - if they have installed an older build of the VS 2005 Web Application Project on their machine before - they get the below error dialog message when they try to add new items to a Web Application project immediately after installing the new SP1 Beta Support for it: Error: this template attempted to load an untrusted component 'Microsoft.VisualStudio.Web.Application, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. For more information on this problem and how to enable this template, please see documentation on Customizing Project Templates. This is caused by a bug with the SP1 Beta setup. You can fix this with the SP1 Beta by closing VS 2005, and then open up the "Visual Studio 2005 Command Prompt" (there is an icon for it in your Start Menu->Visual Studio 2005->Visual Studio Tools folder), and run this command from within it: devenv.exe /InstallVSTemplates This will correctly re-configure the add item templates and make everything work fine. Hope this helps, Scott P.S. The setup issue will be fixed for the final SP1 release - so the steps above are only needed with the Beta.

|
-
I am
excited to announce that I will be joining Mimsware on October 26th.
Mimsware is a Microsoft Gold Certified Partner in the Atlanta area offering
services spanning software development, network infrastructure, and products to
corporate, government and small- or medium-sized businesses. While my focus
will of course be working on real applications for Mimsware, I will hopefully
also finally find a little free time for other activities. So if you're in the
Atlanta area and
looking for a great team of consultants to help you design and implement a
software solution using Microsoft stuff, then don't hesitate contacting Mimsware
to get proven experience.

|
-
In my Limiting Data Modification Functionality Based on the User (C# version) tutorial, I show how to adjust the functionality at the presentation layer based on the “currently logged on user.” (The demo doesn't actually setup the membership and roles systems, and rather allows the visitor to pick who they are logged on as from a drop-down list. See my Examining ASP.NET 2.0's Membership, Roles, and Profile article series for more information.)
One question I have received more than a couple of times is how to extend the permission-based business rules down into the Business Logic Layer and/or Data Access Layer. That is, how can I configure my BLL so that if my presentation layer has a bug or whatever, a person who is not authorized to, say, delete a record, is forbidden from doing so.
There are a couple of ways. One way is to add the logic programmatically to your BLL or DAL. You can access information about the currently logged in user in these layers using the Membership or Roles classes in the .NET Framework, like so:
1 public bool AddProduct(...)
2 {
3 if (!Roles.IsUserInRole("Administrator"))
4 throw new System.Security.SecurityException("You do not have permission to add a new product to the system.");
5
6 ...
Alternatively, you can specify authorization rules using PrinciplePermissionAttributes, as discussed by Scott Guthrie in his blog entry Adding Authorization Rules to Business and Data Layers using PrincipalPermissionAttributes.
With Scott Guthrie's approach, your BLL or DAL's code would include attributes defining the permissions required.
using System; using System.Security.Permissions;
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)] public class EmployeeManager { [PrincipalPermission(SecurityAction.Demand, Role = "Manager")] public Employee LookupEmployee(int employeeID) { // todo }
[PrincipalPermission(SecurityAction.Demand, Role = "HR")] public void AddEmployee(Employee e) { // todo } }
The benefits of PrincipalPermissionAttribute, as noted by Scott, are:
“The PrincipalPermissionAttribute isn't tied to any specific authentication mode. It will work with Forms Authentication, Windows Authentication, Passport Authentication, or any custom authentication mode you want to invent. It will also work with any Role implementation I might use (so if you build or plug-in your own Role Provider in ASP.NET it will just work).
“The PrincipalPermissionAttribute type is implemented in the standard CLR mscorlib assembly that all .NET projects compile against. So it isn't ASP.NET specific, and can be used within any application type (including Windows and Console applications). In addition to making it more generically useful, this makes it easier to unit-test business/data libraries built with it.”
|
-
Earlier this summer I posted two tutorials on using Windows Authentication with ASP.NET: Enabling Window Authentication within an Intranet ASP.NET Web Application and Implementing Role Based Security within ASP.NET using Windows Authentication and SQL Server. I also linked to Scott Mitchell's great ASP.NET 2.0 Security, Membership and Roles Tutorials that cover how to use Forms Authentication and the new Membership/Roles APIs in ASP.NET for Internet based web applications. These tutorials covers how to implement authentication on your site, which is the process of identifying who an incoming user is. They also demonstrate how to implement role based management on your site, which allows you to logically group individual users into higher-level roles or groups (for example: "admins", "friends", "subscribers", etc). The tutorials also demonstrate how to implement authorization rules to grant or deny users/roles access to visit individual pages or URLs within a site (the roles tutorial above also demonstrates how to show/hide menu nodes based on the permissions of the incoming user). Adding Security Authorization Rules to Business and Data Layers When you authenticate a user within an ASP.NET application, the authenticated user's identity will be automatically flowed throughout that user's request on the server. What this means is that you don't need to manually pass a user's identity around from method to method or class to class. This makes it much easier to implement security authorization rules throughout your application. One little known feature in .NET is the ability to have the CLR automatically use this identity information to authorize a user's capabilities before instantiating a class, or accessing a method/property on it. This makes it easy to add clean security authorization rules to your business and data layers without having to write much code. All you need to do to implement this is to use the PrincipalPermissionAttribute within the "System.Security.Permissions" namespace and decorate it on the appropriate class or member on it. For example: using System; using System.Security.Permissions;
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)] public class EmployeeManager { [PrincipalPermission(SecurityAction.Demand, Role = "Manager")] public Employee LookupEmployee(int employeeID) { // todo }
[PrincipalPermission(SecurityAction.Demand, Role = "HR")] public void AddEmployee(Employee e) { // todo } } In the above example, I have added a PrincipalPermission attribute to the "EmployeeManager" class. By adding it I am requiring that a user must be authenticated (logged-in) before this class can be instantiated during a web request (the Authenticated=true demand enforces this). I have also then added two additional security demands on the "LookupEmployee" and "AddEmployee" methods. With the LookupEmployee method I am requiring that the authenticated user for the request is within the "Manager" role in order for the method to be invoked. With the AddEmployee method I am requiring that the authenticated user for the request is within the "HR" role in order for this method to be invoked and have a new Employee added to the system. And now if I accidentally introduce a security hole within my UI tier and have some code-path that allows a non-Manager/HR employee to cause these methods to be invoked, my business tier will automatically prevent this from happening and raise a security exception. The PrincipalPermissionAttribute isn't tied to any specific authentication mode. It will work with Forms Authentication, Windows Authentication, Passport Authentication, or any custom authentication mode you want to invent. It will also work with any Role implementation I might use (so if you build or plug-in your own Role Provider in ASP.NET it will just work). The PrincipalPermissionAttribute type is implemented in the standard CLR mscorlib assembly that all .NET projects compile against. So it isn't ASP.NET specific, and can be used within any application type (including Windows and Console applications). In addition to making it more generically useful, this makes it easier to unit-test business/data libraries built with it. Using PrincipalPermissionAttributes within Pages and Controls The PrincipalPermissionAttribute can be used on any class within an application. So in addition to using it within your business and data layers, you can also use it within ASP.NET pages or user-controls you author in your site as well. For example, to enforce that your "MyPage" page can only be used by those within the "Manager" role, you could add a PrincipalPermission attribute to the code-behind of it (below done in VB): Imports System.Security.Permissions
<PrincipalPermission(SecurityAction.Demand, Authenticated:=True, Role:="Manager")> _ Partial Class MyPage Inherits System.Web.UI.Page
End Class More on ASP.NET Security To learn more about ASP.NET security I'd recommend checking out my ASP.NET Security Resources list as well as my ASP.NET Tips and Tricks Page. There are also now two dedicated books on ASP.NET 2.0 Security out there: Stefan Schackow's Professional ASP.NET 2.0 Security, Membership and Role Management book and the new Developing More Secure Microsoft ASP.NET 2.0 Applications book by Dominick Baier (who runs the great http://www.leastprivilege.com/ blog) that just got published this week: Hope this helps, Scott

|
-
November 6th-10th are the dates for this fall's ASP.NET Connections Conference at the Mandalay Bay Hotel in Las Vegas. If you are looking for a great conference with a ton of ASP.NET, .NET Framework, Visual Studio, SharePoint, and SQL Server content, this is the perfect event for you (there are over 40 unique ASP.NET talks alone, and more than 200 sessions total across all tracks). Several people from my team will be presenting, and I'll personally be doing a broad keynote, an ASP.NET AJAX (aka "Atlas") "coding on the fly" keynote, a LINQ data talk, a ASP.NET Tips and Tricks session, as well as an open Q&A session. The DevConnections team really do a great job putting on this event, and the facilities and organization is superb. I hope to meet up with some of you there! Scott

|
-
Don't ever book your Delta flights directly through Delta! My story has a good ending luckily, but no thanks to Delta. This started when I booked some flights for my family's vacation over 2 months ago. This is for a vacation still over 4 months from now, but I wanted to reserve our spots. I hated doing it at that time since gas was so high, but the accommodations had to be reserved. So today I look at my itinerary, not really for any reason other than I wanted to. And there I found that one leg no longer said confirmed, instead it said contact Delta. So I called Delta and they said they did not go to my destination anymore. I asked why they hadn't bothered to notify me, since I've specified I do want notified of any updates. Their answer was that there is no reason to notify me this far in advance. Hmmm, I purchased my tickets this far in advance because I want to be sure. And now there's one less carrier going there so I'm sure its only going to be harder to get there. But Delta has decided for me that its too far out to matter, even though I've requested notifications. So next I asked what my options were, alternative carriers or refunds. Well it turns out they really want to find an alternative for me. But after checking, since they don't go there now, their idea of an alternative is to go somewhere else. I told them it was easy to find alternatives with other carriers if they were willing. But apparently an alternative carrier is not a viable alternative for them, even though they no longer go where they sold me a ticket too. So that only leaves a refund as an option, which they were happy to do. And that then allows me to go book my own alternative, averting a potential disaster. The funny thing is that most of my itinerary is still Delta, and some of it are the exact same flights. But since gas has gone down I'm actually paying less than I was earlier, and Delta is getting less. By the way, should an alternative not been easy to find, or not cheaper, it turns out travel insurance would not have covered this. They'll cover if the carrier goes bankrupt or has a strike, or changes our itinerary during our trip, but apparently is totally acceptable if they just stop going to the location they sold you a ticket to.

|
-
Today we launched a Chinese and German content section on the www.asp.net web-site (so you can find localized articles, blogs, forums and other community sites). This adds to the Spanish, French and English versions already available. You can switch your language preference in the top-right of the site to filter the content of the www.asp.net site, or link to them directly here: We also updated the Videos Section on the www.asp.net site with a new index. If you haven't checked out the videos lately, I'd recommend making a pass through them. There are about 80+ now on the site, with 1-2 new ones being added each week. They provide a great way to learn about new features. Hope this helps, Scott

|
-
WARNING: There is a potentially severe concurrency issue with ASP.NET 2.0 GridViews, DetailsView, or FormViews that support editing and/or deleting and whose view state is disabled....
In the Editing, Inserting, and Deleting Data tutorials of my Working with Data in ASP.NET 2.0 tutorial series, I demonstrate how the GridView, DetailsView, and FormView can all support the built-in editing, deleting, and inserting capabilities with view state disabled. The reason is because the key data Web control properties (such as the DataKeys collection), are stored in control state, which is always persisted to view state regardless of the control's EnableViewState property value.
In my tutorials I don't mention the view state issue, I just silently set the EnableViewState property to false. And this works wonderfully when testing the page. Deletes and edits work exactly as expected, with or without view state enabled. However, a rather insidious behavior can rear its head when there are multiple users visiting the same page. This potential trap was pointed out to me by alert reader Jamie Crutchley, whose observed and shared information about this problem on the ASP.NET Forums in the past. I'll explain the problem (and a potential workaround) in my own words, but you can read Jamie's posts here and here, if you'd rather.
PROBLEM: Two users - Alice and Bob - visit a page (Products.aspx) that uses a GridView whose to list products; the GridView's view state has been disabled. The GridView uses its DataKeys collection to store the primary key values of the three products. Imagine that the products listed are Pens, Books, and Paper, and their respective primary key values are 1, 2, and 3.
- Alice clicks on the Delete button for the first product in the grid (Pens).
- A postback occurs. Because the GridView's view state has been disabled, on postback the data is re-read from the GridView's data source. This has the side effect of repopulating the DataKeys collection with the newly read data!
- Since the first row index was clicked, the GridView grabs the DataKeys value indexed at 0 and issues a delete based on that primary key value (1).
- Bob still sees all three products on the page (since he loaded the page before Alice deleted Pens). Sometime after Alice has made her deletion, Bob, too, decides that Pens must be deleted. He clicks on the Delete button for Pens.
- A postback occurs. Because the GridView's view state has been disabled, on postback the data is re-read from the GridView's data source. This has the side effect of repopulating the DataKeys collection with the newly read data!
- Since the first row index was clicked, the GridView grabs the DataKeys value indexed at 0. However, since the DataKeys collection has been reloaded in Step 5, the first DataKeys value is the primary key of Books (since Pens has since been deleted). The consequence is that Books is deleted, even though Bob wanted to delete Pens!!
More generally, if Alice deletes any product whose index preceeds the index of the record Bob deletes, Bob's delete will actually delete a different record. Similarly, if Alice deletes a preceeding record of the one Bob is editing, the edits will be applied to a preceeding row. Eep.
SHORT AND SIMPLE SOLUTION: Unless you are absolutely, 100%, certifiably, unconditionally certain that there will never, ever, not in a million years be two users concurrently editing/deleting records, then be sure to leave the GridView / DetailsView / FormView's EnableViewState property to True (the default).
MORE INVOLVED SOLUTION: If you really would like to reduce the page size by disabling view state, you can use the following “hack”... When a Delete (or Edit) button is clicked in the GridView the RowCommand event fires before the DataKeys collection is internally repopulated. Therefore, you can create an event handler that includes code that “saves” the DataKeys value(s) for the record being deleted. Then, in the ObjectDataSource's Deleting event handler you can reassign this value back to the primary key parameter(s).
Here's some code to implement this approach. First, in the RowCommand event handler the primary key (ProductID) is saved in a page-level variable:
1 int recordToDelete = -1;
2 protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
3 {
4 recordToDelete = Convert.ToInt32(GridView1.DataKeys[Convert.ToInt32(e.CommandArgument)].Value);
5 }
Then, in the ObjectDataSource's Deleting event, assign the page-level variable to the appropriate parameter:
1 protected void ObjectDataSource1_Deleting(object sender, ObjectDataSourceMethodEventArgs e)
2 {
3 if (recordToDelete > 0)
4 e.InputParameters["ProductID"] = recordToDelete;
5 }
The tutorials and code at Working with Data in ASP.NET 2.0 will be updated so that they no longer disable view state and will include a similar warning as to this blog entry, although due to the breadth of material online, it may take several days or weeks to get all the changes made and propagated...
|
-
I imagine the MS legal department frowns on the appearance of recognizable names in documentation. Nevertheless, there are a few out there. For instance, the documentation for IXmlSerializable.WriteXml contains a celebrity from Bedrock:
// Create a person object. Person fred = new Person("Fred Flintstone");
Over in the Visual FoxPro world, we find a local Microsoft celebrity:
IF UPPER(userID) = 'BILLG' && only one user may add tables RETURN .T. ENDIF RETURN .F. ENDIF
Finally, perhaps someone had a particular GeorgeW in mind when describing sp_denylogin to aspiring DBAs:
EXEC sp_denylogin 'Corporate\GeorgeW'
If only it were that easy…
So, know of any others? 
|
-
-
Q: Great article on the WWF Rules engine. I am curious how one would implement a rule that is applied to a collection of items, something akin to "IF request.Payments .Amount > 10000 THEN request.Payments .RequiresApproval = true"
A: There are quite a few approaches to choose from. As usual - it depends on the application!
One solution is to use a WhileActivity and loop through the collection. This explicit approach would run a PolicyActivity for each item in the collection.
The Windows SDK contains an interesting alternative approach in the "Processing Collections in Rules" entry. This is approach is worthy of note because it uses the features and flexibility of the rules engine to perform the iteration without any outside help. The approach specifically relies on the following features:
- Every rule in a Windows Workflow rule set has an associated priority number. The priority number determines when the rule will execute relative to other rules.
- The rules engine in WF analyzes the dependencies between rules. When a rule updates a dependency, the rules engine can re-evaluate previous rules that used the dependency.
With a Payment class defined in your domain model, the workflow class can accept an array of Payment references as a parameter:
public partial class Workflow1 : SequentialWorkflowActivity { public Payment[] Payments { get { return _payments; } set { _payments = value; } } Payment[] _payments; IEnumerator _enumerator; Payment _currentPayment; }
Next comes the RuleSet:
| Name |
Priority |
Rule |
| GetEnumerator |
3 |
IF 1=1 THEN this._enumerator = this._payments.GetEnumerator() |
| MoveEnumerator |
2 |
IF this._enumerator.MoveNext() THEN this._currentPayment = (Payment)this._enumerator.Current |
| One Or More Biz Rules |
1 |
this._currentPayment.Amount > 10000 THEN this._currentPayment.RequiresApproval = True ELSE this._currentPayment.RequiresApproval = False |
| Force re-eval |
0 |
IF this._currentPayment == this._currentPayment THEN Update("this/_enumerator/") |
GetEnumerator runs first because it has the highest priority. MoveEnumerator runs second - again because of priority. After these two rules finish, _currentPayment will reference the first Payment object in the array. All the "business" rules could now execute on that payment and decide on an outcome.
The interesting piece happens in the last rule, which always evaluates to true and performs an explicit "Update" on the _enumerator field. "Update" is a rule action that explicitly tells the engine about a side effect. In this rule, we are telling the engine that we've changed _enumerator. Even though we haven't actually changed _enumerator, we've forced the engine to look for previous rules with a dependency on _enumerator.
The rules engine knows the MoveEnumerator rule has a dependency on _enumerator, so it re-executes this rule. If MoveNext returns true in this rule, we update the _currentPayment field. The rules engine also detects this implicit side effect, and will reevaluate all the business rules that depend on _currentPayment. If MoveNext returns false, there are no more side effects and the Policy activity can close.
This is a clever pattern which keeps collection processing inside of a single activity. 
|
-
Its October 1st, which is the annual date that the majority of MVPs are announced, so I'll take this opportunity to announce that I am officially no longer an MVP. That's right, I was not renewed as an MVP -- and I think MS made the right decision. I was first made an MVP in October 2002, which made me one of the first .NET MVPs. At the time I was the top poster in the ASP.NET Forums, active in newsgroups, and I was also evangelizing various base page template methods to use with ASP.NET. Why was I active in these venues? Quite simply, I had the time, and I enjoyed it. I was not seeking any recognition, but all the sudden I found that I was noticed -- I was even invited to the first private alpha of ASP.NET v2.0 with some big names. My time got a little tighter over the following years, but I was still involved, so I was renewed in 2003 and 2004 since its a lot easier to get renewed than noticed. Then I got even busier with both my job and my wife's health taking lots of time, and yet I was renewed again even in 2005 -- and I probably shouldn't have been. But since then I've only gotten busier with my job, and I hardly ever post anymore, so it really came as no surprise when I was told that I was not to be renewed as an MVP. And I think this is the correct decision by MS -- MVP renewal should not automatic. Some people are still renewed based on their names mostly, but maybe that's ending. Instead, its nice to see new people recognized for their community contributions. Speaking of community, its also been very cool to see how Atlanta's has grown up. I remember going to a few user groups back years ago and wondering why I bothered. But now there is a very active group of people involved in the Atlanta community. I remember being the very first developer-oriented MVP awarded in the Atlanta area -- and now look at the very impressive group of developer MVPs that Atlanta can boast. So now when I do have the time, I choose to be more involved in our user groups. So while I'm very proud of the fact that I have been an MVP, for four years even, I'm also very glad to be a part of the local Atlanta community, and to know so many. Hopefully I'll have more time soon to be even more involved -- so watch for more news. :)

|
|
|
|