If you get this error trying to set and hit a breakpoint, there are a couple of things to look for to resolve it. Typically what this error means is that the compiler cannot find debug information for the file you are trying to set a breakpoint in.

The first thing to check is that you have compiled the assembly in debug mode.

image

If you build the assembly in Release mode it will not generate the necessary debug information. Also be aware that there are two modes the compiler can use to generate the necessary program database (pdb) file for debugging, but only one of them actually enables incremental linking of the debug info.

/debug:full or /debug:pdbonly. Building with /debug:full generates debuggable code. Building with /debug:pdbonly generates PDBs but does not generate the DebuggableAttribute that tells the JIT compiler that debug information is available.

Depending on how you are building your solution you either need to look at the msbuild file or if you are building from within Visual Studio you can right click the project file and select properties. Then select the Build tab, and then the Advanced button. You will get the following dialog (VS2008, 2005 may look slightly different.)

image

Notice under Output the line for Debug Info, make sure this is set to full. The other values available are none, and pdb-only. Neither of the latter two values will result in debuggable code.

The next most common cause is that the [assemblyname].pdb file is not being copied or updated correctly to the bin folder of the startup project in a multi project solution.

You can manually copy the assembly file and the pdb file from the bin folder of the assembly you want to debug into the bin folder of the startup or calling project. Or into the web application bin folder if you are calling the assembly from a web application.

Thanks to Adam McKee of Ironworks who recently reminded me of the fix for this problem. I have put the information here to hopefully help the next person.

Cheers,

Robert Porter


 
Categories: .NET | C# | Debugging | Programming | VB.NET | Visual Studio


February 12, 2008
@ 10:58 AM

 

I have stumbled on, been emailed about, or otherwise notified of several interesting new resources of interest primarily for Microsoft Developers. So I thought I would share them here.

MSDN Code Gallery

The newest addition to the ever growing collection of MSDN resources is the MSDN Code Gallery. The code gallery contains code of course, along with video tutorials, sample applications and lots of other resources. It supports user uploads as well, so count on the gallery growing over time. From a rather quick look see on my part it does seem to contain some worthwhile resources.

MSDN Reader

If you have used or seen the New York Times reader then you will instantly recognize the new MSDN Reader. It is a WPF based application that allows you to read MSDN Magazine online. It appears that you do not have to have a subscription to use this, however I am unsure if that will remain true. But it is certainly worth a look.

MSDN Windows Vista Developer Center

This site has recently been overhauled significantly and (to me) seems easier to navigate and find information on. The Windows Vista Developer Center is full of resources related to developing applications that run on Vista and take advantage of features available in Vista as well as the recently launched Windows Server 2008. Of interest on this site was the announcement that SP1 for Vista has been released to manufacturing. Most folks don't consider an operating system or application as truly viable until at least the first service pack. So if you have been waiting for SP1 to look at Vista, your wait is over.

Hopefully one or more of these resources will prove useful to you!

Cheers,

Robert Porter


 
Categories: .NET | Ajax | ASP.NET | Programming | Reviews | Tools and Toys | VB.NET | Visual Studio


 

I had need to be able to play a video file (both mpg and wmv) in a WinForms application recently. I thought it would be rather straightforward, and for the most part it was. However there were a few gotcha's I ran into so I thought I would document them here in case anyone else runs into the issue. Also, if anyone knows a better way please let me know.

One of the conditions I had to meet was that the video file had to play in a loop continuously, as the application is designed as a Kiosk application. Another condition was that I did not want to display any of the UI controls, just the video itself to avoid users stopping or otherwise altering the video playback.

I decided to use the ActiveX (COM) version of the control for simplicity, so I right clicked the Toolbox and selected the Choose Items option and on the resulting dialog box I selected COM Components, scroll down and select Windows Media Player: (Click on the image to see it full size.)

image

Once that is done we drop the control onto the form, and set it's properties as needed. Some of the properties that I set at design time are shown below:

image

Notably, I set FullScreen to false, and uiMode to none which means that there will be no visible interface, Play, Stop etc will not be displayed to the user allowing me to have more control over the end user experience.

