January 2007 - Posts

From the website:

ASP.NET AJAX is a free framework for quickly creating a new generation of more efficient, more interactive and highly-personalized Web experiences that work across all the most popular browsers.

With ASP.NET AJAX, you can:

  • Create next-generation interfaces with reusable AJAX components.
  • Enhance existing Web pages using powerful AJAX controls with support for all modern browsers.
  • Continue using Visual Studio 2005 to take your ASP.NET 2.0 sites to the next level.
  • Access remote services and data directly from the browser without writing a ton of complicated script.
  • Enjoy the benefits of a free framework with 24x7 technical support provided by Microsoft.

Download it now! More information on http://ajax.asp.net.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

The story

A few days ago I deployed Community Server 2.1 for ASP.NET 2.0 to my web space during maintenance. Everything went just fine, thanks to the wonderful work of Telligent. It's really xcopy deployment and running a few scripts on the SQL Server database. Nevertheless, I was pretty annoyed when I had to upload 3878 files and 320 folders (that's how big the extracted .zip file of CS21 is) under circumstances of Passive FTP and regular connection resets. To summarize, this took a few hours due to the large number of small files and associated data connections for file transfers. (Where's the good old time I just had Terminal Services access to my web server, so that I could download the zip directly on the server and unzip it over there? <g>)

So, I thought to myself, how to overcome this issue? This is the solution I came up with.

 

Unzipping in ASP.NET

The idea: upload the .zip file and extract it on the server. How to do? Using ASP.NET and some library with the rather weird feeling name of java.util.zip. Yes indeed, my first ASP.NET web project with J# is a fact:

Before I continue with the code, I want to stress the following disclaimer:

DISCLAIMER: Run this code at your own risk. Keep in mind you'll be extracting files on a remote web server and you could overwrite files if you're unzipping to the wrong location. I'm not responsible for any possible data loss caused by running this code. You should adapt this code to match your own scenario and fully understand what's going on before pulling the trigger (either by pressing F5 in some way or another, or by hitting the ASP.NET page in question). The code in this article hasn't been subject of thorough testing and therefore should be used with care.

On to the code now. First create the following page:

with two text boxes, called txtZipFile and txtExtractTo. Next, attach an event handler to the Go!-button:

1 protected void btnGo_Click(Object sender, EventArgs e) 2 { 3 String folder = this.get_Server().MapPath(txtExtractTo.get_Text()); 4 System.IO.Directory.CreateDirectory(folder); 5 6 try 7 { 8 java.util.zip.ZipFile file = new java.util.zip.ZipFile(this.get_Server().MapPath(txtZipFile.get_Text())); 9 10 // 11 // List for the directories that are in the zip-file. Will be sorted to deduce the creation order. 12 // 13 ArrayList directories = new ArrayList(); 14 15 // 16 // Look for directory entries in the zip file. 17 // 18 java.util.Enumeration entries = file.entries(); 19 while (entries.hasMoreElements()) 20 { 21 java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.nextElement(); 22 if (entry.isDirectory()) 23 directories.Add(System.IO.Path.Combine(folder, entry.getName())); 24 } 25 26 // 27 // Sort the directory list. This will yield the correct order for creation. 28 // 29 directories.Sort(); 30 31 // 32 // Create the directories. 33 // 34 IEnumerator ie = directories.GetEnumerator(); 35 while (ie.MoveNext()) 36 System.IO.Directory.CreateDirectory((String)ie.get_Current()); 37 38 byte[] buf = new byte[1024]; 39 40 // 41 // Look for file entries in the zip file. 42 // 43 entries = file.entries(); 44 while (entries.hasMoreElements()) 45 { 46 java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.nextElement(); 47 48 if (!entry.isDirectory()) 49 { 50 // 51 // Get the input stream and create the output stream. 52 // 53 java.io.FileOutputStream fos = new java.io.FileOutputStream(System.IO.Path.Combine(folder, entry.getName())); 54 java.io.InputStream is = file.getInputStream(entry); 55 56 // 57 // Copy the bytes. 58 // 59 int n; 60 while ((n = is.read(buf, 0, 1024)) > -1) 61 fos.write(buf, 0, n); 62 63 // 64 // Clean up. 65 // 66 fos.close(); 67 is.close(); 68 } 69 } 70 71 file.close(); 72 } 73 catch (java.io.IOException ex) 74 { 75 } 76 }

Wow, this should be my first piece of (crappy) Java-code on my blog :-). A few notes on how it works:

  • Line 3: Server.MapPath is called to find the "extract to" location. This folder is created in line 4.
  • Line 8: An instance of java.util.zip.ZipFile is created to manipulate the zip file (more specifically, to read contents from it).
  • Lines 10-36: Find all the folders in the zip file (when is LINQ coming to J# -- I just wanted to write from e in file.entries() where e.isDirectory() order by e.getName() select e.getName()) and create the folders in order (a little trick that seems to work fine).
  • Lines 40-69: Now find the files and extract it to the target folder's subfolder indicated by the zip entry name (basically Path.Combine does all the work for us).
  • Lines 73-74: Some ugliness thanks to these wonderful checked exceptions in the world of Java :-).

Note: This code requires that the server is configured so that the "ASP.NET identity" (ASPNET, the app pool identity, ...) has sufficient rights to create folders and files on your web space (okay over here). The J# runtime should be present on the server machine as well to have access to the java.util.zip library.

Enjoy!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

I've been tagged by Alex Thissen, so let's join the club and share a few things you might not know about me yet:

  1. I'm a 100% non-alcoholics guy, that means no bear, wine or liquor bonbons :-).
  2. My sign is Aquarius, I was born on 11th February 1983 in Zottegem, Belgium. Incidentally, my favorite drink is Aquarius for the moment, after having been addicted to Coke and Red Bull.
  3. Movies don't interest me much, you won't find me in cinemas except for giving presentations from time to time. One exception are movies and series (Blackadder) with Rowan Atkinson, maybe because he's an engineer too (believe it or not).
  4. I'm a huge fan of snooker. Although it's a long time ago I played some snooker myself, I still love to watch it :-).
  5. For the moment, I don't have a driver's license and no (because so many people ask) I don't miss it. I manage to get everywhere I need so I'm fine.

Time for me to tag some others now. Here are my victims:

  • Gunther Beersaerts - one of the first people I learned to know at Microsoft, with a deep focus on SQL Server 2005 stuff and DataDude and not to forget a top speaker.
  • David Boschmans - officially called a "Developer Platform Advisor" for Microsoft Belux, David is the ultimate resource for all sorts of dev topics in the wonderful world of .NET.
  • Peter Himschoot - a colleague community member in Belgium, employed at U2U and president of Visug.
  • Tom Mertens - the one and only responsible for Microsoft's developer audience in Belgium, organizing great events, driving the local MSDN website, and doing much more.
  • Hans Verbeeck - a guy at Microsoft EMEA who isn't afraid of spending long nights in discos after Microsoft events <g>.
Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

No further comments needed. Here's the link:

Microsoft Pre-release Software Visual Studio Code Name "Orcas" - January 2007 Community Technology Preview (CTP) (VPC image)

Microsoft Pre-release Software Visual Studio Code Name "Orcas" - January Community Technology Preview (CTP) (Installable Bits)

Highlight remains LINQ ("the LINQ wave") but don't forget to check out other highlights as well!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

A few days ago I posted the following two posts for this C# Quiz:

The question was the following:

What's the difference between the following two code fragments?

Fragment 1:

class Bar { private int i = 123; public Bar() { } }

Fragment 2:

class Bar { private int i; public Bar() { i = 123; } }

Some of my readers got the point right and saw the difference with or without aid of my extra code sample:

1 using System; 2 3 class Foo 4 { 5 public Foo() 6 { 7 Console.WriteLine(this.ToString()); 8 } 9 } 10 11 class Bar1 : Foo 12 { 13 private int i; 14 15 public Bar1() 16 { 17 i = 123; 18 } 19 20 public override string ToString() 21 { 22 return i.ToString(); 23 } 24 } 25 26 class Bar2 : Foo 27 { 28 private int i = 123; 29 30 public Bar2() 31 { 32 } 33 34 public override string ToString() 35 { 36 return i.ToString(); 37 } 38 } 39 40 class Program 41 { 42 static void Main() 43 { 44 new Bar1(); 45 new Bar2(); 46 } 47 }

This piece of code will print

0
123

The reason? Simply stated, field initializers are guaranteed to be executed prior to all constructor logic. In Bar2 this means that i will have the value 123 right before the statements in the constructor (or the default constructor) are executed. Still, this doesn't explain the difference completely. In addition, one needs to know that base constructors are called before all subclass constructor logic happens. In this case it means the following call chain:

new Bar2()
-> new Foo()
   -> new System.Object()

Once this chain of calls has completed, constructor logic is exected. In the case of Bar2, the constructor is empty. In the call chain above, the field i is guaranteed to be set to 123. Basically the assignment happens as the first instruction of the Bar2 class's constructor, before the base constructors are called:

30 - public Bar2()
31 - {
28 -    private int i = 123;
 5 -    public Foo()
 6 -    {
           <outside scope - System.Object::ctor>
 7 -       Console.WriteLine(this.ToString());
 8 -    }
32 - }

In Bar1 the situation is different, since the field i is not initialized:

15 - public Bar1()
16 - {
 5 -    public Foo()
 6 -    {
           <outside scope - System.Object::ctor>
 7 -       Console.WriteLine(this.ToString());
 8 -    }
17 -    i = 123;
32 - }

The IL equivalents of both constructors are displayed below:

Bar1:

.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 18 (0x12) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void Foo::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldc.i4.s 123 IL_000b: stfld int32 Bar1::i IL_0010: nop IL_0011: ret } // end of method Bar1::.ctor

