Archives

Archives / 2003 / November
  • Just ordered the Longhorn + Whidbey DVD

    Now I've ordered the DVD containing both the Longhorn and Whidbey bits. I'm not sure exactly what builds they are, but at least I'll be able to have a look at what the PDC attendees been posting about for a couple of weeks now :p

    If someone reading this knows the exact content of that DVD, please comment on this post!

    I just have to figure out which of my computers I gonna install it on. A fast one with lots of memory seems needed, if you look at what people has been reported so far. Guess I'll be needing Virtual PC or something similar...

  • Got me a digital camera

    Yeah, I know I'm late. People has been using digital cameras for a long time, but I finally thought that you could get a digital camera with enough quality at a reasonable price. So I bought me a Minolta DiMAGE F200 on sale this weekend, and I'm pretty impressed with it so far. Ok, some pictures really sucks, because you fire away quite often when you know you got space for 100+ hi-res pictures in the camera, but I got a few nice shots the last couple of days. Once I'm comfortable with it, I might post a picture or two...
  • Praise to Reflector, I found a nice StackTraceToString() method

    I must give my praise to the Reflector program, made by Lutz Roeder. I used it to dig down into the depths of TraceListener, to see how the config sections was read and how the DefaultTraceListener wrote it's stacktrace to the file - StackTraceToString(). Saved me some time, it did ;)

    Here's my refactored version:

                /// <summary>

                /// Converts a stacktrace into something more readable

                /// </summary>

                /// <param name="trace">the stacktrace to handle</param>

                /// <returns>a string with the stacktrace</returns>

                public static string StackTraceToString(StackTrace trace)

                {

                      int startFrameIndex = 0;

                      int endFrameIndex = trace.FrameCount - 1;

                      int iFrame;

                      int iParam;

                      int iFileLineNumber;

     

                      StringBuilder sbReturnString;

                      StackFrame frame;

                      MethodBase mBase;

                      ParameterInfo[] arrParamInfo;

                      ParameterInfo paramInfo;

                      sbReturnString = new StringBuilder(512);

                      for (iFrame = startFrameIndex; (iFrame <= endFrameIndex); iFrame = (iFrame + 1))

                      {

                            frame = trace.GetFrame(iFrame);

                            mBase = frame.GetMethod();

                            sbReturnString.Append(" at ");

                            sbReturnString.Append(mBase.ReflectedType.Name);

                            sbReturnString.Append(".");

                            sbReturnString.Append(mBase.Name);

                            sbReturnString.Append("(");

                            arrParamInfo = mBase.GetParameters();

                            for (iParam = 0; (iParam < arrParamInfo.Length); iParam = (iParam + 1))

                            {

                                  paramInfo = arrParamInfo[iParam];

                                  if (iParam > 0)

                                  {

                                        sbReturnString.Append(", ");

     

                                  }

                                  sbReturnString.Append(paramInfo.ParameterType.Name);

                                  sbReturnString.Append(" ");

                                  sbReturnString.Append(paramInfo.Name);

     

                            }

                            sbReturnString.Append(") ");

                            sbReturnString.Append(frame.GetFileName());

                            iFileLineNumber = frame.GetFileLineNumber();

                            if (iFileLineNumber > 0)

                            {

                                  sbReturnString.Append("(");

                                  sbReturnString.Append(iFileLineNumber.ToString());

                                  sbReturnString.Append(")");

     

                            }

                            sbReturnString.Append(Environment.NewLine);

                      }

                      sbReturnString.Append(" ");

                      return sbReturnString.ToString();

                }

          }

     

    Thank you, thank you, thank you Lutz :)

  • A dive into the TraceListener class

    I had a quick dive into the TraceListener class today. I want to use Assert() in the System.Diagnostics.Trace class from an ASP.NET application, and wondered how to configure the output to file, event log and mail. Making the Assert is easy:

    Trace.Assert(errors = 0, "Assert happened!", "A detailed message for you guys!")

    Now, to write that to a file, just add to web.config:

    <system.diagnostics>
      <trace autoflush="false" indentsize="4"/>
      <assert assertuienabled="false" logfilename="c:\AssertLog.txt"/>
    </system.diagnostics>

    When an assertion fails, this is written to the file:

    ---- DEBUG ASSERTION FAILED ----
    ---- Assert Short Message ----
    Assert happened!
    ---- Assert Long Message ----
    A detailed message for you guys!

        at AssertForm.btnOk_Click(Object sender, EventArgs e)  c:\inetpub\wwwroot\AssertTest\AssertForm.aspx.vb(30)
        at Button.OnClick(EventArgs e) 
        at Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) 
        at Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) 
        at Page.RaisePostBackEvent(NameValueCollection postData) 
        at Page.ProcessRequestMain() 
        at Page.ProcessRequest() 
        at Page.ProcessRequest(HttpContext context) 
        at CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() 
        at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) 
        at HttpApplication.ResumeSteps(Exception error) 
        at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) 
        at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) 
        at HttpRuntime.ProcessRequest(HttpWorkerRequest wr) 
        at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType) 

    Now, if you want to write to the Event log, you need to add a listener to the system.diagnostics/trace/listeners section in the web.config. Note that this can also be made through coding:

    <system.diagnostics>
      <trace autoflush="false" indentsize="4">
        <listeners>
          <add name="MyEventListener" type="System.Diagnostics.EventLogTraceListener" initializeData="Johan1"/>
          <!-- if you don't want to write to a file, uncomment this, or remove the assert section below
          <remove name="Default" />
          --
    >
        </listeners> 
      </trace>
      <assert assertuienabled="false" logfilename="c:\AssertLog.txt"/>
    </system.diagnostics>

    The "initializeData" specifies the source of the Event log to write to. Note that the event source must exist first. The following message is written to the Event log:

    Fail: Assert happened! A detailed message for you guys!

    Pity the stack trace isn't written there too, as it is in the log file. You'd have to write your own TraceListener for that, which is what I did to send the trace message in a mail. To do that, inherit from TraceListener and implement a few lines of code. This is a quick and dirty VB sample that I will rewrite and refactor into c# later:

    Imports System.Diagnostics
    Imports System.Web.Mail

    Public Class SmtpTraceListener
      
    Inherits TraceListener

    Private _recipient As String
    Private _sender As String = "some application"
    Private _smtpserver As String = "127.0.0.1"

    Public Sub New()
     
    MyBase.New()
     
    Throw New ApplicationException("SmtpTraceListener must have 'initializeData' attribute specified in config file: recipient,sender,smtpserver")
    End Sub

    Public Sub New(ByVal smtpData As String)
     
    MyBase.New()
     
    Dim arrSmtpData() As String

      'TODO: Change this into a more decent string, like "sender=asdas;recipient=asdas,smtpserver=asdas"
      arrSmtpData = smtpData.Split(","c)
      If arrSmtpData.Length > 0 Then
       
    _recipient = arrSmtpData(0)
     
    End If

      If arrSmtpData.Length > 1 Then
       
    _sender = arrSmtpData(1)
     
    End If

      If arrSmtpData.Length > 2 Then
       
    _smtpserver = arrSmtpData(2)
      End If

    End Sub

    Private Sub send(ByVal subject As String, ByVal message As String)
      SmtpMail.SmtpServer = _smtpserver
      SmtpMail.Send(_sender, _recipient, subject, message)
    End Sub

    Public Overloads Overrides Sub Write(ByVal message As String)
      send(
    "application message", message)
    End Sub

    Public Overloads Overrides Sub WriteLine(ByVal message As String)
      Write(message)
    End Sub

    Public Overloads Overrides Sub Fail(ByVal message As String, ByVal detailMessage As String)
      send(message, detailMessage)
    End Sub

    End Class

    Note that a stuck smtp-data in the "initializeData" attribute, that's the way the DiagnosticsConfigurationHandler reads the config section and initalize the listener constructor. A cooler way to do this is to add your own config-section, which I will do later on I think.

    Now, just add the listener to the web.config file:

    <add name="MySmtpListener" type="AssertTest.SmtpTraceListener, AssertTest"

    initializeData="recipient@company.com,sender@company.com,smtp.company.com"/>

    I guess there will be better TraceListeners in Whidbey and Longhorn, but I haven't got my hands on those bits yet.

  • Watching Your Server Processes

    Kent Sharkey has published an article on MSDN, which looks useful for ASP.NET application developers. Summary:

    "Learn how to create an ASP.NET HTTP Handler to view the life and death of the processes used by a Web site. In addition, learn how to create a configuration section handler."

    I like the end statement:

    "Once the HTTP Handler is created, and in place, you should be much more aware of what is happening in this important process. And you'll have time for a coffee, instead of having to hunt down the reason your Web site process restarted."

  • [interop] Consuming a .NET Typed DataSet from Java (continued)

    I got a question about what libraries JDeveloper uses for the soap proxy, and I had a quick look at that. I've just started doing soap stuff in Java, but it seems that the proxy stub that Jdev automatically produce for you uses the org.apache.soap package for most of the soap handling and the oracle.soap package for the http transport.

    For my simple code experiment, the request is sent as a org.apache.soap.messaging.Message and the response is received into a org.apache.soap.Envelope. The body goes into a org.apache.soap.Body that contains a vector of body-entries, but the interesting entry is the first one, which is an org.w3c.dom.Element containing the returned XML-data. This code is automatically generated by Jdev, pretty similar to the proxy code generated by VS.NET I guess.

  • Off to aikido practice

    I've spent the whole day moving a new asp.net application from test to production. Amazing how things fail just because there is a tiny, tine difference between the test and production site :/

    Things work fine now anyway, and I'm off to my aikido practice!! Feels so good to toss people around after a release :D

  • [interop] Consuming a .NET Typed DataSet from Java

    Well, as with most things it's dead simple once you get the hang of it. With the help from Jan-Erik, Jdev 10g and XML Spy 4.0 it's not that hard. First I coded up a couple of Web Services in .NET. One method returned a typed DataSet containing both authors and titles, another returned a "typed" XML document (node actually) version created from the typed DataSet:

    public XmlNode GetTypedXmlDocument()
    {
       PubsDataSet dsp = GetTypedDataSets();
       XmlDocument xmlDoc =
    new XmlDocument();
       xmlDoc.PreserveWhitespace =
    true;
       xmlDoc.LoadXml(dsp.GetXml());
       return xmlDoc.DocumentElement;
    }

    It's very simple to generate SOAP client code from within Jdev that will call my Web Service methods, so I won't get into that. Both my .NET web methods will return an org.w3c.dom.Element (Jdev detects this automatically) and if you're into XML and XPath, you can very well start hacking away at the XML data you got. But being used to .NET typed DataSets, this isn't what I like. So, what you do is get hold of XML Spy and point at the schema location of the typed PubsDataSet in it. When the schema has been loaded into XML Spy, goto DTD/Schema->Generate Program Code... and select Java as the program language. XML Spy will now generate a couple of classes for you based on that Schema, which you now can import and use in Jdev:

        Service1Stub ws = new Service1Stub();
       
        try
        {
          //Testing typed DataSet, need to manipulate the stub code
          Element e = ws.GetTypedDataSets();
          PubsDataSetType ds = new PubsDataSetType((Element)e.getElementsByTagName("PubsDataSet").item(0));
          System.out.println(" --- Typed DataSet --- ");
          System.out.println("    No of authors: " + ds.getauthorsCount());
          System.out.println("    No of titles: " + ds.gettitlesCount());
          System.out.println("    An author: " + ds.getauthorsAt(0).getau_fname());
         
          //Testing "typed" xml document
          ds = new PubsDataSetType(ws.GetTypedXmlDocument());
          System.out.println(" --- Typed XmlDocument --- ");
          System.out.println("    No of authors: " + ds.getauthorsCount());
          System.out.println("    No of titles: " + ds.gettitlesCount());
          System.out.println("    An author: " + ds.getauthorsAt(1).getau_fname());
        }
        catch (Exception e)
        {
          System.err.println("Exception getting DataSet:" + e.toString());
        }

    Sorry about the non-existing colors ;)

    As you can see, for the first sample you need to get hold of the first occation of the "PubsDataSet" node because the typed DataSet contains schemas for author and titles, which the XML Spy generated classes doesn't like :) This is not needed for the "typed" xml document, because it only contains the xml data we're interested in. The first example (the typed DataSet) also need a little hack in the Jdev generated service-stub:

      public Element GetTypedDataSets() throws Exception
      {
        URL endpointURL = new URL(_endpoint);

    ...removed a lot of proxy code...

    //    return (Element)fromElement((Element)responseData.elementAt(0), org.w3c.dom.Element.class);
          return (Element) responseData.elementAt(0);
      }

    That's about it. As you can see, the "typed" xml document, need no cryptic code-changes at all. Just feed the return XML Element to the PubsDataSetType constructor, and you're home. The output from above is:

     --- Typed DataSet --- 
        No of authors: 23
        No of titles: 18
        An author: Johnson
     --- Typed XmlDocument --- 
        No of authors: 23
        No of titles: 18
       An author: Marjorie

    I'll ask Jan-Erik and see if we cannot write some kind of article about this. If anyone is interested that is :)

  • Filtering strongly typed DataSets

    Is there an easier way to filter on stongly typed DataSets?

    public PubsDataSet GetFilteredTypedDataSets(PubsDataSet dsp, string filter)
    {
       //filter the rows from a copy of the authors table
       DataRow[] foundRows = dsp.authors.Copy().Select(filter);

       //delete the authors from the typed dataset
       dsp.authors.Clear();

       //merge the filtered rows back to the typed dataset
       dsp.Merge(foundRows,false,MissingSchemaAction.Add);

       return dsp;
    }

    If you don't want the DataRow merged back to the typed DataSet, you can work with them directly by casting the DataRow to a typed version:

    foreach(PubsDataSet.authorsRow r in foundRows)
       Console.WriteLine(r.au_fname);

    DataSets are really nice, and strongly typed DataSets even more so :)

  • I need more memory!

    I'm a total nerv wreck after 30 minutes with Oracle jdev 10g. The editor is cool, but I have too little memory on this machine to play with it. The memory swapping on disk makes me crazy, I can't continue I'm afraid. I'll have to use my laptop (which I'm not allowed to plug in here where I sit at the moment) and use my JOS-player (combined mp3 player and USB Flash Disk) to transfer files between the computers :)

    Later today (if time permits), I'll try to consume a .NET DataSet from a .NET web service from java. My friend Jan-Erik has already done it, both with and without the help of XML Spy. I want the know-how too and you better be prepared. Suddenly the boss pops in and asks you to do some java/net interop :)

  • Nemo was great

    Amazing animations, just amazing...

  • Off to see Nemo

    We're (my family that is) off to see the Nemo movie together with some friends. The few scenes I've seen from it looks really cool. Gonna watch the dubbed version (in Swedish) so the kids can understand it better. I'll buy the original on DVD later on.

    I'm sure you've all seen this picture, but I love it :)

  • 2003 Visual Studio .NET Documentation Update

    Bah, I've just downloaded the Visual Studio .NET 2003 Documentation Update, but the exe refuse to work properly. I get a "... is not a valid Win32 application." in my face. Guess I'll have to try another download :/

    UPDATE: I cleaned the IE temporary files and went to the download page and downloaded the file again. Now it works fine :)

    Download page is here: http://www.microsoft.com/downloads/details.aspx?familyid=a3334aed-4803-4495-8817-c8637ae902dc&languageid=f49e8428-7071-4979-8a67-3cffcb0c2524&displaylang=en

  • [refactoring] Refactoring is fun

    I'm a fan of Martin Fowler and of refactoring. I've used rafactoring add-ins for different Java-editors the last years, and was very happy to read about the rafactoring support in the upcoming Whidbey. Until then, I'm using using the C# Refactoring tool from Xtreme Simplicity, which has refactoring support for the following methods:

    Extract Method 
    Change Method Signature 
    Decompose Conditional 
    Extract Variable 
    Extract Superclass 
    Extract Interface 
    Copy Class 
    Push Up Members 
    Rename Type 
    Rename Member 
    Rename Parameter 
    Rename Local Variable 
    Find References 
    Tidy Imports 
    Encapsulate Field 

    I've only tried a couple of them yet, like the "Extract Method", "Tidy Imports" and "Rename Xxx" and they work great. Pity there isn't support for VB.NET, since I use that alot too.

  • Extending the Exception Management Application Block for .NET

    I'm looking at adding a few features to the Exception Management Application Block for .NET. First, I'm adding support to write an Event ID to the BaseApplicationException type and to the actual event written to the event log. Looks pretty good so far.

    After that I think I'm gonna create a publisher that publishes extra information for ASP.NET exceptions. Like dumping the server variables, referrer and so on.

  • Proxy property of the HttpWebRequest

    I've had problems getting through the http proxy where I work at the moment, but I got excellent help from Luke Hutteman, the author of the RSS Aggregator SharpReader. It all works fine now:

    ...

    Dim webReq As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)

    Dim newProxy As WebProxy = New WebProxy(host,port)

    If username.Length = 0 Then

       newProxy.Credentials = CredentialCache.DefaultCredentials

    Else

       Dim cred As New NetworkCredential(username, password)

       Dim credCache As New CredentialCache

       credCache.Add(newProxy.Address, "Basic", cred)

       credCache.Add(newProxy.Address, "Digest", cred)

       newProxy.Credentials = credCache

    End If

    newProxy.BypassProxyOnLocal = True

    webReq.Proxy = newProxy

    'some proxys need this too

    webReq.Credentials = newProxy.Credentials

    Dim objResponse As WebResponse = webReq.GetResponse

    ...

    Something like that :)

  • Fugitive in my own house

    My wife is hosting a Tupperware party downstairs, so I grabbed my laptop and ran upstairs. Thank God I installed a LAN when I built the house! I've not used this laptop for quite some time, been running windows update for halv an hour now :/
  • Alien Director's Cut

    Ah, this will be something worth seeing I'm sure. I wonder what differs from the original movie. I heard something about it being even shorter (!) than the original. Anyone seen it yet?
  • Good morning...

    Some people thought that my post about Emotional Query Language was fun, except for this guy calling himself "Satan"...duh. I had no idea that the son of a bitch was surfing the Internet, thought he was too busy making real life a hell for people ;) Needless to say, I removed his comment.

    I read a Swedish article about the soon to be released "Two Towers" extended DVD. They've added 45 minutes to it! Yay!

  • Oracle JDeveloper 10g and memory consumption

    I just installed the preview of Oracle JDeveloper 10g (correct, I was not at the PDC so I do not have Whidbey, Longhorn, Avalon, Indigo, [insert favorite pdc buzzword here] to play with :( It happens that I have to do some Java coding now and then, and I wanted to see what the new features were.

    Anyway, what amazes me is the impressive amount of memory JDev occupies just to get running! I wish I could post a picture of it, but Task Manager reports the Mem Usage of jdevw.exe to 94 232 K! And I've not even opened up a project yet... phew! On my machine VS.NET 2003 chews some 20 Meg of memory right after startup, and if I load up a pretty big project, it rise up to 40 Meg.

    JDev 10g do have some very neat features though, which I know is appreciated by the regular Java developers. The box I installed this on only has 256 Megs of mem, so I think I have to move this over to another machine if I want to be able to run anything else on the same machine at the same time. I must say the installation of Jdev is very neat - just unzip the whole stuff and run. A bit faster than installing Visual Studio.NET ;)

  • EQL - Emotional Query Language

    If computers had emotions... wouldn't it spice up life as a programmer if you could get better performance out of the boxes from being a bit nice to them? Imagine SQL Server having feelings, and you would have to ask it nicely to make it give you what you really want. Say you just installed the Emotional Query Language version and you need a list of names from the authors table in Pubs, and you tell SQL to:

    SELECT * FROM authors

    Server: Msg 2812123, Level 12, State 123, Line 1
    You forgot the magic word 'PLEASE'.

    Aha, you think. The bitch is in a bad mood today. So, ok, you change your query to something like:

    PLEASE SELECT * FROM authors

    Server: Msg 1231256, Level 534, State 341, Line 1
    Be more specific, you don't need all those columns, do you?

    Aww, come on! I know I don't need all those columns, but I might need them in the future! Ok, ok, I decide be more specific and change the query again (cross my fingers and hopefully it will even use a clustered index scan):

    PLEASE SELECT au_id, au_fname FROM authors

    Server: Msg 12335, Level 11, State 897, Line 1
    Busy serving IUSR_JENNY.

    What??! Jenny is using my database and you prefer to serve her? In a fit of rage you pull out your box of Oracle 9i CDs, all 23 of them, and wave them in a really threatfull way in front of the screen, screaming: "See all these Oracle disks!!? Yeah? Start serving me or I'll uninstall you, you miserable excuse for a program!"

    Which will probably make the situation worse... Come to think of it, EQL maybe isn't such a good idea after all.

  • Go Joseph Go

    A couple of days old, but still one of the funniest blog-posts I've read this morning. Joseph Duemer takes on "an infantile egoist", which has spammed his blog. Check it out here.

  • Formatting of Date and Time in .NET

    I don't know about you, and perhaps this is just an issue in non-english speaking countries, but the formatting of date and time has always been an issue in our old applications built with ASP and COM components. Especially VB6 components. Some developers settled with setting the default region of the server OS to whatever language the web application was supposed to be read in and then used VB functions such as Now, Time and Date to get and display the date or time formatted according to the regional settings. Well, this worked well until you had to move the application to another box or when some administrator or other changed the default regional settings to something else.

    The solution to this was to build or format the date and time strings yourself, either by concatenating or by using the built-in Format method. But now the Framework library contains a number of powerful features, which help the application developer present date and time strings in the correct format for the user. This is called Globalization, and achieved by setting the specific “culture” of the running process or the current thread. There is no longer need to build date and time strings manually, and I recommend web developers to use one of the following methods for setting the correct culture in their ASP.NET applications:

    1. Set the culture in Web.Config
    2. Set the culture of the current request thread
    3. Set the culture parameter of the ToString method

    I guess you can also set the culture of a Console or WinForm application in the application configuration file just as in the web.config, but I've not tried that yet.

    I always keep date and time data in a Date or a DateTime structure. The Date class is only available in VB.NET but the compiler will translate that into a DateTime structure. The DateTime contains a few convenient methods for formatting date and time strings, which I use most of the time:

    • ToShortDateString
    • ToShortTimeString
    • ToLongDateString
    • ToLongTimeString

    The value of the DateTime instance is formatted using different format characters and passed through the ToString method. As the .NET documentation for DateTime says, the return value for the ToShortDateString is identical to the value returned by ToString ("d", null).

    If a more fine-grained control is needed, you can use the overloaded ToString(format) methods or the static Format method from the Microsoft.VisualBasic namespace, which should be familiar to VB6 developers. I still prefer the different ToXxxxString methods provided by the DateTime class.

    To get the current date and time in VB.NET, you can use either the .NET DateTime or the Date class, as I wrote above. Or, you can use the Now property, which is part of the DateAndTime module from the Microsoft.VisualBasic namespace and also returns a Date object containing the current date and time. Something like this:


            Dim Date1 As String = DateTime.Now.ToShortDateString()
            Dim Date2 As String = Now.ToShortDateString()
            Dim Date3 As String = Date.Now.ToShortDateString()
     
    To get the current date and time in C#, you must use the DateTime structure, since the Date class doesn't exist: 


           string Date1 = DateTime.Now.ToShortDateString();
           DateTime dt1 = DateTime.Now;
           string Date2 = dt1.ToShortDateString();

    I guess you could import the Microsoft.VisualBasic namespace and use the Now function from it, but hey... :)

    Have to rush home now, so I'll post some samples of how to set the culture tomorrow or so.

  • Not much of a revolution

    GAHH, I've just witnessed two of the worst speakers in modern history at the Oracle/Java seminar. Ok, the first guy could talk, but it was so boring people starting to drift off after a couple of minutes. You've got this big theater with 400 programmers sitting there waiting for some cool code tricks, and this guy spends 30 minutes bragging about his company! Not a single row of code, not even a simple if-statement! The other guy was just embarrassing, no one had any idea what he was talking about, least himself. Poor guy... I guess it was worth it, since we all got to see the last Matrix movie afterward ;)

    Not sure why they call it Matrix Revolutions though, there wasn't much of a revolution in it. It had a great deal of action, and the big fight in the hangars of Zion was just amazing. I must admit I didn't really understand the ending. If someone can explain to me about the Oracle and that old guy in the end, please post a comment or two...

    Ah, what the heck, it was good action anyway :D

    Tomorrow, it's back to writing .NET guidelines. See if I can post something useful for once...

  • Sleeping with the enemy...

    This is my first post on the ASP.NET Weblogs, so first, thanks to Scott for letting me in ;)

    I'm soon off to enemy territory, a free seminar held by Oracle and Sun and lots of Java talk. The fact that they will end the seminar by showing the new Matrix movie has absolutely nothing to do with me going there ;)

    I'll let you know what I thought about the movie later tonight. Hopefully it'll be better than the second.