It is important to note that uiMode is not a drop down in the designer, the relevant values for this property are:

  • invisible - Windows Media Player is embedded without any visible user interface (controls, video or visualization window).
  • none - Windows Media Player is embedded without controls, and with only the video or visualization window displayed.
  • mini - Windows Media Player is embedded with the status window, play/pause, stop, mute, and volume controls shown in addition to the video or visualization window.
  • full - Default. Windows Media Player is embedded with the status window, seek bar, play/pause, stop, mute, next, previous, fast forward, fast reverse, and volume controls in addition to the video or visualization window.
  • custom - Windows Media Player is embedded with a custom user interface. Can only be used in C++ programs.

I chose none because I wanted to preserve the option of allowing the interface to be shown for administrative users without messing up the visual layout, none reserves the space necessary to display the UI controls.

With the design time properties set I then wrote the following code to load and play a video file:

   1:          wmpMain.URL = mConfig.VideoFile
   2:          wmpMain.settings.setMode("loop", True)
   3:          wmpMain.settings.autoStart = True
   4:          wmpMain.Ctlcontrols.play()
 

mConfig.VideoFile is a string property that contains a fully qualified path and filename and is used to set the file to be loaded. The second line of code was the tricky part for me, searching for various combinations of .NET and play video in a loop etc resulted in lots of examples of embedding the player in a web page with an attribute called "loop" set to true, but I could not figure out how to implement that in a WinForms version.

Eventually I stumbled on the setMode reference which is rather vague when it comes to intellisense. The available setMode settings are:

Syntax: player.settings.setMode(modeName, state)

    Parameters

    modeName (one of the following)

  • autoRewind - Mode indicating whether the tracks are rewound to the beginning after playing to the end. Default state is true.
  • loop - Mode indicating whether the sequence of tracks repeats itself. Default state is false.
  • showFrame - Mode indicating whether the nearest video key frame is displayed at the current position when not playing. Default state is false. Has no effect on audio tracks.
  • shuffle - Mode indicating whether the tracks are played in random order. Default state is false.
  • state - Boolean specifying whether the new specified mode is active or not.

So in a nutshell that is the basics of getting a video (or audio) file to play in a loop in a WinForms application. There is a lot more you can do with the player, you can programmatically create playlists, react to events the player raises etc. But this illustrates the basics.

Cheers,

Bob Porter


 
Categories: .NET | Programming | VB.NET | Visual Studio


December 7, 2007
@ 10:01 AM

Microsoft has released a Live Lab's (Microsoft Research and Live Services) preview technology package called Volta.

Volta is a framework that allows a developer to potentially build a multi tier application initially as an client application, and then use a technique called "declarative tier-splitting" to identify which pieces of the application run on a server and which pieces run on the client.

This is accomplished by using and XML like declarative markup within the code. With this approach a developer can focus on getting the application designed and functional and then let Volta split the tiers and create the communications "glue" that lets the applications tiers work together.

How this is accomplished is rather interesting, Microsoft decided to go with an MSIL based approach, mostly accomplished in the post compilation area. MSIL code is rewritten to run in Javascript for the client, and ASP.NET for the server side, typically as a web service.

Since Volta works it's magic at the MSIL level, any CLR targeted language is supported, C#, VB.NET, IronPython and others. Visual Studio 2008 is required at this stage, 2005 is not supported and it is unclear if it will ever be.

So show me some code already!

The code shown below is from the Volta Recipe's page. It shows the [RunAtOrigin] custom attribute in use.

namespace VEMashup.Weather
{
    [RunAtOrigin]
    public class WeatherSvcProxy
    {
        public string GetJsonWeatherInfoFor(double lat, double lng)
        {
            var baseUri = @"http://ws.geonames.org/weatherIcaoJSON";
            var uri = baseUri + "?lat=" + lat.ToString() + "&lng=" + lng.ToString();
            var xhr = new Microsoft.LiveLabs.Volta.Xml.XMLHttpRequest();
            xhr.Open("GET", uri);
            xhr.Send();
            if (xhr.Status == 200)
                return xhr.ResponseText;
            else
                return null;
        }  
    }
}

 