Bar2:

.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 18 (0x12) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldc.i4.s 123 IL_0003: stfld int32 Bar2::i IL_0008: ldarg.0 IL_0009: call instance void Foo::.ctor() IL_000e: nop IL_000f: nop IL_0010: nop IL_0011: ret } // end of method Bar2::.ctor

Observe the base constructor calls which occur in IL_0001 for class Bar1 and in line IL_0009 for class Bar2. For our sample, this means that the base constructor's Console.WriteLine(this.ToString()) call happens before i has been set in class Bar1 and after i has been set in class Bar2. Since ToString is a virtual method, it's called on Bar1 and Bar2 respectively, both classes which have access to the field i, which gets printed out.

The moral of the story: field initialization code gets rewritten as follows:

class Child : Parent { private int i = 123; private int j = 456; public Child() { //constructor logic } }

becomes (pseudo-code):

class Child : Parent { private int i; private int j; public Child() { i = 123; j = 456; Parent.ctor(); //constructor logic } }

Have fun!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

If you can read this, blogging from Word 2007 RTM works just fine.

Please ignore this message.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

In yesterday's post for this quiz, I asked for the difference between two little code fragments. Let's take it one step further today, so take a look at the following:

Can you predict the output of the application? And why do you observe that particular output?

Stay tuned for the answer tomorrow!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Saw a good question on the discussion lists yesterday:

What is the difference (practically) in assigning a variable value in the variable declaration line and in the constructor?

So, here's the quiz question: What's the difference between the following two code fragments?

Fragment 1:

class Bar { private int i = 123; public Bar() { } }

Fragment 2:

class Bar { private int i; public Bar() { i = 123; } }

Tip: the difference is rather subtle.

I'll post another code fragment for this quiz tomorrow "on the road to the solution".

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts