Looks like Mitch is studying for 71–536 as well. I’m signed up to do it AFTER the Ready Launch – on Dec 20. For 71–528, we had a study group chat. Mitch has taken a different tack, doing individual blog posts on each of the skills being measured as he looks at them.
So far he’s done:
This looks like a great approach. Leave comments on Mitch’s individual posts if you’ve got stuff to add and get ready to get certified!
This post from Mark Stanfill on The Official SBS Support Blog prompted me to post a Me To.
An apparently little known feature of Windows Media Player (judging from the number of people who are surprised when I tell them about it) is the Fast Forward button, which allows you to watch (and listen to) clips at 1x, 1.4x, 2x and 5x the original speed. I generally watch the PowerPoint section at 2x and scoot back to 1.4x for code demos.
The cool thing is that WMP seems to use a compression technique which cuts out silence in the audio rather than just playing everything at double speed (so it doesn’t affect the pitch). Note that you can also play at slower than real time if you want to. There’s an entry available in the WMP help file that gives you all the details.
Updated – Added Hobart Community LaunchUpdated II – Corrected the Adelaide Venue – thanks Frank
I'm off to Melbourne tomorrow morning to rehearse with Dave Glover and smokin’ Joe Sango for the developer track for our Ready! tour launching VS 2005, SQL 2005 and BTS 2006. Rob Caron, who will be down here for some of the launch tour, will be joining us via Live Meeting for some of the morning.
On Thursday, I'll be heading up to Brisbane to rehearse the same stuff with Chuck and Anthony Borton.
Of course, Frank and Dave (complete with mo, at least for the first 3 cities) will be on the road with us as well, as will Jeffa and Kleefy. In short, we’re putting the band back together.
In each city, we’ll be doing a community launch event and a business launch event. At the community event you can enjoy a night of networking opportunities with speakers, your peers in the industry, speakers at the next day’s presentations and the Microsoft team. The night will consist of impromptu presentations, plus great food and drinks. We will also distribute lots of resources to get you started with the soon to be launched products.
The next day, we’ll be running a full day event we’re calling the business launch (to distinguish it from the community launch). We’ll have a keynote (which will look very similar to this, but delivered by people with significantly more hair) followed by 3 tracks of technical presentations focusing on the technologies that we’re launching. These will be much more formal presentations than the events the night before.
Here's where we'll be and when:
Another meeting this evening where we kind of covered off some of what was left after the first three sessions.
Transcript
Skills being measured
This just in from Brian Goldfarb, Technical Product Manager on ASP.NET
We heard a lot of feedback about the build process and new project system for managing more complex sites, build strategies, and deployment.. As a result, we've been working on a add-in for Visual Studio 2005 that enhances the built in support for MSBuild and the general Web build model.. The code is in Beta, but you can begin using it immediately
Check out the main page at: http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx
Download the BitsRead this article to get started ( seriously :)!)Provide feedback at the forum / get your questions answered
Enjoy!
From the site:
Visual Studio 2005 Web Deployment Projects provide additional functionality for building and deploying Web site applications that you create in ASP.NET 2.0 and Visual Studio 2005. This add-in includes a new tool that enables you to merge the assemblies created during ASP.NET 2.0 precompilation, and it provides a comprehensive UI within Visual Studio 2005 for managing build configurations, merging, and pre-build and post-build task using MSBuild
Update: Scott Guthrie’s also posted some more about this tool:
You can also see a walkthrough and description of it here: http://weblogs.asp.net/scottgu/archive/2005/11/06/429723.aspx
Co-incident with the official launch of Visual Studio 2005, Bootstraper Manifest Generator is also released and can be installed from the Bootstrapper Manifest Generator Home Page. (It is ClickOnce deployed from an internet website)
Bootstrapper Manifest Generator is a set of tools for creating custom bootstrapper packages used with Visual Studio 2005 and for building bootstrappers using the .NET Frameworks SDK v2.0. It includes the following features, and more:
Can build an Installer for a Manifest Project, to deploy it to other developers. Added support for Custom Schedules Ability to Extract Product Codes from MSI's and installed Products Ability to clone (copy) an Install File and all its settings (exit codes, etc...) and other improved copy/paste support.
Recently Used Projects List Better Support for Digital Signatures and File Hashes Select Assembly for AssemblyChecks from the GAC Output should generate a Bootstrapper that runs propertly on case sensitive web servers, like UNIX
Muiltiple Document Window – so you can work on several projects at once.
Tight Integration with MSBuild and Visual Studio
GAC Check - checks to see if an assembly is in the GAC Homesite - allows the installer to be downloaded from a central web site, seperate from your app deployment DependsOn and Includes - Updated package relationships that replace the catalog.xml file.
It was written in Visual Basic 2005 starting with Beta 1, through the RTM version.
We got "together" again last night for our third study group session. Once again, I've posted the transcript. This is also linked from our Skills Being Measured page.
I’d have to say we didn’t get nearly as far as we might have this evening. I’m not sure whether this was due to a McFlurry incident early in the proceedings, or just a general Monday-itis, but we covered off some of the ADO.NET stuff.
Next session is this Wednesday at 1930 (Sydney time – UTC+11)
I’ve also just posted my findings on the AdRotator and Dynamic Image Generation.
As part of my study group homework, I promised to bone up on the AdRotator class in ASP.NET2.0 and report back to the group. Turns out this lead to another cool thing that I needed to report back on - dynamic image generation.
The source code I’ll refer to throughout this post is available for download. Of course, it’s intended as a sample only. Use it at your own risk, no warranty expressed or implied, contents may be hot. Don’t say you weren’t warned. The source code demonstrates the 3 modes of populating an AdRotator control and a technique for dynamically displaying images stored as binary data in fields of a database.
The AdRotator class basically allows you to display a random image (more on where images come from and how "random" works in a bit) with an associated bit of ALT text and (optionally) a hyperlink from the image to somewhere else. You’ve seen this kind of thing on web pages before, in fact it goes back to ASP.NET 1.0 and has been implemented in any number of other web frameworks as well. Since we’ve been studying for the ASP.NET 2.0 exam, that’s what I’ll cover here.
AdRotator populates its image and navigation properties in 3 different ways, which I’ll call “Database”, “XML” and “Programmatic” for reasons that should become obvious, if they’re not already.
In database mode, an AdRotator is linked to a DataSource that needs, at the very least, a column for the URL of the image, a column for the URL to navigate to when the imaged is clicked and a column for the string to be displayed in the ALT tag of the image. In the MSDN documentation (online and offline), the full allowable schema is listed and includes some compulsory fields:
Note that the name of these fields can be overridden in the AdRotator by setting the ImageURLField, NavigateURLField and AlternateTextField properties to the appropriate field name.
In addition, the following fields are optional.
Of course, with the cool data handling functionality of data sources in ASP.NET 2.0, you don’t need a table anything like this, you can pull the data into the appropriate structure with a SQL statement in the DataSource itself. So, if you were dynamically displaying the thumbnail image from the ProductPhoto table in the AdventureWorks sample database, allowing a click to redirect to the LargePhoto image in the same table (again, dynamically rendered) and taking a description from the Product table for the Alternative text (OK, from now on I’ll call it Alternate text and grind my teeth), you could use something like
<asp:SqlDataSource ID="ProductPhotos" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT Production.ProductPhoto.ProductPhotoID AS ID, './ProductThumbNail.ashx?ID=' + LTRIM(STR(Production.ProductPhoto.ProductPhotoID)) AS ImageUrl, './ProductPhoto.ashx?ID=' + LTRIM(STR(Production.ProductPhoto.ProductPhotoID)) AS NavigateUrl, Production.Product.Name AS AlternateText FROM Production.ProductPhoto INNER JOIN Production.ProductProductPhoto ON Production.ProductPhoto.ProductPhotoID = Production.ProductProductPhoto.ProductPhotoID INNER JOIN Production.Product ON Production.ProductProductPhoto.ProductID = Production.Product.ProductID"></asp:SqlDataSource>
Which produces a resultset with the 4 required columns. Of course, writing SQL statements like that is much easier when you do it like this:
The AdRotator control itself then looks like this:
<asp:AdRotator ID="AdRotator1" runat="server" DataSourceID="ProductPhotos" />
All of the properties (except the DataSourceID and the name, of course) are left at their default values because I've used the default names for the fields in the DataSource definition.
The next way to populate the fields of an AdRotator is to use a static XML file. It has a very similar structure to the schema of the table required for the Database method. All of the details of the schema are available in MSDN (online and offline). There’s an example file included in the accompanying downloads. Here's an extract (of a file called Advertisments.xml):
<Ad> <ImageUrl>~/ProductThumbNail.ashx?ID=70</ImageUrl> <NavigateUrl>~/ProductPhoto.ashx?ID=70</NavigateUrl> <AlternateText>Product Number 70</AlternateText> <Impressions>100</Impressions></Ad>
<
And the AdRotator looks like this
<asp:AdRotator ID="AdRotator2" runat="server" AdvertisementFile="~/Advertisments.xml" />
Again, the default values work here because I’ve followed the naming conventions.
The third (and potentially most interesting from a developers’ point of view, although the database method is pretty cool too) is to populate the properties programmatically whenever the AdRotator AdCreated event fires (occurs once per round trip to the server after the creation of the control, but before the page is rendered). The event handler is passed an AdCreatedEventArgs object. You set the 3 properties, ImageURL, NavigateURL and AlternateText (familiar looking names aren’t they) and they are used to render the control.
The AdRotator control looks like this:
<asp:AdRotator ID="AdRotator3" runat="server" OnAdCreated="AdRotator3_AdCreated" />
And in the code-behind file (mine's in C#, but VB.NET would work just as well), I just wired up an event handler (via the properties grid in my case, because I'm lazy)
protected void AdRotator3_AdCreated(object sender, AdCreatedEventArgs e){ // Just for this example - see the download for a different way of using ProductID int ProductID = 1; e.ImageUrl = "~/ProductThumbNail.ashx?ID=" + ProductID.ToString(); e.NavigateUrl = "~/ProductPhoto.ashx?ID=" + ProductID.ToString(); e.AlternateText = "Programatically generated text for product ID " + ProductID.ToString();}
This is potentially very powerful. You could do real-time image targeting based on the navigation history of this user, based on personalisation they’ve done or any number of other criteria.
Up until now, I’ve glossed over the fact that the AdRotator class expects URLs pointing to images, not byte streams or arrays of binary data, or anything else that might represent an image. This potentially presents a problem when (as we have in our example), the images are stored as binary data in a database file. You don’t want to have to write them out to disk, where they’ll take up as much space again and need to be kept in sync with the database version. Up until Beta 1 of VS2005, it looked like this was going to be very easy, just use the Dynamic Image Control. Alas, it was dropped between Beta 1 and Beta 2 (see http://msdn.microsoft.com/asp.net/beta2/beta2changes.aspx). Fortunately, that very same page lists some code that can be adapted to do exactly what we need.
Essentially, we need to create an HTTP Handler class that intercepts calls to a particular URL and returns the image in a format that the browser expects. There are docs on the IHTTPHandler interface (which the specialised dynamic image generation classes in the example implement) in the MSDN docs (online and offline). HTTP handlers give you a means of interacting with the low-level request and response services of the IIS Web server and provide functionality much like ISAPI extensions but with a simpler programming model.
Here’s the code for one of the Handler classes (ProductThumbNail.ashx). The other one is identical, except a different TableAdaptor is used to retrieve the bigger photo.
<%@ WebHandler Language="C#" Class="ProductThumbNail" %> using System;using System.Drawing;using System.Drawing.Imaging;using System.IO;using System.Web;using System.Web.Caching;using System.Data;using System.Data.Sql;using System.Web.UI.WebControls;using System.Web.Configuration;using System.Configuration;using System.Collections; public class ProductThumbNail : IHttpHandler{ public void ProcessRequest (HttpContext context) { // Get the image ID from querystring, and use it to generate a cache key. String imageID = context.Request.QueryString["ID"]; String cacheKey = context.Request.CurrentExecutionFilePath + ":" + imageID; Byte[] imageBytes; // Check if the cache contains the image. Object cachedImageBytes = context.Cache.Get(cacheKey); if (cachedImageBytes != null) { imageBytes = (Byte[])cachedImageBytes; } else { GetImageTableAdapters.ThumbNailTableAdapter oTA = new GetImageTableAdapters.ThumbNailTableAdapter(); GetImage.ThumbNailDataTable oDT = oTA.GetData(int.Parse(imageID)); if (oDT.Rows.Count == 0) { // MAGIC NUMBER! // Photo ID 1 displays "No Image Available" image oDT = oTA.GetData(1); } imageBytes = (byte[])oDT.Rows[0]["ThumbNailPhoto"]; // Store it in the cache (to be expired after 2 hours). context.Cache.Add(cacheKey, imageBytes, null, DateTime.MaxValue, new TimeSpan(2, 0, 0), CacheItemPriority.Normal, null); } // Send back image. context.Response.ContentType = "image/jpeg"; context.Response.Cache.SetCacheability(HttpCacheability.Public); context.Response.BufferOutput = false; context.Response.OutputStream.Write(imageBytes, 0, imageBytes.Length); } public bool IsReusable { get { return false; } }}
<%
using
public
The important method to implement in the IHTTPHandler interface is ProcessRequest(). This gives you low-level access to the context object which, in turn, gives to access to the Request and Response objects so you can get the ID passed as a query string in the URL (using Request) and shove stuff back out with the Response object. The stuff to shove back out is just a byte array grabbed from the binary column in the table. Notice, I’ve just grabbed the contents of the ThumbNailPhoto column in the first row and cast it to a byte array.
To send the image back, just set the content type (note that this could come from the table as well, or could be dynamically determined from the header in the binary if required), tell the Response object just to stream the bits back, don't wait for the stream to close, and then just write the byte array to the output stream.
A couple of other things to note here (and I’m not claiming they’re best practice – comments always welcome):
Notice that instead of programatically creating connections and commands, I’ve opted to create a dataset (GetImage.xsd in the App_Code folder) with a couple of table adaptors. The naming convention adopted by ASP.NET gets me every time I use these. The TableAdaptors are in the <DataSetName>TableAdaptors namespace and aren’t available to intellisense until you’ve built the project after the xsd is created. The data tables are classes of the <DataSetName> class. So in this case The GetImageTableAdaptors namespace contains the ThumbNailTableAdaptor and the ProductPhotoTableAdaptor classes. The GetImage class has two properties – instances of the ThumbNail and ProductPhoto classes.
Configuring these datasets is heaps easier than remembering how to use them. Just add a DataSet to the project and the first TableAdaptor is added automatically. I added a very simple SQL statement with a parameter (the ProductPhotoID) to return a single row. To add the other, just right-click on the xsd design surface and choose Add TableAdaptor.
Note that I’ve opted for the very simplest Table Adaptors – no INSERT, UPDATE or DELETE clauses. These are only ever designed to be read-only.
This bit was already in the code on the MSDN site about the DynamicImageControl being pulled, but I left it in there because it seemed like such a good idea. The cache engine takes a key to see whether it has already looked up the image and stored it for future use. In this case I’ve left the cache duration at 2 hours. Obviously, you’d massage this based on how often images were likely to change.
I know these things have been up for a little while, but I've been slack and Craig's prodded me to blog about them (which I always intended to do, so thanks Craig).
1. Craig's announced OzFox Lite - a weekend conference for VFP developers in Australia to run 25/26 March 2006 at MS HQ in North Ryde, Sydney. He's calling for presenters and local community involvement. This will be a low-cost, high intensity weekend of VFP.
2. Craig and Scott have (finally <g,d&r>) released OzFoxRocks - an Australian VFP PodCast. Episode 1 contains some great thoughts from Craig and Scott, as well as an interview with some guy from Microsoft. Well worth listening to (except perhaps the interview). From the OzFoxRocks site:
It has three main aims:1. Keep the local Australian developer community informed2. Highlight news and tips from around the world3. Present interviews with both local and international VFP developers
3. Craig and Scott have also been working on a fantastic VFP 9.0 add-in called VFPSolutionExplorer. One of the first components to be released into beta is FoxTabs. Andrew MacNeil did a screencast of an early alpha of FoxTabs in action. Wow. These guys have been busy. Check it out.
4. Ken Levy has posted his November Letter from the Editor. It contains information about new content online about Visual FoxPro 9.0 and Sedna, VFP added to the MSDN Feedback center, more in-depth information about Microsoft's roadmap for Visual FoxPro, plus recent content and community news.
Update – Fixed the transcript link
We got "together" again last night for our second study group session. Once again, I've posted the transcript. This is also linked from our Skills Being Measured page.