This is an example of "tier splitting" via markup. This tells the Volta framework that this code is destined to run on the server. Code not marked will continue to run on the client. This means that as a developer you can postpone deciding how and where to partition your application until the last minute.

The agile developer in me seriously enjoys this particular aspect! Volta technology is seriously early in the life cycle however, so bear in mind that this will change before it gets released.

There is a handy list of known issues you should review before you start playing with the framework.

You could think of Volta as architecture refactoring on steroids. As shown below Microsoft has designed it explicitly with that in mind. (Image from Volta Web Site.)

image001

Bear in mind that you are not limited to 2 tiers, you can retarget portions of your application to as many tiers as you want!

All in all I think this bears some watching!

Cheers,

Robert Porter


 
Categories: .NET | Agile | ASP.NET | Javascript | Programming | Reviews | TDD | Tools and Toys | VB.NET | Visual Studio | XML


By now everyone knows that Visual Studio 2008 has launched, along with the .NET Framework 3.5. This version, previously known as 'Orcas', brings some significant new capabilities with it.

But first things first, installation and out of the box impressions.

I installed 2008 on a system that was clean in the sense that it had never had any of the pre-release versions of Orcas installed on it. I used the Virtual Machines that Microsoft provided to play with the pre-release versions. Wonderful idea judging by all the recent blog posts on how to uninstall the beta's before installing the final release.

If you do need help uninstalling the beta's in order to get the final production version installed, ScottGu has an excellent post on the topic.

Microsoft's official 2008 site has a great deal of good information, tutorials and other examples to peruse, I strongly recommend you check it out.

Anyway, I installed, from a DVD image I burned from the ISO file I downloaded from MSDN. I installed the Professional edition as I do not have access to a Team Foundation Server.

Installation was NOT smooth, the install kept crashing trying to install the .NET Framework 3.5 which was one of the very first steps. So I tried downloading and installing the Framework directly, which also failed.

Looking at the log files I was surprised to see that it was complaining that the 3.0 Framework SP1 was not present and that 3.5 considered that a pre-requisite for installation. Since I was running Vista which came with 3.0 pre-installed I was surprised as I check Microsoft Update weekly and I was sure the SP1 patch had already been installed.

I finally rebooted and logged in as Administrator and re-installed the standalone version of 3.5 again, this time it worked fine. Then I installed 2008 still logged in as Administrator and again everything went fine. The install, including the new MSDN library took slightly over 2 hours.

Once everything was installed I fired up the IDE which took another 10 minutes to configure itself based on my environment selections. Once it was finally up I was able to begin playing around a bit.

The IDE is very similar in appearance to 2005, in fact it is identical, at least initially. The first time I noticed a significant difference was when I opened a project. Visual Studio now uses the native file dialogs as opposed to it's own custom versions. (This is true on XP as well.)

image This is a welcome change especially on Vista as it allows all the functionality of the file dialogs that Windows provides.

There are numerous changes under the hood of course, and many many changes and new features in the languages and Framework which I hope to touch on in a future post.

One other thing I noticed was the fact that Visual Studio now seemed to be a lot faster to load. This is of course a welcome change!

One of those buried features is very welcome and much talked about, multi-targeting! As you can see from the screen shot below this allows you to target an imageapplication at the following frameworks:

2.0, 3.0 or 3.5

This means you can continue working on your 2.0 or 3.0 projects using the newer IDE. Rick Strahl has a great post on moving projects between 2005 and 2008 and back. Basically the project format has NOT changed, and the Solution file changes are minor. This means that you can work on 2.0 targeted applications in either 2005 or 2008 with no particular problems.

I was able to open several 2005 projects, work on them, compile them, run and debug them with no issues. I opened WinForms, ASP and Class library projects with no issues.

One annoyance I did notice was that the help library was much slower to open and seems prone to hanging. The MSDN library is fine when launched standalone, but when launched from within the IDE it is slow to actually show up.

More to come in the next post! Stay tuned.

Cheers,

Robert Porter


 
Categories: .NET | Reviews | VB.NET | Visual Studio


Microsoft has released the latest version of their Power Pack for Visual Basic 2005. Get your copy while it's still spinning!

Microsoft Visual Basic 2005 Power Packs 2.0 - Download

 

Microsoft Visual Basic 2005 Power Packs 2.0 - Information

 

Powerpack2

 

Cheers,

Robert Porter


 
Categories: .NET | Tools and Toys | VB.NET


If you have used Visual Studio 2005 for any length of time, particularly if you have installed the .NET 3.0 bits in either Beta or Release form, you may have suddenly seen some or all of your project templates in the New Project dialog disappear!

I wrote about this and a related issue before but this time around the fix was not so simple. I had installed the WWF and WCF bits along with the .NET 3.0 SDK. Somewhere in the process I lost the Windows Application template for VB.NET.

This lead me to try a number of potential fixes outlined in this blog post on Eric Hammersley's blog. None of the fixes outlined there helped. Neither did uninstalling and reinstalling Visual Studio itself. I also uninstalled the 3.0 bits, all add-ins, etc.

So I started doing some digging, the way the templates, at least the stock ones, seem to work is that there is a series of directories in this folder: C:\Program Files\Microsoft Visual Studio 8\Common7\IDE

The ones of interest are: ProjectTemplates, ProjectTemplatesCache, ItemTemplates, ItemTemplatesCache.

The Templates directories contain the "Master" copies, the Cache versions of the folders contain the copies that are displayed in the New Project or Add Item dialog boxes. They are normally identical.

The command devenv /InstallVSTemplates run from a Visual Studio command prompt should sync the directories up. But this had not happened on my system. Repeated execution of the command resulted in no change.

Then I began to wonder, after all I am running Vista, even though I had made my account a member of the Administrators group to resolve this issue (not recommended by the way), I remembered that on Vista that was actually only making me an "almost" administrator.

So I logged in as the real administrator account, opened a Visual Studio Command Prompt and executed the devenv /InstallVSTemplates command and this time the hard drive lit up and there was a perceptible delay before the command prompt reappeared.

I logged out, logged back in as my own account and launched Visual Studio and the templates were back again!

Further spelunking in the Application event log showed that about two days before Visual Studio had started to complain that my cache directories were not in sync, and that several templates were missing their templatename.vstemplate files.

Templates are a basically zip files which include a vstemplate file that captures the references and directory structure of the template when it is expanded and created. Something had corrupted the cache copies and apparently I did not have enough rights to copy the originals over top of the cache copies.

More disturbing was that reinstalling Visual Studio did not fix the issue! But whatever the reason the files became damaged, logging in as administrator resolved the issue.

Hope this helps someone else!

Cheers,

Robert Porter

UPDATE: I forgot to mention, don't try just copying the directories from the master copies into the cache folders. There is more involved than a simple copy operation and if you just physically copy the files you will lose ALL of your templates. I know, I tried.


 

I recently rebuilt my system, something not unusual for developers. In my case it is at least once every quarter. There is even an industry buzzword for it, re-paving, and it is appropriate as you are in essence taking a work surface that has become potholed and rough, and laying a brand new surface (your OS and applications over top of it).

But in my case the real pain started after I was done. During setup I happened to install SQL Server 2005 first this time, before Visual Studio. Apparently as a result of this a number of strange things happened to Visual Studio's default settings. For one thing, my help collection defaulted to SQL Server, for another I never got the Visual Studio "What kind of developer are you dialog" during install.

But most frustrating of all was the anemic looking New Project Dialog box that now appeared. (Click on the image for a larger version. Notice that there are almost no options, especially as applies to where you want to save a project or if you want a solution created, or if you want to add the project to SourceSafe!!!

Auugghhh! I searched high and low in the various options dialogs and on the web. I found all kinds of information on creating custom templates and repairing damaged templates. But nothing that would indicate how to restore the now missing functionality for the New Project template. However while I was searching for this information I stumbled on to the blog entry on Eric Hammersley's blog, called Missing an item template in Visual Studio 2005? Try this... buried in the comments was an answer to my other mystery, why was my help being pre-filtered for SQL Server?

The comment suggested that you go to Tools | Import and Export Settings | Reset all settings.

Then select your preferred developer type. In my case I selected General Development Settings from the list and Oy! All was right in my world again!

I once again had a full fledged New Project Dialog!! And my help was restored to the correct standard collections!

Ah, life was again good! Here is a shot of the IMHO "good" New project dialog box, again click the image for a larger copy. As you can see it shows the options that were missing.

Some experimentation yielded the fact that the Visual Basic Developer settings generated the anemic dialog. I guess Microsoft thinks VB developers can't handle the real stuff? Anyway, I am back to where I wanted to be. I hope this helps someone else.

Cheers,

Robert Porter


 
Categories: .NET | Programming | VB.NET | Visual Studio


In the last (and first) post of this series we discussed how to create a typed dataset. Now that we have our dataset we need to see how to use it.

But before we go into the details, I want to explain something that I stumbled upon in my research. There is a serious bug in the implementation of the dataset generator. It effects retrieving and manipulating childrows when you are dealing with related tables.

After a great deal of hair pulling, self doubt, and serious coffee consumption, I finally found a series of blog posts that ended up leading me here. The bug has been confirmed and will be released: “thanks again for reporting this. We fixed this problem and the fix will be available in the next Visual Studio release.”

Description
When you create a typed DataSet using the class-designer of VS.NET with a parent- and a child-table, a method is generated on the parentrow-class which should return the childrows. This method uses DataRow.GetChilds with the name of the relationship. This method returns a parentrow-array instead of a childrow-array. The generated method casts it to a childrow-array and thus causes a InvalidCastException.
This bug reduces some of the functionality of the typed dataset in production applications. There is a workaround, but it is a simple kludge, and the end result is that you cannot easily work with related data.
 
Ok, with that said, lets continue on with the series. Next post in this series will take us back into the thick of it. There is still a huge benefit to using typed datasets, just sad that this bug caused such an unfortunate loss of some of that functionality.
 
Cheers,
 
Robert Porter

 
Categories: .NET | ADO.NET | Programming | SQL | VB.NET | Visual Studio | XML


The first thing we need to do is to create the actual dataset. There are a number of ways to accomplish this, however I have found that the most straightforward way is to right click your solution, select Add… then select Dataset from the list.

Datasets can contain many tables or queries or both, I tend to create a dataset per table unless I need to work with joins or multiple tables at once.

There are also a number of options involved in creating a dataset, we are going to explore several of them in this series. The most significant decision you will need to make is whether or not to base your dataset on Stored Procedures or Queries.

In this first example we will be using Queries. But first we need to create the dataset. Once you have selected Dataset you should give it a name, I typically use the table name it is going to be based on, in this example, Employees.xsd

The Dataset Designer will appear, a mostly blank screen that we will drag objects from Server Explorer onto. Go to the Server Explorer window, if it is not visible you can pull down the View menu and select Server Explorer. You should see something like Figure 1: Figure 1.

The Data Connections node is what we are going to work with, right-click it and select the Add Connection… option. Fill in the resulting dialog to connect to your instance of SQL Server and make sure the database selected is “pubs”.

Expand your connection and you will see a listing like Figure 2: ServerExplorer2

As you can see we now have access to a number of items within the database itself, most importantly for this example, the Tables node.

Expand the Tables node and drag the ‘employee’ table onto the dataset designer surface. By default you will get an ‘employee’ dataset and an ‘employeeTableAdapter’ with two methods, Fill and GetData().

Behind the scenes a great deal of code has been generated for you, or will be once you press Save. But we don’t want to accept the defaults, so we are going to make some adjustments.

The first thing you should know is that the process of dropping the table onto the designer surface persisted the connection you created in you applications app.config file. It will have created the app.config file if one did not already exist.

In a production application you would want to alter this connection string to match the production servers connection parameters as well as probably encrypt it. For this example I would suggest that you open your app.config file and rename the connection to “pubs”. My ConnectionStrings section contains the following:

    <connectionStrings>
        <add name="pubs" connectionString="Data Source=DELLXPS;Initial Catalog=pubs;Integrated Security=True"
            providerName="System.Data.SqlClient" />
    </connectionStrings>

I will show you later how to use this renamed connection string as opposed to the one the dataset will be expecting, and explain why I do that.

Next, we need to tweak some of the defaults created for us by the designer. Right-click the employee Dataset and select Configure from the context menu.

You will see a TableAdapter Configuration Wizard pop up. It will show you the query it is using to build and populate the dataset. Click the “Advanced Options…” button and make sure all 3 checkboxes are checked. They usually are by default. The first option tells the designer to create Insert, Update and Delete statements that match the Select statement used.

The second option tells the designer to Use optimistic concurrency which adds intelligence to the Update and Delete statements to allow them to detect if the record(s) they are about to Update or Delete have been modified since they were populated.

The final option, “Refresh the data table” fires a Select after every Insert and Update statement in order to retrieve calculated fields, default values and identity values that are generated by the database.

Once you have done that, return to the Wizard and select Next, you will get the Choose Methods to Generate screen. You will see 3 options, the first two are what we are concerned with for now.

All 3 should again be checked, modify the names of the methods to better reflect what they are doing, in this case returning all employees. See Figure 3 below for an example:

MethodsGen1

Press next once more and you will get Wizard Results screen that shows that the designer has generated all the code, queries and methods we asked it to.

Review the results, then press Finish to return to the designer. Your dataset should now look something like this in the designer:

ModifiedDatasetNotice the highlighted section, this shows that the method names have changed like we wanted.

Thats it! You have now created your first strongly typed dataset.

Next up, we will discuss what exactly this does for you, and how you would use it in code and what advantages you gain from using this construct.

Stay tuned!

Bob Porter

 


 
Categories: .NET | ADO.NET | Programming | VB.NET | Visual Studio | XML


November 28, 2006
@ 11:11 PM

This post is my first attempt to share some of my own experience. Specifically with ADO.NET and Typed Datasets. Scott Guthrie published an excellent series of tutorials on creating a DAL using Typed Datasets.

This is not an attempt to duplicate that series, but it is inspired by it. And I also wanted to do this from a Winforms perspective rather than an ASP.NET view, since I still work in both worlds.

For my first effort, I created a fairly simple application that allows the user to perform simple, Select, Update, Delete and Insert operations against the SQL Server sample pubs database employee table.

SQL Server 2005 does not ship with the pubs or Northwind databases any longer. If you want the scripts to create them you can download them here. These scripts while designed for SQL Server 2000 worked just fine in SQL Server 2005 and created the databases and populated them with data. (They also include pre built databases in the form of MDF and LDF files that you can attach but I prefer to build them from the scripts.)

If you want to download the sample application that goes along with this series of tutorial posts you can do so here. File Attachment: MasterDetail001.zip (71 KB)

I am going to begin this series in earnest tomorrow with the first of the “meat” posts. And let me clearly state, the code in the sample app is very basic, little or no error handling, and not necessarily even the correct way of doing things. I am looking for constructive feedback myself. This application, as it grows, and the tutorials that accompany it are as much a learning exercise for me as anything else.

Cheers,

Bob Porter


 
Categories: .NET | ADO.NET | Programming | SQL | VB.NET | Visual Studio | XML


Julia Lerman started it! And the Bill McCarthy jumped in, and it was all good! “It”, is a description about VB.NET’s Shared definition which equates more or less directly to C# and Java’s Static keyword. VB.NET already had used “Static” for quite another purpose historically.

Both posts do an excellent job of explaining the usage of Shared in VB.NET.  It’s not a new concept, but it throws lot’s of VB’ers because of the holdover baggage from Basic 1,2,3,4,5,6,7 and VB1,2,3,4,5,6 days, not to mention, QuickBasic and all of it’s incarnations.

So if you are ever struggling to understand the differences, or explain them to someone else, either or both of these posts would be a great reference.

Bob Porter


 
Categories: .NET | Programming | VB.NET


There are literally dozens of articles on how to retrieve images from a database and display them in a web page.  The vast majority use one of two variations.

Variation 1

Retrieve the image data, save it to a temporary file and then use the file as the image controls ImageURL or src.

Variation 2

Use an .aspx page with its content type set to an image/xyz type and retrieve the image within the ‘loader’ page and use that page as the image controls ImageURL or src.

I can’t use Variation 1 because I don’t want to create temporary files for a variety or reasons. Variation 2 works for individual images but I need to be able to quickly pull back up to 12 images and I experienced problems using this method within a loop from the calling page.

So here comes Variation 3. I am still not 100% satisfied by this but it works. As an aside since I can retrieve the image as a byte array directly from the database I would love to be able to do something like:

PageLoad Event

Go get image from DB and return it as either a Byte Array or a memorystream

Image1.ImageURL.LoadFromStream(ms)

Alas even though I wish it to be true it does not appear to be possible. However in the Wrox Book “ASP.NET 2.0 MVP Hacks and Tips” I stumbled on what turned out to be my solution in chapter 17 the part titled “Compositing Images with an HttpHandler” which was written by Scott Hanselman

So my solution was a variation on Variation 2, I created a HttpHandler class that in essence does the same thing, it retrieves the image data and then writes the image directly to the output stream and so I can now call my handler and pass in some parameters like this:

Using the html img tag:

<img src="GetImages.ashx?RecID=90&Size=Small">

Or using the server side model:

Image1.ImageUrl = "~/GetImages.ashx?RecID=90&Size=Model"

This method works like a champ even in a loop, and seems to be much faster than the .aspx page method. Not sure why, perhaps an HttpHandler does not have the overhead a full .aspx page does, but it sure works well.

The full code for my solution is below: Note: this was test code, I would NOT recommend using dynamic SQL like I do below in a production application, instead use parameterized sql.

<%@ WebHandler Language="VB" Class="GetImages" %>

    1 Imports System

    2 Imports System.Web

    3 Imports System.IO

    4 Imports System.Drawing

    5 Imports System.Drawing.Imaging

    6 

    7 Public Class GetImages : Implements IHttpHandler

    8 

    9     Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest

   10         'Create the request object and retrieve the QueryString Parameters

   11         Dim req As HttpRequest = ctx.Request

   12         Dim iRecID As Integer = CType(req.QueryString("RecID"), Integer)

   13         Dim sPicSize As String = CType(req.QueryString("Size"), String)

   14         Dim img() As Byte = GetData(iRecID, sPicSize)

   15         ctx.Response.ContentType = "image/gif"

   16 

   17         If (Not (img) Is Nothing) Then

   18             Dim m As MemoryStream = New MemoryStream(img)

   19             Dim image As Image = System.Drawing.Image.FromStream(m)

   20             image.Save(ctx.Response.OutputStream, ImageFormat.Gif)

   21         End If

   22 

   23     End Sub

   24 

   25     Public Function GetData(ByVal iRecID As Integer, ByVal sPicSize As String) As Byte()

   26 

   27         Dim cnn As Data.SqlClient.SqlConnection

   28         Dim cmd As Data.SqlClient.SqlCommand

   29         Dim msTemp As New MemoryStream

   30         Dim strSQL As String

   31 

   32         Select Case sPicSize

   33             Case "Large"

   34                 strSQL = "SELECT LargeImage FROM cyb_Frames WHERE RecID=" & iRecID

   35             Case "Small"

   36                 strSQL = "SELECT Thumbnail FROM cyb_Frames WHERE RecID=" & iRecID

   37             Case "Model"

   38                 strSQL = "SELECT ImageWithModel FROM cyb_Frames WHERE RecID=" & iRecID

   39             Case Else

   40                 strSQL = "SELECT LargeImage FROM cyb_Frames WHERE RecID=" & iRecID

   41         End Select

   42 

   43         Dim connString As String = Web.Configuration.WebConfigurationManager.ConnectionStrings("xyz").ConnectionString

   44         cnn = New Data.SqlClient.SqlConnection(connString)

   45         cmd = New Data.SqlClient.SqlCommand(strSQL, cnn)

   46         cnn.Open()

   47 

   48         Return cmd.ExecuteScalar

   49 

   50     End Function

   51 

   52     Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable

   53         Get

   54             Return False

   55         End Get

   56     End Property

   57 

   58 End Class


 
Categories: .NET | ASP.NET | SQL | VB.NET


January 2, 2005
@ 12:41 AM

Hmmm