Article: Customizing generated Web Service proxies in Visual Studio 2005#

I'm proud and honored to see that my first article has been published on the Microsoft Belux website:

Customizing generated Web Service proxies in Visual Studio 2005

As the title implies, it talks about how you can customize the Web Service proxies that are generated by the "Add Web Reference" dialog box in Visual Studio 2005 or the WSDL.exe tool through a new mechanism introduced in .NET 2.0 called "Schema Importer Extensions".

Don't hesitate to let me know if you liked or disliked the article or the proposed solution!

Articles | Blog | Programming | .NET | VS.NET | Whidbey
Tuesday, November 29, 2005 9:47:26 PM (Romance Standard Time, UTC+01:00) #    Comments [8]  | 

 

Downloading Visual Studio 2005 RTM#

The RTM version of Visual Studio 2005 has finally arrived! Downloading the goodies is still quite a pain though, I couldn't get any download started through MSDN Subscriptions yesterday, my colleague had more luck after trying a few times this afternoon but then he had a little hickup as well:

Fortunately, File Transfer Manager can resume :-)

Other than that, it seems that the Visual Studio Team Suite Trial Edition that was available yesterday has already been removed from the Subscriptions download page, as well as the Beta 3 Refresh of Team Foundation Server (also spotted by Sam Gentile). What's up with that?

Blog | Programming | .NET | VS.NET | Whidbey
Friday, October 28, 2005 3:50:25 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

 

Are you ready for the launch?#

In just two weeks, Microsoft Belux is organizing what I personally think is the biggest launch event in the last couple of years: on November 10, SQL Server 2005, Visual Studio 2005 and BizTalk 2006 will finally be released to manufacturing!

Developers and IT professionals are invited to celebrate the launch of the new versions of Visual Studio, SQL Server and BizTalk Server together with us. The event will start with a keynote session by S. Somasegar, Corporate Vice President at Microsoft Corporation.

Further some of the best speakers and subject matter experts worldwide will entertain you. Make sure you bring along your most burning SQL Server 2005 or Visual Studio 2005 questions.

Later in the evening we offer a walking dinner and a party to remember...

You can find more information and subscribe for the event on the Microsoft Belux Launch site.

I've been asked to hang out at the Ask-The-Experts area as a Visual Studio Expert, so if you're there: come say hi and ask me some tough questions :-)

See you there!

Blog | General | Programming | .NET | VS.NET | Whidbey
Wednesday, October 26, 2005 6:36:12 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

Copy To Output Directory#

Here's a tiny new feature in Visual Studio 2005 that caught my attention:

Pretty nice, now you don't need a post-build step with macros anymore to get some files into the output directory.

It doesn't seem to work all-the-way though: when running a Test Project, this setting won't copy the file into the running test's current directory. Other than that, it's still nice to see the "little things" that so often make the difference...

Blog | Programming | .NET | VS.NET | Whidbey
Thursday, October 20, 2005 10:22:08 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

Generics & Invariance: An Interesting Problem#

Setting The Stage: Invariance

I had a rather interesting problem using generics in C# 2.0 today, but before I dig in to the actual issue, let me briefly introduce you to the "invariant" nature of generics.

As you know, you can certainly assign a string to a variable of type object because string is a subclass of object:

string s = "some value";
object o = s; // No problem

Now suppose you have a List<object> and a List<string>, which are generic types describing a list of objects and a list of strings, respectively. Given that string is a subclass of object, you might assume that you can assign this List<string> to a List<object> as well:

List<string> strings = new List<string>();
List<object> objects = strings; // Fails

The compiler, however, rudely disagrees with you: error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<string>' to 'System.Collections.Generic.List<object>'. This is because generic types in .NET are said to be invariant, which means that they don't adhere to the same inheritance tree as their type parameters (string and object in this case).

Although similar in nature, arrays don't share this nature and are said to be covariant, which means that the following code is perfectly legal:

string[] strings = new string[] {};
object objects[] = strings; // No problem

For more information and the reasoning behind this, check out Rick Byers' excellent post on Generic type parameter variance in the CLR.

The Problem Manifestation

With that in mind, imagine the following class hierarchy:

So there are two interfaces describing a document (IDocument) and a cabinet (ICabinet) which basically holds a generic list of these IDocuments. The Document class implements the IDocument interface in the obvious way. The interesting part is the Cabinet class:

public interface ICabinet
{
string Name { get; }
string Location { get; }
List<IDocument> Documents { get; }
}
public class Cabinet : ICabinet
{
  private string name = null;
  private string location = null;
  private List<IDocument> documents = new List<IDocument>();
 
  public string Name { get { return name; } }
  public string Location { get { return location; } }
  public List<IDocument> Documents { get { return documents; } }
}

To implement the interface, the Cabinet class has to expose the List<IDocument> through the Documents property, and since generics are invariant, this means that the return type cannot be List<Document> (note the use of the class here, not the interface). This implies that the private documents backing field must also be a List<IDocument> in stead of a List<Document>, for the same reason.

Now there's currently no link between the concrete cabinet type and the concrete document type and I really want this Documents property on my Cabinet class to expose a List<Document>, so that's a problem. The reason I need this, is that my cabinet class will be exposed over a Web Service and must therefore be serializable. As you might know, serializable types cannot publicly expose interface types because the serializer cannot handle them. But there could be other valid reasons why you would want the concrete cabinet type to return the concrete document classes.

Trying To Solve The Problem

I came up with a moderately satisfying solution... I implemented the private backing field and the Documents property using the "class version", and explicitly implemented the interface as such:

[Serializable]
public class Cabinet : ICabinet
{
  private string name = null;
  private string location = null;
  private List<Document> documents = new List<Document>();
 
  public string Name { get { return name; } }
  public string Location { get { return location; } }
  public List<Document> Documents { get { return documents; } }
 
  [XmlIgnore]
  List<IDocument> ICabinet.Documents // Explicit implementation
  {
    get
    {
      return this.Documents.ConvertAll<IDocument>(
        delegate(Document target)
        {
          return (IDocument)target;
        }
      );
    }
  }
}

The explicit interface implementation will not only "hide" the property from normal consumers of the class and resolve the obvious naming conflict of the two Documents properties, but the xml serializer will also ignore the explicitly implemented property (and just to be sure, I also applied the [XmlIgnore] attribute to it). If this property is queried anyway, it will convert the "class version" to the "interface version" using the generic ConvertAll method, which returns a new list of another type by converting each list item through an anonymous method. In this case, a simple cast is enough because they are covariant. This yields the following picture:

An Additional Problem

There's still an issue with this approach, though: if you come in through the interface and try to manipulate the documents list (for example, if you add an item to it), you will be working on this freshly-created copy of the list and your changes won't show up in the original list:

ICabinet cabinet = new Cabinet(); // Declared as the interface
cabinet.Documents.Add(new Document()); // Won't work as expected
Assert.AreEqual(cabinet.Documents.Count, 0);

Luckily, I had the option to change the interface to return a ReadOnlyCollection<IDocument> so that modifications weren't even possible and the problem went away. Luckily.

But if I weren't as blessed, I would probably have given up and steered away from these generic types altogether in this scenario since they generate quite some issues when used in inheritance hierarchies as you've seen. I'm a big fan of generics and they've surprised me in many interesting ways (just look at the sheer beauty of that ConvertAll combined with the anonymous delegate above), but this time I think I've stretched them too far...

Blog | Programming | .NET | Quirks | Whidbey
Tuesday, October 18, 2005 8:11:21 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

 

Two Cool Tools#

I've said before that I'm not a "linking out" kinda guy, but these two tools are just too cool not to mention.

CR_Documentor

CR_Documentor is a free addin for Visual Studio (works on Visual Studio 2003 and 2005!) that shows a live preview of how the XML documentation under your cursor would look like in a help file.

I'm a real documentation freak, so this is pure heaven for me!

PowerTrace

PowerTrace is a free library that contains the TerminalTraceListener class, which "opens a port and allows you to connect to your app through Telnet so you can watch your traces in the lab or even across the globe" (quoting the November 2005 edition of MSDN Magazine's Bugslayer column).

I think that's a pretty clever concept: you're not wasting any disk space with trace files, in stead you can connect to a running app when there's trouble. You don't receive a history of the last x minutes or trace lines when you login though (which you will probably need to properly diagnose the problem) but it's still a great idea to add this functionality to production systems.

Blog | Programming | .NET | VS.NET | Whidbey
Tuesday, October 18, 2005 5:36:41 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

Assert.AreEqual not working properly for Arrays#

As you might know, Visual Studio 2005 Team Test Edition will feature testing tools to perform unit testing, load testing, functional testing, ... It's great to see Microsoft really getting serious about providing these much-needed tools where third parties such as NUnit have been filling the gap all these years.

Anyway, while implementing some unit tests with the Release Candidate earlier today, I noticed that the following test failed:

string[] list1 = new string[] {"Test"};
string[] list2 = new string[] {"Test"};
Assert.AreEqual<string[]>(list1, list2);

After some digging, it appears that the AreEqual method doesn't special case for arrays, it just performs an Object.Equals(list1, list2). In turn, this will result in list1.Equals(list2) and I would expect the equality check for arrays to actually compare the array contents (object equality) in stead of checking if they're the same object (object identity). Especially since there is an Assert.AreSame method which should serve the latter purpose. In fact, I can understand that AreEqual would call Object.Equals and AreSame calls Object.ReferenceEquals, but I figured that System.Array would have overridden the Equals method to perform the equality check. Apparently, I was wrong.

So I had to revert to a manual check to see if both arrays have the same length and contents:

Assert.AreEqual(list1.Length, list2.Length);
for(int i = 0; i < list1.Length; i++)
{
  Assert.AreEqual(list1[i], list2[i]);
}

NUnit has worked around this problem by putting similar logic into the Assert.AreEqual method, which makes more sense in my mind.

Thursday, October 13, 2005 10:17:02 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

 

ASP.NET 2.0 References#

I've been using the Release Candidate of Visual Studio 2005 lately, and I'm very pleased with the overall look and feel of the application. There are still some issues left to work out (I get the occasional crash and burn), so I hope they'll all be gone by the time they RTM in the week of November 7th...

One of the things I really wished they would have fixed, though, is the way references are handled in ASP.NET 2.0 websites or WebService projects. This is what I had to say about references in June 2004, and it still holds true:

Although certainly not always possible, the ultimate solution to problems with references has always been using Project References. So that's what I'm doing now, but in ASP.NET they tend to switch from project references to fixed binary references that don't get updated anymore. And you wonder why you get runtime errors... So you need to check those references regularly and reset them to project references. Joy! What's even funnier is that an ASP.NET site doesn't have a project file anymore, which would be fine if there was nothing to remember for an ASP.NET project. But what about these references? I'm sorry to have noticed that, but they're stored in the solution file. Bad, bad, bad... If you have multiple solutions with the same ASP.NET project in them, it would depend on the solution file which kind of references the project would use. If you really need project-settings, revive the project file guys and recall the "no project file needed"-hype. What's one file extra going to do anyway?

Apart from the project references randomly becoming binary references (I've seen it happen again in the RC!) I still think it's an even bigger problem that project properties are put into the solution file. If you want proof, this is a part of a solution file that contains a WebService project:

Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = http://localhost/TestWebService/,
"http://localhost/TestWebService", "{F7389224-931A-4652-A0E2-3A932D1B40C6}"
 ProjectSection(WebsiteProperties) = preProject
  ProjectReferences = "{BC53180F-394F-4F31-A61E-BFBC4DBF9B32}|BusinessLayer.dll;"
  Debug.AspNetCompiler.VirtualPath = "/TestWebService"
  Debug.AspNetCompiler.PhysicalPath = "..\..\..\..\POC\TestWebService\"
  Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\TestWebService\"
  Debug.AspNetCompiler.Updateable = "true"
  Debug.AspNetCompiler.ForceOverwrite = "true"
  Debug.AspNetCompiler.FixedNames = "false"
  Debug.AspNetCompiler.Debug = "True"
  Release.AspNetCompiler.VirtualPath = "/TestWebService"
  Release.AspNetCompiler.PhysicalPath = "..\..\..\..\POC\TestWebService\"
  Release.AspNetCompiler.TargetPath = "PrecompiledWeb\TestWebService\"
  Release.AspNetCompiler.Updateable = "true"
  Release.AspNetCompiler.ForceOverwrite = "true"
  Release.AspNetCompiler.FixedNames = "false"
  Release.AspNetCompiler.Debug = "False"
  SlnRelativePath = "..\..\..\..\POC\TestWebService\"
 EndProjectSection
EndProject

The rest of the settings are also project-specific (hence the ProjectSection) so I think it's all unacceptable. But I guess it's too late to change any of this...?

Update: I did some thinking and some of this might actually make sense... As the line in the solution file above actually states, it's a Project Reference. Since project references refer to other projects within the same solution file by definition, this is actually quite logical. I tried to do the same thing with a non-project reference (i.e. a binary reference) and it's not stored in the solution file. But before you start cheering, be aware that the reference isn't stored anywhere at all. The assembly is just copied over to the website and you'll have to update it manually if the reference changed. Not too brilliant either... The fact that project references tend to switch to binary references might have something to do with adding the website to a new solution which doesn't contain the referenced project, but I'm not so sure the reason is that simple.

Blog | Programming | .NET | ASP.NET | VS.NET | Whidbey
Thursday, October 13, 2005 8:23:50 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

 

Deleting source-controlled items#

Now here's a dialog box in the Visual Studio 2005 RC I'm very happy with:

Finally, no more orphaned files in your Source Control Repository when you delete files from your project locally!

Blog | Programming | .NET | VS.NET | Whidbey
Thursday, October 13, 2005 9:51:34 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

 

Releasing E = m c² 1.3#

E = m c² (apart from a silly little formula relating an object's mass to its energy content) is a pet project I've created a few years ago and that I'm still using everyday. It's basically a tray utility that can check various sources for messages, then filter and redistribute them. A typical example is checking your mailbox and showing you a popup window if there are new messages, but the scope of this tool goes beyond that since it's fully extensible using plugins. For example, you can check RSS files for new blog posts, be reminded of events on certain times, log messages to a database, play a soundfile when new messages arrive, send a summary email, run a program, ... Basically, you can make E = m c² do all you can think of!

Although I still have a lot of plans and cool ideas for the tool, it's been over 2 years since my last update, and that's mostly because I haven't had much time to work on it and I was always postponing the release of a new version due to a lack of big changes. So with Visual Studio 2005 and .NET 2.0 around the corner, I guess I won't be continuing it as it is right now but I'm moving all the cool new features I have in mind over to the 2.0 release which will be built upon Visual Studio 2005 and possibly WCF/Indigo.

Hence, this is the final release of the 1.x branch, if you care enough to give it a spin then don't hesitate to let me know how you like it!

The E = m c² 1.3 executable and documentation (251,54 KB)
The E = m c² 1.3 executable, source code and documentation (380,87 KB)
The E = m c² 1.3 Plugin Pack and documentation, without Mshtml (301,93 KB)
The E = m c² 1.3 Plugin Pack and documentation, with Mshtml (1,86 MB)
The E = m c² 1.3 Plugin Pack, source code and documentation, with Mshtml (3,75 MB)

New features on the core executable:

  • Added checkbox "Add to all distribution channels" next to "Add Plugin" button so you can opt out of this default behaviour.
  • Fixed bug where plugins weren't disposed when new settings were applied.
  • Made the plugin properties panel show categories.
  • Made sure the Filters treenode in the settings screen is now always in between the Publishers and Subscribers nodes.
  • About screen now closes on any keypress.
  • Tray icon is now gray when the application is disabled.
  • New features in the plugin pack:

  • Added "Toast" plugin.
  • ContentFilter now works in Block or Pass mode and can be made case sensitive.
  • Added Categories to the plugin settings.
  • Renamed Ping plugin to ServerStatus because it now also supports checking an url to see if a certain server is online.
  • Added XslFileName to RssWriter plugin.
  • Blog | Programming | .NET | Indigo | Whidbey | Emc | Download
    Tuesday, October 11, 2005 7:19:47 PM (Romance Standard Time, UTC+01:00) #    Comments [3]  | 

     

    Static Classes And The HasShutdownStarted Property#

    During the pre-conference session on Framework Design Guidelines, Brad Abrams was kind enough to share the story behind the infamous HasShutdownStarted property on the Environment class with us. If you're unfamiliar with that property, take a look at its original definition below:

    public sealed class Environment
    {
    private Environment() {}
    public bool HasShutDownStarted { get { /*...*/ } }
    }

    Now see if you can spot the "minor issue" with this property...

    The funny thing is, this code actually shipped in the initial release of the .NET Framework, but obviously it needed to be QFE'd (Quick Fix Engineered). So Brad did a little investigation to see how it could have happened that an effectively uncallable property made it into the framework. Running through the engineering callstack, he found out that:

    • The property was implemented and unit tested by the developer.
    • It was subsequently tested and approved by the tester.
    • It was documented along with "working" sample code.
    • And finally it was reviewed and accepted by the Program Manager who owned the feature (in his defense, he had originally specified that it should be static).

    According to the story, this incident triggered the static classes feature that is new in C# 2.0 (which declares a class as having only static members) to prevent this from happening again.

    By the way, declaring a class as static makes the compiler mark the class both sealed (so it cannot be inherited) and abstract (so it cannot be instantiated) under the covers; furthermore, the compiler checks that everything on the class is effectively static. It doesn't create a private constructor, as you might think, because there's no real point to do that anymore (instantiation is already prevented by defining the class as abstract) and to avoid the small metadata overhead induced by the additional constructor.

    Blog | General | Programming | .NET | Quirks | Whidbey | PDC05
    Friday, September 16, 2005 5:15:49 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Article: Applied Visual Studio 2005 Enhancements In WeFly247#

    My first "official" article just went online here on my website: "Applied Visual Studio 2005 Enhancements In WeFly247".

    There's a link to the article in the Beta Experience Newsletter that was just sent out today to everyone who subscribed to it (so welcome, all, and stick around for more!). So if you have a special interest in Visual Studio 2005 and .NET 2.0 be sure to check out the Beta Experience!

    And keep reading my blog, of course :-)

    Thursday, July 28, 2005 12:02:40 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    WeFly247 now available in Australia#

    Cool, if you live in Australia, you can now order WeFly247 as well (via frankarr). You can order just WeFly247, or WeFly247 with the Visual Studio 2005 Beta!

    That's the first country outside of EMEA that I've heard of that's also giving away free copies. Good thing we localized it to Aussie :-) Enjoy!

    Update: New Zealand is also giving it away! (Via Nigel Parker, thanks Frank!)

    Thursday, July 14, 2005 7:01:15 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    TechEd Day 2#

    Keynote 1: Ready For Business (Andrew Lees)

    The official keynote was a combination of a "show" and a talk, with Corporate VP Andrew Lees being regularly swapped out for a couple of (what I presume to be) actors in the typical Developer/IT Pro/User roles. I'm sure we've all been there as one of these roles, just not getting anything done from the other ones; but it's all about team work, and the speach was mostly about how the Microsoft products will help these teams work together. Along with a number of videos and flashy demos (not built in Avalon though, which is a shame) this was quite an entertaining keynote, but nothing shockingly new of course.

    There was one pretty cool demo about WS-Management (a new systems management protocol) that showed MOM sending management queries to a non-bootable machine (I'm still puzzled by which stack or hardware component). And since it's an open specification, it even worked on a Sun Solaris which they demoed live on stage. Nice!

    They also mentioned that Microsoft Learning is currently offering free skills assessments and free trainings on Visual Studio 2005 and SQL Server 2005. Really nice!

    ARC302 - Building And Using A Software Factory (Steve Cook, Annie Matthewman)

    While the presentation was pretty "dry", I got quite some thinking out of the whole Software Factory concept. I think of Software Factories as the two-steps-up evolution of the Enterprise Templates you might remember from a few years ago when Visual Studio .NET first came out. They're basically an abstraction from recurring enterprise-specific patterns, implemented as Domain Specific Languages (DSL's). In a basic sense, this boils down to project and code generation inside Visual Studio 2005, along with graphical editors and designers that drive this generation process. It can be as simple as providing an editor for the UIP Application Block's configuration file (which they demoed), to an entire code generation of your business layer based on a service description.

    They used the Guidance Automation Toolkit (GAT) to build their DSL editor, so it's good to think of this as a "Factory for Factories". This is a tool that will mostly be used by architects defining and implementing DSL's for an enterprise scenario. At first sight, creating a DSL using the GAT seemed doable for one-way code generation (I also took a Hands-On-Lab on it), but I wonder how hard it would be to implement it in a two-way synchronized mannor. Nonetheless, impressive stuff, but it will take some significant effort to implement this into your current software development strategy.

    ARC309 - Microsoft Visual Studio 2005 Team Edition for Software Architects: Developing Service-Oriented Systems (Eric Lee)

    This was an excellent overview on the Team System features for architects, mainly about the four Distributed System Designers that will help you create executable as well as deployable designs: the Application, System, Logical Datacenter and Deployment Designer. There isn't really a lot more to say about it other than the fact that Eric Lee is also a very good, enthousiastic and knowledgeable speaker. Great talk!

    CTS365 - Implementing "Indigo" Endpoints: Addresses, Bindings and Contracts (Christian Weyer, Steve Swartz)

    Steve Swartz did a nice job of explaining Indigo endpoints. He outlined the three types of contracts: the data contract (schema and versioning), the message contract (SOAP headers), and the service contract (behaviour).

    The way to version a data contract is stunningly easy in Indigo: just add the VersionAdded, MustUnderstand and IsOptional attributes to your data member and you're set to go:

    [DataMember(VersionAdded=2, MustUnderstand=false, IsOptional=true]
    public string SomeNewField

    The Indigo runtime will now have two-way support for this member, i.e. the new type will still work in the old service, and the old type will still work in the new service.

    The proposed way to version a service contract was to inherit your new ServiceContract interface from the old one:

    [ServiceContract]
    public interface ICalculator2 : ICalculator

    I'm not sure if this is really the way to go (it feels too much like MSXML, MSXML2, MSXML3, ...) but I'll give it some more thought before I make up my mind about this.

    Another point he made was that Exceptions are problems in code, whereas Faults are error responses from the server. Since these Faults are also a WSDL standard, there's explicit support for them in Indigo through the Fault class:

    DivideByZeroFault f = new DivideByZeroFault("Cannot divide by zero");
    throw new Fault<DivideByZeroFault>(f);

    There was also a cool demo showing the fact that you can return a Stream from a service operation, allowing infinite streaming data to be passed back (e.g. audio broadcasting, or webcam streams).

    Finally, on the behaviour part of Indigo services, developers tend to care mostly about the concurrency and instancing behaviours (can recurrant calls be made, is it a singleton or singlecall service, is session state available, ...), whereas deployers care more about throttling and metadata behaviours (how many concurrent calls and instances can I have, is the WSDL available online, is WS-MetadataExchange supported, ...). All these types of behaviours can be defined by simple attributes or configuration settings.

    All in all, a very nice talk showing some advanced capabilities of Indigo.

    CHT072 - Drilldown into Visual Studio 2005 Team System (Eric Lee)

    This interactive Chalk & Talk session gave a good demonstration about Team System, with Eric Lee showing how to create Team Projects and work in them, while answering questions from the attendees. Again, this guy seems to know pretty well what he's talking about, so it was a nice wrap-up for the day.

    (Apart from the fact that there were free drinks in the community hall afterwards, but I'd argue that the Dutch beer doesn't really count as free drinks ;-) )

    Monday, July 11, 2005 8:06:45 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    TechEd Day 1 - Building Connected Systems Today#

    After arriving a little late at TechEd in Amsterdam yesterday morning (due to the obligatory Dutch traffic jams), I went through the rather quick and painless registration process[1], quickly grabbed some healthy breakfast[2] and dove into the "Building Connected Systems Today" Preconference Session.

    The proposed new approach to building connected systems is to introduce a new 3-part service based system model, supplementing the more "traditional" 2-part Business and Technical Model with an intermediary "Service Oriented Architecture" Model. This SOA Model forms the bridge between the capabilities, processes and SLE's (Service Level Expectations) defined by the business, and the technical services offered by an implementation framework (e.g. Enterprise Services or WS-ReliableMessaging). So the SOA Model basically defines the Service Contract (implementation independent, by using WSDL and XSD), the SLA (Service Level Agreement) and optionally the Orchestration rules defining the business processes, again independent of the used technology.

    The Business Model can be created by adopting a new modelling strategy called "Motion", which is entirely based on this concept of Capabilities, that only describe the "what" (structural information) and not the "how" (dynamic process information). Actually, this business modelling part wasn't that interesting to me, as it seemed mostly a high-level work-in-development, and it seemed like "just another methodology" to me without much real practical value for me in my current position. But maybe it could mean a lot to people who actually know what BPR, Six Sigma, Lean, Zachman and TOGAF stand for. Currently, there's also no tooling to support this new methodology, but they're implementing it as a DSL (Domain Specific Language) in a Software Factory (talk about buzzwords that are bound to come back in the coming days).

    The SOA Model can be created by applying the "Pragmatic SOAD" approach (Pragmatic Service Oriented Analysis & Design), which is basically a higher-level mapping of our old-time friends: use cases, collaboration diagrams, message exchange patterns, canonical data, ... to model the actual Services.

    Finally, the Technical Model was shown as an implementation in C# which had endpoints as WebServices and as COM+ ServicedComponents, and which was partially created by tools and code generators powered by the GAT (Guidance Automation Toolkit, another hype in Software Factory land). Not a lot of surprises there, and I was actually much more impressed by Scott Hanselmans TechEd US session on a practical approach of using code generation from WSDL and XSD all the way to actual code and technical as well as functional documentation.

    One interesting slide showed the platform capabilities for the 2005 and Longhorn product waves, defining that Indigo, Avalon, Office 12, BizTalk Server 2006, SQL Server 2005 and WinFS would become increasingly important. I'm glad to see WinFS is still alive and on the roadmaps as there has been quite some confusion about its future. Alongside BizTalk Server, a service called WWS or "Windows Workflow Services" was mentioned, which I hadn't heard of before. It's basically a lightweight workflow server baked right into the operating system. Sounds interesting!

    Generally, I'd say the first day was a nice warm-up for the content to come later this week, but not much new just yet.

    [1] Goodies:

    Swag[] techedSwag = new Swag[] {
       backpack, tshirt, baseballCap, msdnMagazine,
       new FreeLicense[] { SQLServer2005, VisualStudio.NET2005StandardEdition, VirtualServer2005 },
       randomOtherStuff };

    [2] Cookies, muffins, coffee. Yum.

    Tuesday, July 05, 2005 11:45:28 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    When ASP.NET 2.0 throws 404's at you...#

    If you're getting curious HTTP 404 errors in your ASP.NET 2.0 application, be sure to check for a zero-length "magic file" called app_offline.htm and delete that. If this file is present in your web site, then the entire application will be considered offline by the ASP.NET runtime.

    While certainly useful as such to quickly disable an entire site, it's not so great that the "magic file" can also "magically appear", especially since there's no indication as to why you're getting the 404, so you can spend quite some time chasing bugs that aren't there. Fortunately, post-beta 2 builds will be providing a proper explanation.

    The reason it can appear by itself is that it's used to "take the application offline" when copying a web site. If this operation crashes somewhere in the middle for some reason, the file doesn't get deleted (while we wait for a transactional filesystem anyway) and bite you in your, errr, isapi filter.

    Blog | Programming | .NET | ASP.NET | Whidbey
    Monday, May 23, 2005 11:10:53 PM (Romance Standard Time, UTC+01:00) #    Comments [4]  | 

     

    Generics at the Indigo service boundary#

    It seems that Don Box is quite into continuations, iterators, anonymous methods and all sorts of other mysterious corners of programming lexicology lately. Some of the stuff he's showing is some pretty cool and nifty higher-order logic with C# 2.0, although I don't really see that happening in real-world enterprise applications any time soon. It's just another tradeoff between programming power and readability (which is, of course, directly related to maintainability).

    Throughout his posts, generics are ubiquitous - and rightly so, since they're one of the most powerful and appealing new constructs in .NET 2.0. Funny thing is, Indigo (his brainchild, one might say) doesn't really seem to dig generics at the service boundary: if I specify a generic interface as an Indigo [ServiceContract], it will apparently blow up at runtime...

    Take the following and run it into the Indigo/Avalon (affectionally called WinFX) Beta 1 RC that was just released:

    [ServiceContract]
    public interface IServiceProvider<T>
    {
        [OperationContract]
        T PerformService(T item);
    }
    
    public class ServiceProvider<T> : IServiceProvider<T>
    {
        public T PerformService(T item)
        {
            return default(T);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Uri serviceUri = new Uri("http://localhost/ServiceProvider");
            ServiceHost<ServiceProvider<int>> host = new ServiceHost<ServiceProvider<int>>(serviceUri);
            host.AddEndpoint(typeof(ServiceProvider<int>), new BasicProfileBinding(), "ep");
            host.Open();
            Console.WriteLine("Running. Press any key to stop...");
            Console.ReadLine();
        }
    }

    If I run this, all will seem fine. Until I request the wsdl (http://localhost/ServiceProvider/ep?wsdl): it gives me an HTTP 500 internal server error. Doing the same without the generic interface (replacing T with int directly) will work just fine.

    I wonder what went wrong. Probably something in the reflection part where they don't deal with generics properly yet...

    Anyway, it's great to finally have one machine with Visual Studio .NET 2005 Beta 2 and WinFX Beta 1 RC working together. A largely undiscovered land lies ahead, and I've got my backpack ready :-)

    Blog | Programming | .NET | Indigo | Whidbey
    Monday, May 23, 2005 10:11:47 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    WeFly247 Overview Webcast#

    Yesterday, we hosted a public webcast to give an overview of the WeFly247 project (which is part of the soon-shipping Visual Studio .NET 2005 Beta Experience, as I've mentioned before).

    I think it gave a pretty good impression of all parts of the project (overview, demos, architecture, code highlights), and it was certainly fun to do. Talking online into the void without any feedback whatsoever takes some getting used to, but it seems to have gone pretty well.

    If you missed it, you can replay the recorded show directly from the LiveMeeting site.

    Tuesday, April 19, 2005 11:50:38 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    WeFly247 Developer Interview#

    Yesterday, Rob Macdonald recorded a "WeFly247 Developer Interview" with me to be put on the soon-to-be-released WeFly247 DVD. We discussed the implementation of the different applications I worked on and a bunch of new features in .NET, and I think it all went pretty well. So be sure to check it out if you get your hands on the DVD!

    Looking back, there's a lot of places where I sounded pretty "marketingy" and used terms such as "developer productivity", "very powerful", and just "cool", but talking about the killer features in the upcoming .NET 2.0 platform and the new Visual Studio .NET just made me step back a little and appreciate all the good stuff in there with fresh eyes again.

    While we have gone through a lot of pain with instable alphas and betas, in the end it's been a great experience and I can't wait to see the final version ship!

    Tuesday, April 12, 2005 2:49:55 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    WeFly247 Screenshots#

    Now that the word on WeFly247 is gradually getting out, here is some more teasing with some screenshots of the different applications in a near-finished state. Click on an image to get an enlarged version.

    The Login screen (reused by different Windows applications)

    The Passenger website (ASP.NET 2.0 application)

    Homepage (not logged in):

    City Information:

    Homepage (logged in):

    Preferences:

    Entertainment:

    Meal Service:

    Seat Service:

    Duty-Free Shop:

    Customs & Immigrations InfoPath Form:

    The Pilot Application (ClickOnce Windows Forms application)

    Startup Screen:

    Pre-Flight Check:

    In-Flight Monitoring:

    Problems:

    Problems (Professional Look):

    The Problem Report Word Document (VSTO Smart Document)

    Problem Report:

    Notice the Flight Number Smart Tag (which fills in the flight details) and the custom actions pane showing the open problems.

    Problem Report Research:

    This shows the Research webservice that can be used to diagnose problems in real time from within the Smart Document.

    Blog | Programming | .NET | VS.NET | WeFly247 | Whidbey
    Sunday, April 10, 2005 12:51:09 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Visual Studio .NET 2005 Beta Experience#

    Tom has already been teasing about the Visual Studio .NET 2005 Beta Experience, and since it's getting more and more traction, I can finally say we're shipping WeFly247 in the EMEA region (Europe, Middle-East, Africa)! It's already been distributed for Beta 1 at VSLive! in San Francisco, but this time we're shipping it inside the box with the upcoming Visual Studio .NET 2005 Beta 2 release all over EMEA.

    If you're new here, WeFly247 is a Microsoft project to showcase the new features of Visual Studio .NET 2005, and I'm very proud to have done most of the development for it. In fact, we've been very busy lately closing down the bits for Beta 2, which, as you can imagine, is pretty tough seeing Beta 2 doesn't exist yet ;-)

    We'll be running a series of webcasts on the project to get you all excited, so come tune in if you can. Here's the information straight from Learn247:

    Learn 247 .NET Learn 247 .NET


    We are pleased to announce that shortly we will be releasing the follow up to the highly successful Football247 and WeRock247 projects titled WeFly247.

    As per our previous projects we will release a multimedia training DVD that will contain over 60 hours of audio recordings and coding labs on Visual Studio 2005 and developer technologies and full source code to the entire WeFly247 suite of applications.

    The WeFly247 scenario focuses on a fictitious airline company and contains everything that a developer needs to know about building applications with Visual Studio 2005 beta 2.

    The applications for WeFly247 scenario are broken down into 3 areas covering all areas of development, including Windows Mobile, VSTO, Smart Client, and InfoPath and much more.

    • Pilot: Pre-flight inspection of the aircraft and in-flight monitoring of key systems.
    • Passenger: Entertainment system for in-flight entertainment.
    • Crew: Management system for managing passenger requests.

    As we get ready for the launch of the DVD and sample code, throughout April we will be running a series of WebCasts to highlight the technologies we have used in the WeFly247 solutions and give developers previews of the solution which we will release in April.


    18 April: 5pm - 6:15pm GMT

    WeFly247 Application Walkthrough and Technologies

    Come and learn about the WeFly247 project, learn about the technologies used to build the solution and the architecture design.

    This session will give you a chance to get an understanding of the entire project and see all the applications working together as well as hear from the developers of the applications that built each application.

    AGENDA:

    • WeFly247 Application Overview
    • WeFly247 System Architecture
    • Building the Pilot applications (Windows Forms, VSTO)
    • Building the Passenger application (ASP.NET 2.0)
    • Building the Crew application (.NET CF)
    • Wrap up / Q&A

    To access the meeting click here. We recommend connecting 30 minutes before the meeting takes place.


    JOINING THE WEBCASTS IS EASY:

    Step 1) Make a reminding in your calendar to remind you of the event (do it now so you don't forget).

    Step 2) Click the link to join the meeting.

    The meeting will take place online, audio will be streamed to your PC.

     © 2005 Learn247.net.     All Rights Reserved.

    Blog | Programming | .NET | VS.NET | WeFly247 | Whidbey
    Sunday, April 10, 2005 12:10:47 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    DataSets Are Not Evil#

    Ok that's it, everybody stop talking smack about the DataSet. As self-elected chairman of the inexistent "DataSet Preservation Fund", I feel urged to respond to years of incorrect positioning, biased thinking and over-simplified black-and-white views. I won't allow the "enterprise community" to make the DataSet the Clippy of .NET, so to speak.

    All joking aside, I've long been putting off writing about this topic since I wanted to make sure my opinion was balanced enough but David Boschmans pointed me at a recent MSDN article on Custom Entity Classes by Karl Seguin which strikes me as pretty typical so here's my two cents on the matter. I'll take the article as my guide to inject some of my opinions, so it should be helpful to have a quick scan of the article to see what it's all about. By the way, why this article appears in the ASP.NET Developer Center and not in an Enterprise Development Center or the like (think PAG) is unclear to me, since this kind of discussion should target a broader audience.

    Introduction

    First and foremost, as the disclaimer in the introduction states: the article only talks about untyped DataSets, not about strongly-typed DataSets. This is a very unfortunate limitation by the author in my opinion, since Typed DataSets do indeed solve most problems mentioned in the article, as well as provide extra benefits, and this type of simplification will only give more traction to the anti-DataSet camp.

    Alleged Problems

    • Lack Of Abstraction.
      The statement is made (a few times throughout the article actually) that a DataSet makes it impossible to decouple your code from the database structure. While true that you still deal with logical tables, columns and relationships, a Typed DataSet will make this much less visible because you can navigate all of these by just using strongly-typed properties and methods. The argument that changing a column name in the database schema would result in adapting your client code doesn't make sense, you can (and, for this reason, always should) use "AS" in your SQL query to abstract away the actual column name, so it won't "trickle down" to the calling layers. So if the UserId column would actually change to Id for example, the SQL statement would simply become:
      SELECT Id AS UserId, FirstName AS FirstName, LastName AS LastName FROM Users
    • Weakly-typed.
      The obvious statement is made that regular DataSets are untyped, the issues mentioned by the author are of course 100% correct. Hence the invention of Typed DataSets. They will eliminate all the raised concerns. This (along with the next paragraph) also renders the "Why Are They Beneficial" section superfluous.
    • Not object-oriented.
      Sure enough, if you create a Typed DataSet, you get a class that inherits from System.DataSet, which means you can't make it derive from another class anymore. But does this make it "not object-oriented"? This type of problem is often referred to in the Java world as not being a "Plain Old Java Object" (POJO), so in this case I'll refer to it as a "Plain Old .NET Object" (PONO). The problem seems big enough to have Indigo address this by not requiring your components to inherit from any base class (as is the case with Enterprise Services COM+ components, which need to derive from ServicedComponent). If this is not a serious issue for you (it's never been for me), nothing prohibits you from just subclassing that generated DataSet class to add functionality to it without resorting to external utility methods. In the upcoming 2.0 version of .NET, it will even be possible to add functionality to the class without the need for subclassing it by using the partial classes feature.
      The Scott Hanselman quote, taken from his rant against DataSets on service boundaries, makes a good point though: "DataSets are bowls, not fruit". I'm actually cool with Typed DataSets being "bowls with a picture of fruit on them", they're data containers (data transfer objects) after all. Custom entities aren't fruit either, they're another binary representation of the same concept, but they still don't smell like fruit.
    • NULLs.
      A point is made that "dealing with NULLs in DataSets isn't the easiest thing, because every time you pull a value you need to check if it's NULL". While I certainly agree that NULLs can be a pain, you could partially deal with this through annotations on your Typed DataSet, which allow you to define the value returned if the field actually contains a NULL value. Besides, a field having a functional value or not (i.e. being NULL or not) is something that affects all layers, and how you handle this in code will not be very different when using DataSets or custom classes. This is certainly true for value types (while we wait for nullable types anyway, gimme int? now!).

    Other points that make me go "hmmm"...

    • "Never return a class from the System.Data or child namespace from the DAL". If you are convinced that System.Data is the namespace for all server-side database stuff, then you're right. But I don't think that's the case, the provider child namespaces (e.g. System.Data.SqlClient) are server-side. I would allow System.Data.DataSet to pass through customs without a problem here.
    • On performance: "whatever processing time you are able to save probably doesn't amount to much compared to the difference in maintainability". This is really comparing apples and pears, as runtime and designtime have very different characteristics and requirements in a project. It certainly is true that a "blanket statement" is pretty useless here, but I would like to say that although the performance hit and XML overhead on the wire of a DataSet might be larger in absolute figures, you should be communicating with the service backend through chunky calls anyway and the main performance bottleneck will lie beyond the service facade most of the time anyway. But the best performance tweaks can only be done through one optimal path: measuring and interpreting live data.
    • "You can certainly assign nothing/null to [value types], but this will assign a default value. If you just declare an integer, or assign nothing/null to it, the variable will actually hold the value 0." Excuse me? Have you actually tried to run the "int i = null" statement through a C# compiler? This largely diminishes my trust in the author's, eh, authority on the subject of object oriented programming.

    Free Code

    So, what do you get with Typed DataSets? Free code mostly.

    • You can use the boilerplate DataTable.Select method for searching through a table (which is illustrated as "custom behaviour" for the custom entity classes - i.e. code you need to type or generate).
    • The remark that this Select call isn't strongly typed is again correct, but if you define a key on the UserId field in your Typed DataSet for example, you will also get a free typed method called FindByUserId which will select rows based on that key.
    • In ADO.NET 2.0, you'll get the data column names as strongly typed properties so you can use these in your code. The databinding example in the article actually isn't strongly typed itself: the call to DataBinder.Eval(Container.DataItem, "UserName") contains the column name as a plain string, so it would benefit from these properties here as well.
    • If you model relationships between tables, you get free methods and properties to navigate between parent and child tables. You can even use databinding expressions to navigate through these relationships.
    • As stated by the author, "the DataView's built-in support for sorting and filtering, although requiring knowledge of both SQL and the underlying data structure, is a convenience that is somewhat lost with custom collections". So this is basically free code again, and as an extra remark: of course you need to know the data structure, how would you build an application if you knew nothing at all about your data structures? The main point, again, is that you're not supposed to know the database schema here, just the logical data structure. And regarding sorting: if you call "UserName DESC" (which you can use as a sorting expression) knowledge of SQL and think that's too hard to grasp, then you can't really expect much from a developer anyway. There needs to be some way of pouring that sort expression into a language construct. Indeed, it would be better to add strongly typed methods to sort with a sort flag enumeration (Ascending/Descending) and a column name, but it's really not that bad, is it?
    • Data binding is far better supported with DataSets than with any other mechanism in the .NET Framework. Developer productivity is indeed a project feature.

    DataSet Issues

    So it can't all be good, right? There are indeed some issues with the DataSet and I can only hope they are fixed in upcoming versions of the framework. But the main point I'm trying to convey here is that these don't suffice to radically kill DataSets or tell everyone they're all Bad and Evil. Some real problems:

    • They behave bad on the wire when passing over a Web Service or otherwise serialized as XML. This is indeed a problem and a very good reason to avoid them, if (and only if) you need to interoperate with platforms other than the .NET runtime. Don't forget, a lot of times you have both ends under control so this is actually not always an issue.
    • They have a bloated wire format, since the XML representation can become very large very fast. If this is really a problem in your case and causes a measurable performance hit, you could opt for gzip compression over the HTTP transport protocol, or rethink the way you are using the services. The more or less "fixed" overhead will also become smaller in relative figures if the communication with the backend service is chunky in stead of chatty, so that's certainly an important point of attention. And you can consider using the GetChanges method to only include a diffgram of the changes since the DataSet was initially populated - but beware that this is incredibly platform-dependant though.

    Good Points

    Fortunately, the author makes some other very valid points as well.

    • "I realize that code generation sounds like something of a dream. But when properly used and understood, it truly is a powerful arsenal in your bag of tools - even if you aren't doing custom entities". This is very, very true.
    • "Making the switch to custom entities and collections shouldn't be a decision you make lightly". This is even more true. It has a major impact on the way your applications and services will be developed.
    • "Jimmy Nilsson has an overview of some of these alternatives in his 5 part series Choosing Data Containers for .NET (part 1, 2, 3, 4, and 5)". These articles are quite good, indeed. Recommended reading!

    Conclusion

    I think part of the real discussion here is: do we go for a full Object Oriented domain model (most likely with some kind of Object/Relational mapping tool that handles lazy loading, automatic persistence, etc.) or do we build a (Typed) DataSet model where you create different ad-hoc DataSets according to each separate use case (which means there is no unified "one fits all" model). I personally think the full OO model is very hard to maintain in a large corporate domain with many projects and dependencies. Combine this with Service Orientation where it's much harder to "deploy" your domain model to the outside world (since you can only share contract and certainly not type) and I tend to think the latter is more flexible. Either that or you'll have to re-map the service boundary messages to your domain model internally, which causes even more work (although this might be a good approach if that fits your existing internal OO model).

    To conclude, I believe in one thing: choose the right tool for the job. Given two viable options, choose the option that would solve the problem best under the constraints at hand. As Andres Hejlsberg often puts it when comparing performance between C++ and C#: given infinite time and resources, you'll do better in C++. Given infinite time and budget, I might agree that custom entity classes are the best possible solution. Unfortunately, that's not very realistic in real-world projects. Developer productivity and shipping should be considered two very important "features" of your project, and if DataSets help you accomplish these, then I would certainly advise (or at least consider) using them.

    Wednesday, March 23, 2005 11:15:27 PM (Romance Standard Time, UTC+01:00) #    Comments [17]  | 

     

    Indigo March CTP "Hello World" Server & Client#

    Yes! I just got my first Indigo sample up and running!

    I started off with a clean Windows XP SP2 installation, and I just installed the March CTP of Avalon/Indigo/WinFX (build 2.0.50110) without anything else - no Visual Studio .NET, no IIS, no nothing - so it's definitely back to basics here while I'm downloading the February CTP of Visual Studio .NET 2005... On the other hand, it's quite a lot of fun to just try and get anything working without any major productivity booster such as Visual Studio, IntelliSense or any form of actual documentation installed. For now, I'll consider notepad and ildasm.exe my best friends in the Indigo space. Long time no see, welcome back guys :-)

    The first thing to try was to get any of the prepackaged samples working. I unzipped the AllSamples file in the "C:\Program Files\Microsoft SDKs\WinFX\samples" directory and seeing I had no Visual Studio installed I just tried to run MSBuild on the solution files. Although I think this should work, it was complaining to me about not being able to copy some files or something. Weird.

    I then decided to take Clemens Vasters' Indigo Hello World sample and see what I could make of that. I just copied it into a new file and ran the compiler on it:

    csc /r:"C:\Program Files\Microsoft Indigo Preview\System.ServiceModel.dll" IndigoHelloWorld.cs

    Unfortunately, I got an error straight away: the BasicProfileHttpBinding class wasn't found. So here's ildasm to the rescue already. As it turns out, they recently must have renamed the class to BasicProfileBinding, so a simple change to the sourcefile fixes the problem and we're all set and compiled. Step 1 complete! The server code is now just:

    using System;
    using System.ServiceModel;

    namespace IndiHello
    {
      [ServiceContract]
      public class Hello
      {
        [OperationContract]
        public string SayHello(string name)
        {
          return "Hello " + name;
        }
      }

      class Program
      {
        static void Main(string[] args)
        {
          ServiceHost<Hello> host = new ServiceHost<Hello>(new Uri("http://localhost/hello"));
          host.AddEndpoint(typeof(Hello), new BasicProfileBinding(), "ep");
          host.Open();
          Console.WriteLine("Press ENTER to quit");
          Console.ReadLine();
          host.Close();
        }
      }
    }

    So with my newborn Indigo service now up and running on my machine, I figured I should be able to make this do something, right? So because I couldn't really think of anything else, I just took the ASMX approach, which is to surf to the endpoint (http://localhost/hello/ep) and observe the magic: Indigo provides a very similar model to ASMX with an informative html page if you access the endpoint via HTTP/GET and is so kind as to give a hint what you could do next. Not only does it tell you how to generate a client proxy for the service, but it also gives some basic info about how to use the proxy afterwards.

    So off I am building a client proxy using svcutil.exe (think wsdl.exe for Indigo) on the wsdl:

    "C:\Program Files\Microsoft Indigo Preview\svcutil.exe" http://localhost/hello/ep?wsdl

    This just creates a proxy class in a file named tempuri.org.cs (since I haven't changed the default namespace, it just takes the tempuri.org namespace as the base name) with the contract interface and some kind of channel interface (I'm not sure what that does yet but I'll find out sooner or later):

    [System.ServiceModel.ServiceContractAttribute()]
    public interface Hello
    {
      [System.ServiceModel.OperationContractAttribute(Action=http://tempuri.org/Hello/SayHello, ReplyAction="http://tempuri.org/Hello/SayHelloResponse")]
      [return: System.ServiceModel.MessageBodyAttribute(Name="SayHelloResult", Namespace="http://tempuri.org/")]
      string SayHello([System.ServiceModel.MessageBodyAttribute(Namespace="http://tempuri.org/")] string name);
    }

    public interface HelloChannel : Hello, System.ServiceModel.IProxyChannel
    {
    }

    public partial class HelloProxy : System.ServiceModel.ProxyBase<Hello>, Hello
    {
      public HelloProxy()
      {
      }

      public HelloProxy(string configurationName) : 
        base(configurationName)
      {
      }

      public HelloProxy(System.ServiceModel.Binding binding) : 
        base(binding)
      {
      }

      public HelloProxy(System.ServiceModel.EndpointAddress address, System.ServiceModel.Binding binding) : 
        base(address, binding)
      {
      }

      public string SayHello(string name)
      {
        return base.InnerProxy.SayHello(name);
      }
    }

    Looks good. Next up: adding a test driver. Simple enough, the service's informative html page shows me how to create a simple console app that uses the proxy:

    HelloProxy proxy = new HelloProxy();
    string result = proxy.Hello("some data");
    System.Console.WriteLine("The Hello service returned '" + result + "'");
    proxy.Close();

    So I just whipped that into the generated proxy class file, and tried to compile the bunch:

    csc /out:Client.exe /r:"C:\Program Files\Microsoft Indigo Preview\System.ServiceModel.dll" tempuri.org.cs

    Too bad, there seems to be a little bug in the way the service generates the html page (I bet you didn't spot that just now, neither did I), since the service operation isn't called "Hello", it's "SayHello". So a small change here as well, run the compiler again - which seems to give me an actual executable this time - and we're ready to try and run the client:

    C:\IndigoTest>Client.exe
    Unhandled Exception: System.InvalidOperationException: Could not find Channel element for contract Hello, Client, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
       at System.ServiceModel.Design.ConfigLoader.LoadChannelDescription(ChannelDescription channelDescription, ContractDescription contract, String configurationName, EndpointAddress address)
       at System.ServiceModel.Design.ChannelLoader..ctor(Type contractType, String configurationName, EndpointAddress address)
       at System.ServiceModel.ChannelFactory`1..ctor(String configurationName)
       at System.ServiceModel.ProxyBase`1..ctor()
       at Test.Main(String[] args)

    Whoops, that's not good. Here's that Channel thing again. But then again, I didn't really provide an actual uri where the client could locate the service. So I decide to use one of the generated HelloProxy constructors that seems to make sense: the one with an EndpointAddress and Binding.

    A quick look in Ildasm at the EndpointAddress class reveals a constructor that takes a uri string, so I'll just take that and then paste in the same binding as I used on the server side:

    HelloProxy proxy = new HelloProxy(
        new System.ServiceModel.EndpointAddress( "http://localhost/hello/ep" ),
        new System.ServiceModel.BasicProfileBinding() );
    string result = proxy.SayHello("some data");
    System.Console.WriteLine("The Hello service returned '" + result + "'");
    proxy.Close();

    Throwing the compiler at the code creates me a new executable, so I run that and voila:

    C:\IndigoTest>Client.exe
    The Hello service returned 'Hello some data'

    Wicked! My first Indigo client is talking to my first Indigo service over a basic profile HTTP binding, without even having IIS installed. Ain't that something...

    Here are the files if you want to try it out yourself: IndigoHelloWorld.cs (service), tempuri.org.cs (client)

    In retrospect, I could also have used the Indigo CTP SDK docs Don Box pointed at, but, well, it just didn't come to my mind. I was so happy to see ildasm again, I guess I didn't want to trade our new-found relationship for some long-distance relationship with a remote webserver ;-)

    Now that I have this basic stuff out of the way, I can start digging in the articles, posts and documentation for Indigo to get a better hands-on view of the API.

    Sunday, March 20, 2005 3:50:31 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    TechEd Europe 2005#

    Hans Verbeeck, overall technical content owner of TechEd Europe 2005, has started planning what's on the agenda for this year.

    TechEd focuses on hot (nearly) available technologies so with the conference taking place in the beginning of July, that's going to be

    • Beta 2 of the .NET Framework 2.0 and Visual Studio .NET 2005 for developers,
    • Beta 3 of SQL Server 2005 for DBA's (I didn't even know there was going to be a third beta, I thought they were actually pretty close to shipping already),
    • SOA, software factories, domain specific languages for architects and
    • "Special tracks" (hmm that's pretty vague ;-) ) for IT Pro's.

    Not on the shortlist:

    • Indigo and Avalon, although there's a bundled CTP of both coming up in March (but it doesn't fit the "relevant within 6 months" criterium),
    • Windows Longhorn (if anybody still knows what's up with that anyway since it ran out of pillars to be based upon, but that's probably just my confusion, right?)

    Cool stuff, so if you dig this kind of content (along with labs, ask-the-experts, panels, Amsterdam's finest herbs, and - let's not forget - wicked parties) don't forget to add 4-8 July to your agenda!

    Friday, February 11, 2005 9:49:49 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    ASP.NET Comments#

    I've just expressed my love for comments (which generated some interesting discussion as well) and a while ago I've been quite active in ASP.NET 2.0; so let me take the opportunity to raise a personal concern of mine when combining the two.

    Remember that one goal of ASP.NET 2.0 was to reduce the code needed for typical scenarios by 70%. That's a lot and I don't have any metrics yet, but they've certainly managed to eliminate a lot of keypresses that I hope I will never need to break my fingers on again. They've also overhauled the databinding system (just look at the ObjectDataSource) to reduce code and you can even use the Web.config file to declaratively create a strongly-typed Profile, or couple all your pages to a common basepage to include boilerplate code.

    So great! With all this, ASPX has definitely become a double-JITted programming language of its own - as Early & Adopter so beautifully put it during the last PDC.

    The only problem I have with it, is that when hiding more and more code behind markup, where do we document what we're doing? We don't. Do you? Thought so... So come on, be nice: comment your markup when it gets anywhere near semi-complex.

    And don't just write <!-- html comments --> either, but be sure to use the <%-- server-side comments --%> in ASP.NET, since they don't get sent out to the browser (which would increase your final page size and possibly even leak information about your business logic to the browser for everyone to see).

    Still, this doesn't do anything to promote itself as metadata (that can be used by tools) like the well-known XML comments, so it's still fairly useless apart from serving as in-line documentation. But then again, if you're writing structured code that needs structured comments, you should really put it in code anyway, and not in markup.

    Blog | Programming | .NET | ASP.NET | Whidbey
    Monday, January 24, 2005 8:04:35 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

     

    Tiny but great DataSet change in Whidbey#

    There's a quite lengthy post from the VB team about the data design time changes between Whidbey beta 1 and beta 2 (via 3Leaf Development).

    In there, I found a little gem that will solve one particular annoyance I have with the current Typed DataSet generator: while the columns are generated as strongly typed objects, they're declared as internal so they're no use outside the declaring assembly. Hence the column names in quotes in my previous posts about DataSets and Web Services:

    testData.Employee.Columns["ID"].ColumnMapping = MappingType.Hidden;
    testData.Employee.Columns["CompanyID"].ColumnMapping = MappingType.Hidden;

    This will fortunately change in Whidbey, allowing more strongly-typed and thus safer code:

    testData.Employee.IDColumn.ColumnMapping = MappingType.Hidden;
    testData.Employee.CompanyIDColumn.ColumnMapping = MappingType.Hidden;

    I had planned a rant on that but it seems I've been pre-empted by the team that figured it out on their own :-) At least, if the C# team is also doing this but I can hardly imagine that they wouldn't follow the pattern here. It's the small things that can really make a difference you know...

    Blog | Programming | .NET | VS.NET | Whidbey | Samples
    Thursday, January 13, 2005 10:08:58 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Avoiding WebSite_1 when pulling an ASP.NET Site from SourceSafe#

    Today was frustration day. I got all cooked up a few times and got mad at

    • my next-door neighbour (for playing loud music at 2:30 AM)
    • some printer (for paperjamming 66% of the time)
    • Visio (for generally sucking; well either that or I'm just too much of an idiot to understand how to properly draw a UML sequence diagram in there)
    • aspnet_wp (for not finding some system dll's in its own runtime cache until I nuke the process)
    • SourceSafe (see Visio; and for the reason below)
    • Visual Studio .NET 2003 (for pestering me with the "Object type cannot be converted to target Type" CopyLocal bug again)

    Luckily, I also picked up what could be the trick to avoid an all-too-common SourceSafe mess.

    If you're getting a new solution from SourceSafe that includes an ASP.NET Web Site or Web Service you probably encountered this as well: chances are that you don't keep your sources under IIS's wwwroot but under your local SourceSafe working directory and then create VRoots (Virtual Roots) in IIS to the proper directory. If you did that before you opened the solution in Visual Studio .NET for the first time, you're doomed with a feeble attempt of SourceSafe to create the web for you, again. It notices that there's already a web with that name, creates a new one with the same name and a "_1" suffix and then complains that it can't bind to the proper web site. Here's a trick that worked for us:

    • Create the directory but keep it empty (don't get a local copy out of SourceSafe)
    • Create the VRoot to that directory with the proper name
    • Make sure Anonymous Access is enabled on the VRoot
    • Open the solution in Visual Studio .NET, SourceSafe should be getting the files in the right directory now
    • Disable Anonymous Access on the VRoot if required

    If you have other or better solutions, don't hold back and share them :-) I've seen a trick via David to avoid some other problems by making SourceSafe treat a web project as a class library, but I think the friction is pretty high on that one.

    And I'll still be holding my breath for the source control system included with Visual Studio 2005 Team System of course. That, and the fact that Visual Studio .NET 2005 doesn't need IIS anymore, or creates web sites under wwwroot by default. Shoosh, now be gone SourceSafe.

    Monday, January 10, 2005 10:09:55 PM (Romance Standard Time, UTC+01:00) #    Comments [4]  | 

     

    PDC 2005!#

    Yes! It seems there'll be a PDC again in 2005 (via Scoble)! The new PDC05 site is already up although there's not a lot of content yet (meaning there's no content yet, apart from the date (and the fact that it's announced of course (which is most important))). In fact the news is so hot they didn't even have the time to update the PDC03 logo yet ;-)

    Oh, I so wanna go again, last year's PDC was a blast... I'm already marking that week as busy in my agenda, wink wink :-)

    Since Whidbey/VS2005 should be old news by then, I'm assuming this one will be all about Indigo and Avalon, and of course Longhorn (or what's left of it anyway), and they'll probably have some yet unrevealed tricks up their sleave as well. Bring it on!

    Blog | Programming | .NET | Whidbey | PDC03 | Longhorn | PDC05
    Wednesday, December 08, 2004 10:05:49 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Edit & Continue in C#... Why?#

    What's all this fuss about Edit & Continue making it into C#?

    I've never really missed it much, and I believe it makes you think harder before you code if you don't have the 'luxury' of coding-as-you-go. I do believe it makes sense in a few scenarios - e.g. when you have a reaaally big project and you don't want to have to recompile for a simple 'i <= length - 1' mistake (but then again, do you really need your project to be that big?) - but in the majority of cases, I just don't see the need.

    Thoughts? Prove me wrong!

    Blog | Programming | .NET | VS.NET | Whidbey
    Sunday, October 17, 2004 8:56:13 PM (Romance Standard Time, UTC+01:00) #    Comments [4]  | 

     

    Enhanced feature request about icon sets in Visual Studio 2005#

    I've seen on Tom Mertens' blog that Robert McLaws is asking to support the number 2 feature suggestion for Visual Studio 2005: an updated icon set that ships with it. I heartily agree. What's more: I'll top the suggestion and expand it a little.

    We don't need just an updated icon set to ship with Visual Studio. If Windows Forms 2.0 is the final stage in Windows Forms development and Microsoft wants people to ship products with a compelling "User Experience" on the road to Longhorn, then they better start providing the community with the proper tools to do so. Icons are in important part of the user experience (platform-wide consistency is an important design principle), so the most important step here is indeed to make the common user interface elements obiquitously available.

    In my mind, that's not just shipping the icon files with the development environment. It's also publishing those icons on a searchable resource-like website where you can just download the icon you need without having to search the entire web and skim out the ridiculously outdated or overly charging icon-library websites. Microsoft must already have some central library of these icons to be shared by the product teams so why not share it with the world?

    The next step is to go all .NET'y and package a large number of common icons in strongly signed .NET resource assemblies (dll's). These could be distributed with the runtime and placed in the Global Assembly Cache (GAC) so they're readily available to all your .NET programs. That gives you the advantage of being able to update all your icons to the latest (fanciest) version with just a configuration change and it follows the same idea as reusable dll's in the first place: why embed all those common elements in each and every program when you can share one version between multiple programs?

    Anyway, an update to the icon set would be a requirement in my mind. The rest would be a nice-to-have. But I really don't want to start searching the web for a decent looking Save button ever again.

    Blog | Programming | .NET | VS.NET | Whidbey | WinForms | Windows | Longhorn
    Monday, September 27, 2004 1:26:11 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    The ASP.NET 2.0 Profile#

    Tough luck. I had been busy (well, "busy", as I mentioned: the summer has been a bit of an idle time tech-wise) writing an article on the all-new Profile concept in ASP.NET 2.0, but I just noticed that I've been pre-empted by MSDN where the article "Storing User Information with ASP.NET 2.0 Profiles" just went online. It's a great read though, and it covers pretty much everything I had to say about it (and more of course) except the part about Profile migration on which I'll add my 2 cents now.

    Let me just briefly summarize the Profile, which is one of the cornerstones of the new Personalization framework: the Profile is a "personal, type-safe, persistent data store" for each of your website's users. You can use it to remember settings (like language or culture, UI theme, ...), data (favorite color, shopping cart items, ...) or anything else you can think of really. Type-safety is ensured because it is an actual object with typed properties, and the data is automatically persisted into a data store of your choice [1]. Furthermore, you can configure the Profile to work for users that aren't known or logged in yet. When the user decides he likes your site so much that he wants to create an account, you can migrate his anonymous profile very easily in Global.asax by implementing a method like the following one:

    Sub Profile_MigrateAnonymous(ByVal s As Object, ByVal e As ProfileMigrateEventArgs)
        
        ' Fish up the profile belonging to the anonymous user that just logged in.
        Dim anonProfile As HttpProfile = Profile.GetProfile(e.AnonymousId)
        
        ' Move the settings over to the authenticated user's profile.
        Profile.FavoriteColor = anonProfile.FavoriteColor

    End Sub

    So far for the article's example. There's a little issue with this approach though. Imagine a user who already created an account and is now just browsing to your site. He hasn't logged in yet so he gets the default settings for an anonymous user. Then he logs in, thereby migrating and overwriting his own settings (which were persisted from last time) with the default ones. Too bad, you just lost your shopping cart.

    Unfortunately, there's currently no way of checking if the profile being migrated to is new - i.e. if the user already had an account and is now just logging in, or if he just created an account. Only in the latter case will you want to migrate the profile, so that's pretty tricky. Hence the following feature suggestion: provide a ProfileMigrateEventArgs.IsProfileNew flag so we can check if we actually need to migrate the profile.

    Another option would be to check on the default values of the profile [2]. But what if the user changed one of the properties before he logged in? You would wrongfully not migrate his settings. Not good.

    So until there's a better way of doing this, I'd suggest putting a flag on the Profile itself that says it's a new profile and flip it over once you've migrated the anonymous profile, e.g.:

    <profile>
     <properties>
      <add name="FavoriteColor" allowAnonymous="true" defaultValue="Red" />
      <add name="HasMigrated" type="System.Boolean" defaultValue="false" />
     </properties>
    </profile>
    

    Sub Profile_MigrateAnonymous(ByVal s As Object, ByVal e As ProfileMigrateEventArgs)
        
        ' Migrate the profile preferences only if the user is new.
        If Not Profile.HasMigrated Then
        
            ' Fish up the profile belonging to the anonymous user that just logged in.
            Dim anonProfile As HttpProfile = Profile.GetProfile(e.AnonymousId)
        
            ' Move the settings over to the authenticated user's profile.
            Profile.FavoriteColor = anonProfile.FavoriteColor
            
            ' Indicate that migration has been done.
            Profile.HasMigrated = True

        End If
        
    End Sub

    One last remark about the Profile: a VaryByProfileProperty option for output caching would make sense. Imagine you have a multilingual website and you keep the user's Culture setting in the Profile. Then you could easily configure your page to be cached for all users that share the same culture as such:

    <%@ OutputCache Duration="60" VaryByProfileProperty="Culture"  %>

    It's not really shocking but it's just a bit easier than using VaryByCustom and returning the Culture manually...

    [1] The Profile derives from the System.Configuration.SettingsBase, which is the new configuration system available in .NET 2.0. It's also used in Windows Forms so you can have type-safe access to application- and usersettings in this environment as well. Goodness!

    [2] If you're working in VB.NET, you might wonder how you can access the default value of a Profile property. It's not listed in IntelliSense (I'm still puzzled why not because it does show up if you use C#) but there's a Properties collection you can use to access a certain Profile property and get the default value out of it as follows:

    Dim defaultValue As Object = Profile.Properties("FavoriteColor").DefaultValue

    Blog | Programming | .NET | ASP.NET | WeFly247 | Whidbey | Samples
    Tuesday, August 24, 2004 6:57:30 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    Whidbey Beta 1 Available#

    Psssst, don't tell anyone but Visual Studio 2005 Beta 1 is out on MSDN! I can't wait to kick the alpha I'm running now out of the door (sure it's cool and all but it's really messing with my head lately) and install this baby. And if you think that's all, think again...

    There's also a range of Express Products (lightweight development tools for non-professionals) which looks interesting if you can't just cough up the dough for the Visual Studio .NET flagship product and related tools. There's even a SQL Server 2005 Express! And there's a Summer Of Express Coding Contest over on Channel9 to promote these little gems...

    Some other big news: the new MSDN Product Feedback Center is a place where you can get direct access to the Microsoft bug databases. You can search bugs, report bugs, make suggestions, get notifications if bugs you're monitoring change status, ... Wicked!

    Anyway, sorry for bothering you with this - you probably read it all over the blog space today anyway. I just couldn't not post this ;-)

    Blog | Programming | .NET | VS.NET | Whidbey
    Tuesday, June 29, 2004 6:31:33 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    My.Family.Feed()#

    Just a thought for the My namespace in VB.NET Whidbey (since every programmer will be far too busy exploring all the new goodies anyway):

    My.Family.Feed()

    Sunday, June 27, 2004 1:39:24 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Last-Minute Whidbey Feature Request: Easy Global Interception#

    While we wait for decent AOP frameworks in .NET that can handle this kind of stuff, wouldn't it be great if we could just do some basic interception like the code below? We can't have every single object inherit from MarshalByRefObject to get some interception goodies now can we? At least we'd get rid of boilerplate code added to every single method (who wants to type hard to maintain logging code manually anyway, or have it generated and still clutter your code view).

    Of course this has some major security implications (if you can hook into any method and look at it's parameters you can easily sniff passwords or alter parameters or look at private methods you weren't intended to see). But I guess these could be fixed by allowing only your own methods (i.e. in the same assembly) to be intercepted.

    As for the performance hit, well, in the easiest cases where the MethodInfo parameter isn't used (to 'switch' on certain methods for example) the compiler or JIT could inline this stuff altogether (change obj to this and replace the args with their respective parameter names). Otherwise, there'll be a pretty serious performance penalty but then again, you get some serious benefits and you can enable it dynamically only in case there are problems on your production machines. When disabled, the code won't even be run so it'll perform at a whopping 100%.

    CLR guys? Got some spare time before the first Whidbey beta? Robert? Got some spare time to push this up the agenda? ;-)

    public void Initialize()
    {
        // Only allow this if we have problems or while debugging.
        if( enableInterception )
        {
            // Hook up some event handlers to get interception on method entry and exit.
            System.Reflection.MethodInfo.MethodEntered += new MethodEnteredEventHandler( MethodEntered );
            System.Reflection.MethodInfo.MethodLeft += new MethodLeftEventHandler( MethodLeft );
        }
    }

    /// <summary>
    /// Called when any method is entered.
    /// </summary>
    /// <param name="info">The runtime information about the method being entered.</param>
    /// <param name="obj">The object on which the method is being called, or null if it is a static method.</param>
    /// <param name="args">The arguments passed to the method.</param>
    /// <remarks>
    /// This method is not called for event handlers of the <see cref="System.Reflection.MethodInfo.MethodEntered"/> event
    /// to avoid an infinite loop.
    /// </remarks>
    public void MethodEntered( System.Reflection.MethodInfo info, object obj, object[] args )
    {
        // Insert your logging, security, pre-condition check, ... code here.
        System.Diagnostics.Debug.WriteLine( "Method entered: " + info.Name );
    }

    /// <summary>
    /// Called when any method is left.
    /// </summary>
    /// <param name="info">The runtime information about the method being left.</param>
    /// <param name="obj">The object on which the method is being called, or null if it is a static method.</param>
    /// <param name="outArgs">The byref and out arguments of the method.</param>
    /// <param name="returnValue">The return value of the method, or null if it is a void method.</param>
    /// <param name="exception">The exception that caused the method to be left, or null if the method exited normally.</param>
    /// <remarks>
    /// This method is not called for event handlers of the <see cref="System.Reflection.MethodInfo.MethodLeft"/> event
    /// to avoid an infinite loop.
    /// </remarks>
    public void MethodLeft( System.Reflection.MethodInfo info, object obj, object[] outArgs, object returnValue, object exception )
    {
        // Insert your logging, security, post-condition check, ... code here.
        System.Diagnostics.Debug.WriteLine( "Method left: " + info.Name );
    }

    Thursday, June 03, 2004 11:09:59 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Last month on WeFly247.NET#

    It's been quite a while since the last progress report on WeFly247.NET, but we've been very busy getting a more or less stable build out for the rest of the team to review - luckily that also means a lot of work has been done in the mean time :-)

    Last time, I left off with a "standalone" Passenger web site that looked like it was designed by a developer (well, it was :-) ), but since then I've updated the look and feel to match the great designs from Elevator Digital and connected it all to the business tier. The website is pretty much done right now, it's all talking to the backend over Web Services through smart Agents that handle security and custom authorization Soap headers.

    The home page:

    The "panels" (flight info, destination info, crew info, ...) on the homepage are Web Parts so you can customize the whole lot and look only at what you would want to see during your flight. The Flight Map on the homepage is a dynamic image (easy as pie with the new .asix handler and the DynamicImage control in ASP.NET 2.0) which displays the the route the plane has already traveled and where the plane is at now.

    There's also an InfoPath form that allows you to fill in your Customs & Immigration information; it also pulls and pushes data from and to the backend through Web Services (but since InfoPath doesn't talk Soap headers yet, it's not automatically secured yet).

    The Duty Free Shop:

    So with that part pretty much done, I've started working on the Maintenance application, which is a Smart Client application for the pilots that can be used on a Tablet PC. They use it to go over a checklist before takeoff (there are no gas stations in mid-air so better check if you're fueled up) and to monitor some statistics in-flight (to make sure you won't be fined for speeding). There's some custom controls here with transparency, and the whole app is supported by smart Office documents: the new ActiveDocumentHost control allows you to embed those directly into your WinForms app! If there's a problem with one of the readings (e.g. your altitude is too low), you can look at an Excel sheet showing the data and you have a Research Pane ready to help you diagnose the problem before you submit a problem report in Word.

    The Maintenance Application:

    So we've already covered quite a lot of the scenarios but there's still a lot of work (especially on the Flight Attendant app on Pocket PC) - so I'm off coding again!

    Wednesday, May 26, 2004 9:12:07 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Visual Studio Team System#

    Whoa, a lot of important stuff seemed to have happened over night. Now they sure wouldn't have anything left to say on a PDC this year, since they just unveiled some pretty impressing technology on TechEd yesterday: the Visual Studio Team System.

    It's been all over the blogs so I'm not going to repeat all the goodness here, I'll just mention some highlights:

    • Integration of FxCop and other code analysis tools
    • They killed NUnit and NCover (which hadn't even really taken off yet), indeed, why stop at killing NAnt ;-)
    • They finally gave that good old piece of junk called SourceSafe a neckshot and replaced it by (make sure you're sitting down for this) a spicy new SQL Server-based, fully transactional, client-server source control system! (Please hold on while I whipe my chin.)
    • A bunch of designers (I suppose they're summarized under the "Whitehorse" umbrella?) to help all roles on the team (architect, dev, tester, ...) put their ideas into spiffy models.
    • ...

    And in other news (via Sam Gentile): WSE 2.0 has shipped!

    Damn, I'm going to need even more hours in a day :-(

    Tuesday, May 25, 2004 8:27:07 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    ADO.NET 2.0 Quickies#

    Writing data access code will probably remain useful for quite some time, especially since ObjectSpaces is being rolled into Longhorn's WinFS data store. I sure do understand why, but I'm still a little sad to see it go (although it's not really gone of course).

    Anyway, here's a quick dump of some things I picked up from a recent MSDN TV episode on ADO.NET 2.0. Especially cool is the "provider-agnostic data access code" so you're never coding against an actual provider (SQL Server, Oracle, ODBC, plain text, whatever, ...) but use the generic versions through a factory...

    // Get the configured providers if you want to see them all.
    DataTable providers = DbProviderFactories.GetFactoryClasses();
    // The "InvariantName" column contains the invariant name to be passed to GetFactory.

    // Use a specific provider.
    DbProviderFactory factory = DbProviderFactories.GetFactory( invariantName );
    using( DbConnection c = factory.CreateConnection() )
    {
        // Use generic methods to create commands and other ADO.NET goodies.
        c.ConnectionString = "...";
        DbCommand cmd = c.CreateCommand();
        cmd.CommandText = "...";

        // Something else that's new: load a DataTABLE directly in stead of a DataSET.
        DbDataReader r = cmd.ExecuteReader();
        DataTable table = new DataTable();
        table.Load( r );
    }

    // And for perfomance, in stead of updating each row separately to the DB,
    // batch them all at once to lower the number of connections to the DB.
    // This will call sp_executesql(""); with a sql string that contains the batched statements.
    DataAdapter da; // Initialize this...
    da.UpdateBatchSize = 100;

    Blog | Programming | .NET | ASP.NET | Whidbey | Windows | Longhorn
    Monday, May 24, 2004 2:53:00 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Easy sorting with generics and anonymous methods#

    Imagine a typed dataset of which you want to sort the rows in a special way according to a calculation on the column values. Sounds fairly complicated - but using the new generics and anonymous methods feature in C# Whidbey, it's pretty easy really:

    MonitorItemData.MonitorItemsRow[] rows; // This array is already filled.
    Array.Sort<MonitorItemData.MonitorItemsRow>( rows,
        delegate( MonitorItemData.MonitorItemsRow row1, MonitorItemData.MonitorItemsRow row2 )
        {
            // Calculate the absolute deviations of the individual monitor items.
            // Multiply by 10000 to increase the subtraction precision of the ints.
            int deviation1 = Math.Abs( 10000 * ( row1.ActualValue - row1.StandardValue ) / row1.StandardValue );
            int deviation2 = Math.Abs( 10000 * ( row2.ActualValue - row2.StandardValue ) / row2.StandardValue );

            // Sort descending according to the deviation.
            return deviation2 - deviation1;
        }
    );

    For the Array.Sort method, we're using a generic overload which takes a an array of the generic type T and a Comparison<T> delegate that can compare two instances of the generic type. But where is the Comparison delegate type mentioned? Nowhere - it's called type inference. So by looking at the signature on the anonymous method above, the compiler can make a well-educated "guess" about the type of the delegate and this baby will just compile and run. Cool? I think so!

    Monday, May 10, 2004 9:45:48 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Random Visual Studio Whidbey Annoyances#

    I guess I'm in bitch-mode anyway so why not: some random things that are driving me nuts in the Visual Studio .NET Whidbey CTP:

    • Those damn datasets that keep generating an extra SomeDataSet1 file and class! It's great that we get typesafe datasets from the MSDataSetGenerator, really, but one class will do just fine thankyouverymuch. It's probably because the dataset is under source control, thereby making all the associated files readonly. This makes it pretty hard for the generator to write to the file and in stead of checking out the original file, it has the great idea of ignoring it altogether and appending a number to it in stead - thereby introducing multiple versions and breaking builds. (Just my guess.) It even messes things up sometimes if you're just looking at the dataset. What's wrong with looking at a file? Never let looking at a file trigger a checkout!
    • Clicking a project item in the solution explorer when you're coming from another project makes the solution explorer scroll so that the current project node is made visible. Contrary to what someone must have thought on the design team: that's not cool. I don't expect any window to change its position or layout by just clicking in it. But what's a lot worse: if you double-click, say, a classfile and it decides to scroll then the double-click fires afterwards and you're really opening a different file. Combine that with the previous remark and you can have the great effect that double-clicking some regular class in solution explorer can cause the window to scroll, thereby making itself think you clicked a dataset, triggering it to be displayed, checked out and having it generate a SomeDataSet1 file. Did I mention this wasn't a cool feature?
    • And last but not least... The eternal pain of references. This is killing me. References have been bugging me before, so please, please, pretty please with sugar on top, fix them once and for all! Although certainly not always possible, the ultimate solution to problems with references has always been using Project References. So that's what I'm doing now, but in ASP.NET they tend to switch from project references to fixed binary references that don't get updated anymore. And you wonder why you get runtime errors... So you need to check those references regularly and reset them to project references. Joy! What's even funnier is that an ASP.NET site doesn't have a project file anymore, which would be fine if there was nothing to remember for an ASP.NET project. But what about these references? I'm sorry to have noticed that, but they're stored in the solution file. Bad, bad, bad... If you have multiple solutions with the same ASP.NET project in them, it would depend on the solution file which kind of references the project would use. If you really need project-settings, revive the project file guys and recall the "no project file needed"-hype. What's one file extra going to do anyway?

    Anyway, ASP.NET 2.0 still pretty much rules apart from that so that makes up for a lot :-)

    (That doesn't mean that this shouldn't all get fixed of course, so if you're reading this and can do anything at all about it that would be greatly appreciated :-) )

    By the way, I realize it's an alpha build so it's not perfect; this post will just help me re-evaluate the beta once it ships :-)

    Blog | Programming | .NET | ASP.NET | VS.NET | WeFly247 | Whidbey
    Tuesday, May 04, 2004 9:32:36 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    The ASP.NET 2.0 ObjectDataSource Revisited - or - Give Me That Extra Inch!#

    Since I cried tears of joy over the new ObjectDataSource in ASP.NET 2.0, two things have happened:

    The first one is only important if you're doing, well, anything at all in .NET really. By that I mean: go get it already dammit! It can now load, visualize, search and decompile assemblies from any .NET runtime, including the Whidbey ones, so this killer tool just became even better! I just used it to check upon my remark to see if the ObjectDataSource would cache the runtime type information it found - but it doesn't look like it does. This would imply a significant overhead on assembly probing and reflection each time the data is fetched (if it isn't read from the cache of course). Anyway, let's call that "room for improvement" or "never mind you twat they know bloody well what they're doing so stop decompiling and jumping to conclusions already".

    Regarding the second one, I thought about naming this post "ASP.NET 2.0 DataBinding - Close But No Cigar" or even "Microsoft still doesn't get DataBinding" - but that's just a little harsh and arrogant ;-) It would probably generate more attention though, but for now, I'd just like to subtitle it "Give Me That Extra Inch".

    So what's the problem? Let me just briefly sketch the right context here... Most modern applications are n-tier, which means your data is stored in a data tier (which is backed by a relational database most of the time), it passes a business tier holding all your core business logic, and then reaches your user interface tier. The data itself is "disconnected", meaning no connection (to a database or other data store) is kept alive and the data has no memory of where it came from. In .NET land, this is represented by the DataSet object with embedded DataTables, primary keys, relations, constraints, ... - thus providing an in-memory representation of a relational database. But I'm sorry for boring you; you know all of this, right?

    So the two main points in modern data-driven enterprise development are: n-tier and datasets.

    And although we (and certainly Microsoft) have known all this for years, there's never been any real support for this in the .NET framework or in the samples: 95% of all examples still go straight from the UI to the database. And that's frustrating for you as an enterprise developer, since they're not realistic or useable in your world.

    Now I thought for a minute that the ObjectDataSource would finally be able to solve this issue - as I've said before, it's a DataSource control that fetches data from any object through declarative configuration. So just hook it up to a remote business component or web service that returns a dataset and you've succesfully decoupled your UI from your other tiers, while maintaining your easy-to-use declarative ASP.NET databinding.

    Well, yes, but only partially. While this works great for a lot of scenarios, it fails when things get just a little bit more complex: it won't work when you have multiple data tables in your dataset, which is a very common practice when you're fetching related data. Since you're working with multiple tiers, you'll want to reduce the number of calls and get chunky in stead of chatty conversations. So you try to group as much related data in a dataset as possible. And then the client can look at this data as individual tables but also navigate the relationships between them.

    And a data source having multiple tables has always been supported in databinding as well, using the data member to indicate which table in your dataset should be used. The new databinding classes also support this through "views" on the data, which you can retrieve by the view name. Unfortunately, here's the drawback: the ObjectDataSource only supports one table from the dataset. It actively checks on the retrieved object to see if it's a dataset and if it is, it just uses the first table to create its one and only view. (How do I know? Reflector for president!) Even the documentation says so: "The ObjectDataSource control supports only one data source view". So that's where it ends I guess. They really did come close this time, but I'm still a little disappointed.

    I need to get a little more chunky than chatty too, so just to summarize: please make the ObjectDataSource support multiple views if there are multiple DataTables. Thanks. That's all I wanted to say really :-)

    Monday, May 03, 2004 3:27:56 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    Working around some ASP.NET AdRotator limitations#

    I'm playing working with the updated AdRotator in ASP.NET 2.0, and I had to work around some limitations so I figured I'd best share what I came up with...

    The AdRotator is a control that shows a random advertisement, which is basically just an image and a link to a target page (like a shopping page or an e-commerce site). And that's the problem. That's all it is. An image and a link. What I wanted to do is make an advertisement that also shows a description and a price next to it, but unfortunately there's no templating mechanism for the AdRotator to customize the control. (Spot the hidden feature request.)

    Another problem I had is that I pull the advertisement data from the database (the new AdRotator supports the cool new ASP.NET 2.0 databinding so you're not limited to xml files anymore like before). But there's no NavigateUrl in the database, and I need to give the AdRotator a URL to which it should navigate when you click the image. Unfortunately, I can't make the NavigateUrlField "smart". I have a ProductID in my datasource, so I'd like to have it construct a url based on that, a little something like this:

    <asp:AdRotator (...) NavigateUrlField='<%# Eval("ProductID", "~/Shop.aspx?ProductID={0}") %>' />

    But that doesn't work of course, the NavigateUrlField has to point to a field in the datasource (and I'm not sure if this <%# %> construct would work anyway)...

    I could add a NavigateUrl field on the business tier but frankly, I don't want to. It's not the business tier's business (pun intended) to know there's an AdRotator somewhere down the line that needs this funny Shopping URL. It only knows about products. I could add the column on the client tier but then I'd lose my beautifully simple databinding since I'd need to preprocess the data. Well in fact the databinding would still be easy, I'd just bind it to a local "proxy" preprocessor object in stead of to the actual webservice. But it's less transparant and I still wouldn't have my price and description anywhere near my image...

    In the end, I decided to do it a little differently. I created a simple Advertisements user control with an AdRotator in it, and labels for the price and description. Then I just use the AdRotator's AdCreated event to play around a little bit. The trick is, you can get to the data source fields through the AdProperties dictionary on the AdCreatedEventArgs. I'll just let the code speak for itself:

    <%@ control language="VB" classname="Advertisement"%>
    <script runat="server">
     Private Sub shopAds_AdCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AdCreatedEventArgs)
      e.NavigateUrl = "~/Shop.aspx?ProductID=" & e.AdProperties("ProductID")
      description.Text = e.AdProperties("Description")
      price.Text = e.AdProperties("Price")
     End Sub
    </script>
    <table>
     <tr>
      <td>
       <asp:AdRotator ID="shopAds" Runat="server" DataSourceID="advertisementData" ImageUrlField="ImageUri" OnAdCreated="shopAds_AdCreated" />
      </td>
      <td>
       <asp:Label ID="description" Runat="Server" />
       <br />
       <asp:Label ID="price" Runat="Server" />
      </td>
     </tr>
    </table>
    <asp:ObjectDataSource ID="advertisementData" Runat="server" TypeName="WeFly247.UI.Proxies.PassengerWebService" SelectMethod="GetProducts">
     <SelectParameters>
      <asp:ProfileParameter Name="cultureName" Type="String" PropertyName="Culture" />
     </SelectParameters>
    </asp:ObjectDataSource>
    Blog | Programming | .NET | ASP.NET | WeFly247 | Whidbey | Samples
    Wednesday, April 28, 2004 10:14:37 AM (Romance Standard Time, UTC+01:00) #    Comments [13]  | 

     

    DataBinding in ASP.NET 2.0#

    ASP.NET 2.0 features a whole new DataBinding infrastructure, which allows you to define and consume data sources declaratively. Sounds fancy, and it is. If you look at last week's coding summary, you can see this in action:

    <asp:ObjectDataSource ID="infoData" Runat="server" TypeName="WeFly247.UI.Proxies.PassengerWebService" SelectMethod="GetFlightData" />
    <asp:GridView ID="info" Runat="Server" DataSourceID="infoData" />

    As you can see, there's that new GridView control, and in stead of binding it in code (you know, set the DataSource property and don't forget to call DataBind!) you just set a DataSourceID. This is a reference to some data source object, which can now be just a control as any other (under the "more markup! less code!" motto).

    Now there are a number of data source controls: SqlDataSource (accesses SQL Server), AccessDataSource (accesses Access (whew)), SiteMapDataSource (reads a sitemap file), DataSetDataSource and XmlDataSource (which speak for themselves), and last but certainly not least: the ObjectDataSource.

    Now this is what I call goodness. They've finally come to their senses and realized that not everyone uses a database on the client tier. They've heard themselves say "Web Services" one time too many I guess, and this ObjectDataSource is the solution for everyone who has data living on another tier. What it does is create a new instance of the type you specify, and then call a method on it to get the data. After that, the object is disposed again but your disconnected data remains alive in the data source control.

    Possibly (I'm just guessing - hoping actually - here, I haven't checked since I can't use Reflector to decompile this yet :-) ) they'll cache the object and method information (not the object itself, the documentation states clearly that it's disposed of) somehow to prevent every call from having the overhead of using reflection to find the type and the method to call. Anyway.

    So in our case this little piece of markup just creates a new Web Service proxy for the passenger Web Service, calls the GetFlightData method on it (which effectively sets the whole SOAP story in action, talk about hidden complexity) and uses the returned data for data binding.

    Sounds easy, and easy usually means limited. Fortunately, they've thought well about it, and provided quite a range of extra options. DataSource controls support parameters to be passed in or out, through parameter controls which can fetch their values from other controls, form fields, cookies, the new ASP.NET Profile, the query string, the session, or you can build your own. (A literal parameter value would be nice to pass in a constant though, but it doesn't seem to be there...). For example, this one fetches the user's culture from his Profile, and passes that along to the GetProducts method:

    <asp:ObjectDataSource ID="advertisementData" Runat="server" TypeName="WeFly247.UI.Proxies.PassengerWebService" SelectMethod="GetProducts">
     <SelectParameters>
      <asp:ProfileParameter Name="cultureName" Type="String" PropertyName="Culture" />
     </SelectParameters>
    </asp:ObjectDataSource>

    And in case you were worried about two-way data, DataSource controls also support updating, deleting and inserting through other properties - again with parameters like before. For a lot more information, look at the excellent MSDN article on databinding in ASP.NET Whidbey by Early & Adopter.

    So this is one of the reasons I'm pretty impressed with ASP.NET 2.0. More reasons are bound to follow - stay tuned :-)

    Wednesday, April 28, 2004 9:59:20 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    Server Explorer On Steroids#

    As you can see they've added a whole bunch of things in the "Server Explorer" window in Visual Studio .NET (Whidbey): basically all your operating system objects are there (processes, treads, accounts, shares, ...). So I guess if you can get to it through WMI then you can find it here. So what used to be a separate download (the WMI Extensions) is now built-in and accessible right from your IDE!

    Pop quiz: what's missing in this picture? Yep. The SQL Server plugin. Fortunately, you can still do most of the things you need (editing stored procedures, looking at table definitions, running ad hoc queries) after creating a Data Connection but I must say I panicked for a second there :-) But I'm sure it'll be back when the beta ships...

    Now let's hope they fixed that ugly memory protection error I get when trying to browse a table (as I said, most of the things...).

    Tuesday, April 27, 2004 4:28:12 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Setting a general base class for all your ASP.NET pages#

    Since ASP.NET 2.0 is making such an effort to reduce the need for writing actual code, it's now becoming less likely that you will be using code-behind files. It's still possible of course, but if you don't actually create a page class yourself, ASP.NET will just do that for you. And the good thing is, you can just specify the base class it needs to use - so you can slide in your own custom base class in stead of the standard System.Web.UI.Page. Very convenient in scenarios where you're writing framework-like base pages, or if you want to do something extra in every page of your site. Just use the <pages> section in the web.config file as such:

    <pages pageBaseType="Acme.Framework.Web.UI.SharedBasePage">

    You can do the same for controls by the way. Actually, you can do a whole lot of things in that tag, like adding namespaces that need to be imported by default, pre-registering tag prefixes, well basically just managing your pages in a single place. Cool!

    Blog | Programming | .NET | ASP.NET | Whidbey
    Monday, April 26, 2004 2:42:32 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Last week on WeFly247.NET#

    Well it's been a bumpy ride so far, I can tell you that. Working with alpha builds is always a bit of a "challenge" so of course we knew we could expect some trouble, but regular crashes and excessive memory consumption are now part of my regular day :-) Let's just say there's still quite a lot of work on Visual Studio, so I think I know why they're calling it "2005" nowadays :-)

    So for now, we're still on the CTP build released on MSDN a few weeks ago, but maybe we'll switch over to a newer build if there's a chance of getting a more stable one. Anyway, it's a good thing I'm developing inside a VirtualPC, so when all else fails I can still revert to a more or less clean VPC and just pull the sources from SourceSafe.

    But the good news is that there's such a flood of really great stuff coming in Whidbey errrr "Visual Studio .NET 2005 formerly known as Whidbey" (I think I'll stick to calling it "Whidbey" though :-) ) so I'm really excited about it! I've been mostly working on the ASP.NET side of things, and it's just incredible what they've been doing over there. Security, Personalization, DataBinding, Web Parts, Themes, Masterpages, ... It's all there and it's really well architected. And best of all: it even seems to be pretty stable in this build :-)

    The trick here is to try and forget some "best practices" from ASP.NET 1.x because there are just a lot of new ways to do things now, and most of them don't require any code at all. Take DataBinding for example, with just 2 lines of markup, you pull your data from your Web Service and bind it to the new GridView control:

    <asp:ObjectDataSource ID="infoData" Runat="server" TypeName="WeFly247.UI.Proxies.PassengerWebService" SelectMethod="GetFlightData" />
    <asp:GridView ID="info" Runat="Server" DataSourceID="infoData" />

    Goodness!

    So I'm pretty much done with the general structure of the website, I'm now going to focus on connecting it to the business tier and feeding it some actual live data.

    Blog | .NET | ASP.NET | VS.NET | WeFly247 | Whidbey
    Monday, April 26, 2004 1:22:23 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Visual MemoryLeak .NET 2005#

    I was wondering why my VirtualPC in which I'm running Visual Studio .NET 2005 CTP (f.k.a. Whidbey) got so incredibly slow. I gave the virtual machine 512MB RAM and I only had 2 Visual Studio's open in it (with fairly simple projects), along with an explorer window and a Word document. I did keep the Visual Studio's open for a pretty long time and apparently that's not such a good idea: Windows was using over a gig of memory. One Visual Studio instance took up around 120MB, the other one maxed at 200MB. Talk about a little memory leak... Let's hope this improves in the beta, or - shudder - is it supposed to eat up that amount of memory?

    Blog | Programming | .NET | VS.NET | Whidbey
    Tuesday, April 20, 2004 3:29:27 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    ASP.NET & XAML - I'm so slow#

    I just made the most obvious observation: ASP.NET 2.0 and XAML are mother and daughter. And their hereditary determined angle-bracket beauty will only be increasing by the laws of natural selection.

    Although that shouldn't come as a surprise at all since it's often been said that "XAML is to WinForms what ASP.NET was to the web". I just hadn't had the physical real-world click just until now. (Of course it's already been shown extensively that XAML isn't really tied to WinForms at all, but it's probably still the most useful scenario for it.)

    So what triggered the click? I just noticed that some ASP.NET controls provide a kind of nested properties like <SomeControl Property-NestedProperty="[value]" />, e.g. <GridView HeaderStyle-Font-Bold="True" />. That's just like the nested properties syntax in XAML (only here they're using a dash in stead of a dot). I don't think the syntax here is as universally supported (I've only seen it with a number of properties, mostly to do with styles) but it's conceptually the same.

    Another thing that struck me is the template mechanism; it's been there since the beginning really, but in fact it's just a way to attach template objects to controls (like grids) without using code. In other words: declarative object coupling.

    So to realize their 70% code reduction claims they're providing declarative nested attributes and object coupling - exactly what XAML is so damn good at… I should've seen this long ago, I'm so slow...

    Monday, April 19, 2004 1:19:22 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Some more info on Microsoft WeFly247.NET#

    Microsoft has been building some sample applications to showcase .NET through the Learn247.NET site. Former projects are Football247.NET and WeRock247.NET that focused particularly on Visual Studio 2003 and Smart Clients respectively. You can order the DVD's for these for free on the site, by the way, so if you're interested in some free goodies... :-) These projects are accompanied by labs presentations, a community website, and a Microsoft tour through EMEA to promote all of this.

    The latest project - WeFly247.NET - (which, as you could have guessed or known by now, I'm on; me being half of the development team) is going to focus on Visual Studio 2005 (a.k.a. "Whidbey"), using an imaginary airline to show a lot of enhancements in the upcoming version of .NET. Rather than sum it all up, I'll just refer to the introductory post to WeFly247.NET on the community forums. The intention is that we use that site to keep "the community" (a.k.a.: you!) up to speed on what we're doing (e.g. weekly builds, blogs, documentation, ...) and get them excited to ask questions and give feedback and build extensions, so if you're interested: be sure to keep an eye on this site!

    I'll keep blogging about my experiences building the apps here, and on the community site as well once we get the blogs up and running over there.

    Thursday, April 15, 2004 11:15:28 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    Inheritance modelling in a relational database#

    I'm modelling the database for the WeFly247.NET project, and a small issue came up so I thought I'd share the problem and proposed solution with you... Ideally, because you're way smarter and know of a much better way to do this of course :-)

    It basically has to do with inheritance hierarchies in a relational database, and I found a pretty good introduction to mapping objects to tables on the Object Architects site but I'll just limit myself to the problem at hand here.

    Imagine a SeatServiceRequests table in which all passenger requests on a flight are stored. The list of things you can request is in the SeatServiceItems table; these include a range of drinks, books, papers, pillows, blankets, "special attention" by the flight attendant ;-), ... and belong to certain categories (Drinks, Reading Material, Comfort, ...). In another use case, you can schedule a meal to be delivered to you and choose a drink to go with that. So the MealRequests table needs a link to the SeatServiceItems - but here's the tricky part: only drinks are allowed here (logically). You can't drink a newspaper with your meal (at least not if we can stop you from trying).

    There are options to enforce the constraint that a requested SeatServiceItem must be a drink of course, such as checking the item's category in the business logic, or using a trigger to check the constraint when a new row is added in the MealRequests table. However, that makes it an 'implicit' constraint: it's not modelled in the ERD and not really enforced by the database itself:

    So that doesn't make me very happy...

    The problem, in fact, is that we have sort of an inheritance relationship between a SeatServiceItem and a Drink - a Drink is a SeatServiceItem - but I didn't want to make the database too complex and go about one of the full object-to-table mapping schemes here.

    One thought was to create a "Drinks" view over the SeatServiceItems table so that only items from the "Drinks" category are shown. That way we can link the MealRequests table to the Drinks view. Unfortunately, SQL Server doesn't support relationships between tables and views so we can't use that to model the relationship or to enforce the constraint.

    So I took this up with a colleague who proposed a pretty simple solution for this (thanks, doggi :-) ). Just add an extra "Drinks" table containing the primary keys of the SeatServiceItems that are in fact drinks (so basically this is an emulated view on the SeatServiceItems). Now you can establish all relationships without problems.

    It's not as elegant as I'd want it to be (when working with drinks, you have 2 tables to maintain) but it beats the 'implicit' constraint idea so I guess I'll be using this solution. What do you think? Any issues with this, any other ideas?

    Wednesday, April 14, 2004 3:21:38 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

     

    MVP Global Summit - I want in!#

    I'm hearing a lot of stuff lately about the MVP Global Summit that just took place. Seems like a really cool place to be if you're into the whole Borg / Koolaid thing (and I am, I gotta admit).

    So here's my mildly overdue new year's resolution: I want to be an MVP by next year so I can join in on the party :-)

    Actually, I don't really know what I have to do to become an elected MVP but when all else fails, I'll just crash the MVP party like Rory did :-)

    Friday, April 09, 2004 5:50:47 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    WeFly247: A piece of the lid just came off#

    I just noticed on Dave Sussman's blog that he's already mentioning the WeFly247 project. I didn't even know we were allowed to talk about it but I guess just linking to someone who does should get me off the hook ;-) Dave is the guy who wrote a lot of books on ASP.NET and other stuff so he sure knows his stuff.

    So as you might have guessed, I'm on the project as well. I flew over to Reading last week for a day to attend the kickoff meeting and as you can see in his post it's going to be a really cool project, and I'm really excited to be working on it! It's also going to be very much in the open so that's both scaring and exciting.

    I'm at the absolute bottom of the food-chain on this project (as the lower half of the "dev team") but I wouldn't want to be anywhere else with all the .NET goodness coming up in 2.0 really :-)

    So stay tuned, we'll be showing you lots and lots of great Whidbey stuff in the coming weeks!

    Friday, April 09, 2004 1:09:10 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Whidbey Impressions#

    I've finally started working on the new Whidbey build. Some marketing-friendly people called it CTP (Community Tech Preview), people who like uniformly-rising integers might call it PD4 (Partner Drop 4) but real coders refer to it as "2.0.40301" of course. I've already had it added it to my list of friendly runtimes (don't worry, I still have enough tattoo-space left for years to come).

    The first big thing I noticed was that Whitehorse still isn't there. The goodness of having a round-trip engineering class designer, a uml modeller, a network layout modeller, ... all within your IDE (emphasis on the 'I' here) will have to wait a little longer I guess. This means I have to go back to Visio to model my use cases and database diagrams for my current project. It's not that Visio is a bad product or anything, it just sucks that's all. It's not integrated, it doesn't look as good, it feels old and clumsy, and I hate the way it does some of its layouting (especially connectors are terrible, and too hard to correct yourself).

    A nice little improvement on the Error Reporting dialog (aka crash-o-spam-a-thon, I always send error reports you know :-) ) caught my attention (actually, it's not a good thing that I noticed this, since I was hoping not to encounter the dialog altogether but well, it's still alpha software of course :-) ): there's now an option that makes the dialog close itself after the error report has been sent. Thanks, it's the little things that annoy you the most you know. They should really put this in the general Windows error reporting dialog as well (I would have figured it was actually the same component but apparently that's not the case).

    I got an interesting exception when trying to view a project's properties (officially I'm pretty puzzled how I'm going to manage without project properties but still): "The type serialized in the .resources file was not the same type that the .resources file said it contained. Expected 'System.Drawing.Size' but read 'System.Drawing.Size'". Normally when I get this kind of warning, I'd expect some kind of versioning problem here. But within Visual Studio? Uh-oh...

    Update: the Project Properties are working again... There seemed to be a problem with the keyfile causing the build to fail which apparently also prevented the project properties page from loading. I removed the keyfile tag in the .csproj file (xml and msbuild rule) and all is well again.

    Now I'm in even more trouble: the new Pocket PC 2003 emulator doesn't seem to do a lot. I doesn't power up and freezes my Visual Studio... Deploying it to the "legacy" emulator does seem to work though, and what's pretty cool is that it gives you these confirmation dialogs to replace "mscoree.dll" so I'm really patching the emulator to the Whidbey build of the .NET CF 2.0. Ah wait a second, fortunately already an update on this: the new emulator does work! You just have to wait a long while when powering it on. It takes a minute before the Windows Mobile splash screen pops up, then you have to wait even longer for the .NET CF 2.0 to be installed, the application itself launches slow, but it works fine and I still think the whole concept rocks :-)

    The Object Browser window doesn't seem to have the new view yet where you can see a class definition as an emtpy code file, too bad because I kind of like the idea: it's more natural as a programmer to view a type contract as an actual code block. You can however get a glimpse of how it will look using the (buggy) Windows Forms Class Viewer tool (WinCV.exe in the SDK 2.0 dir).

    Update: It's not in the Object Browser window but it's there: View - Other Windows - Code Definition View. This gives you a window that shows a code block for whatever class happens to be under your caret. Cool!

    Oh one more thing before I actually get back to work: wear sunglasses when coding. The component tray (you know, the region where your non-visual components like tooltips and extenders are shown in the designer) is in eye-bashing purple. So are the gridlines in the task list. Damn, they must have fired all the people with a working set of eyes over there...

    Blog | Programming | .NET | ASP.NET | VS.NET | WeFly247 | Whidbey | WinForms
    Thursday, April 08, 2004 3:10:35 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

     

    Good stuff coming up!#

    It's been pretty quiet here, I know, but I'm finishing up my current project so there's just not a lot of interesting stuff going on. The things I've been pretty involved with lately and that I really do want to share with you are just too big to post here so I'm cooking something up for a slightly different distribution channel - stay tuned :-)

    Besides, it seems somebody heard my desperate cry for new Whidbey goodies: my next project will be all about Whidbey and Yukon! So that's gonna kick some serious bootay; I just hope I won't be under NDA or anything because I can't wait to explore this goodness and share the drool with you :-)

    Saturday, March 27, 2004 1:54:28 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Whidbey Delayed - You Bastards!#

    ZDNet brings us the sad news that Microsoft delayed Whidbey and Yukon until the first half of 2005. You utter, utter bastards! I want this stuff now! Actually, I do have alpha bits from the PDC of course, but they're wearing off ;-) And I have a later build but that's pretty unstable. I want some new goodies and even the beta doesn't seem to be coming any time soon... Somebody ease my pain!

    Blog | Programming | .NET | Whidbey | PDC03
    Thursday, March 11, 2004 9:12:38 AM (Romance Standard Time, UTC+01:00) #    Comments [3]  | 

     

    Cake anyone?#
    Seriously, if Anders says "you get to have your cake and eat it too" one more time, I'm creaming him. Just like I creamed BillG a few years back ;-)
    Blog | General | Programming | .NET | Whidbey | PDC03
    Tuesday, February 03, 2004 12:44:42 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    MSBuild In 30 Minutes#

    John Lam gives a great introduction on MSBuild in his PDF newsletter "Practical Eye For The .NET Guy". Pretty clear and interesting even if you're familiar with [N]Ant. (Through Chris Sells' blog)

    Wednesday, January 28, 2004 12:49:09 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Events Under The Hood#

    I've already explained how events work in Visual Basic .NET, now I just found out about a rather old article on MSDN about events in C#. Nice look at how you can implement the delegate handling yourself in stead of having the compiler do it for you.

    Wednesday, January 21, 2004 11:09:09 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    ASCII Blitting#

    Heh, the Whidbey Console class has a MoveBufferArea method so you can move an entire screen region to a new position in the console at once. I sure hope the folks at marketing won't forget to mention the huge performance benefit of ASCII blitting :-)

    Sunday, January 18, 2004 2:03:56 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    ClickOnce Manifest#

    All right so ClickOnce seems to work again: publishing works. But when I try to launch a published program, it gives me a deployment error: "general activation failure".

    Lucky me, it mentions "See the log file for more details". Unfortunately, it doesn't provide a hint as to what log file that is, or where I could find it. So far for extra credit on the "useful errormessages" department - but I remind myself that it's alpha software so I'm not complaining :-) So I just reverted to the IIS logs, and it seems that the browser is trying to fetch a .manifest file for which it gets an HTTP/404 error.

    Adding a new MIME type (.manifest, type text/xml) in IIS seems to do the trick, but I do suppose (i.e. hope) that this works by default on a clean box. So I'm just assuming that it's my setup (which is probably pretty messed up by now, cyclic installations of older and newer builds of various programs can't be too good).

    Friday, January 16, 2004 12:13:15 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    Dessert anyone?#

    By now the suspense ("Did the Whidbey reinstall work? Were the Whidbey gnomes really digging holes in the new build?") should be killing you. Otherwise: go fish! ;-)

    Well, only partially I'm afraid. The PDC build of Visual Studio .NET Whidbey installed but with some errors (some packages couldn't be loaded but they don't seem too critical). ClickOnce is working again though, and ASP.NET is looking a lot better.

    It's just that Yukon still isn't running :-( Always fun to watch its transactional installer in action though: you spend an hour looking at a progressbar running towards the light, until it tries to start the MSSQLSERVER service, which fails, and then it just goes about rolling back the whole installation without asking. An hour and a half wel spent!

    Oh well, at least the tiramisu worked out pretty well. Maybe I should consider a career change ;-)

    Friday, January 16, 2004 8:43:10 AM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

     

    Whidbey Trouble#

    Ok so there are a lot of nice things to be said about the new Whidbey build. However, I struggled too hard to get a lot of stuff to work that I really need right now: ClickOnce was broken (publishing failed due to an XmlException on a file which I presume to be the generated deployment descriptor but I couldn't tell), ASP.NET acted weird (personalization didn't work for instance, it wouldn't even recognize the personalization tag in web.config), and I tried installing the PDC build of SQL Server Yukon (beta 1) to try if that worked but after installation (which meant installing the PDC build of the .NET Framework as well, although the new build of Visual Studio .NET wanted that out of there when I installed that) the service failed to start altogether. So I guess that spells d-o-o-m.

    Uninstalled everything. Reinstalling PDC build :-(

    Thursday, January 15, 2004 6:55:50 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    More impressions of the new Whidbey build#

    Nice: now you get a task-switch window if you press CTRL-TAB to switch between your windows too (a bit like ALT-TAB in Windows itself) with the available windows and the active tools (like the Solution Explorer).

    It seems they have already fixed the minor F2 usability bug. How thoughtful :-) "Make" is still there though, although they moved it into the "Build" menu. Not good enough, and certainly not as long as CTRL-SHIFT-B doesn't 'Make' by default. Can't seem to assign another shortcut to it either, apparently...

    The removed all WinBar stuff in this build (office style toolbar), I wasn't too fond of the implementation yet but why they ripped it out altogether...? Ah well, it'll be back I guess, they've been marketing it already so there's no way back.

    Ah the DataGridView (formerly known as GridView) is already looking much better. It's like the ASP.NET DataGrid we all got to know and love ;-) Sorting, header resizing, flexible column types, extensive support for formatting and templates, now in a Windows Forms environment. Cool!

    The StatusBar control has been replaced by a StatusStrip, which now finally supports a ProgressBar. It will probably support more things later on too (like buttons and such). Well it's a start but I'd rather see it able to support any type of control. (I wrote a class once that could handle that actually...)

    Hey another code generator (the "Strongly Typed Resource Builder") has entered the building! Resource files are now backed by typed classes so you can go form.Text = AppWideResources.ApplicationTitle if you have a resource key called "ApplicationTitle" in an AppWideResources.resx file. The resource editor has also undergone a remake (thank God, because quite frankly: it sucked): now you can add images, icons, audio, files, ... from the IDE. Pretty nice! Sorry for Lutz Roeder's Resourcer though ;-)

    Damn. The WebBrowser component seems broken in this build: I get a COM error :-( Uhm yeah what else, I really didn't expect it all to be managed code by now ;-)

    And in general, the Windows Forms designer is really messing with my head. It keeps messing up the generated code and it just seems a lot less stable than the PDC build. Well can't have it all I guess...

    Thursday, January 15, 2004 11:00:37 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

     

    New Whidbey Build#

    Whew, I finally got the new Whidbey build installed. Seems that you need to uninstall the previous version of Whidbey first - which I can understand for Visual Studio .NET and the likes; but what about the .NET Framework? It had to go although I thought it had strong versioning... So that all took quite some time already, but I think I used my waiting time well. Ask me tomorrow how my tiramisu turned out ;-)

    Anyway, when installing Visual Studio I had to start over a few times because it turned out there was an error in one of the cab files. From the name of the cab (something with CE in it) I guessed it had something to do with the Compact Edition of the framework so I tossed all that out and I got it running now :-)

    Anyway, some first GUI impressions: it all looks a bit fancier. Office style toolbars, shark-fin tabs, updated icons, realtime-rendered DirectX breakpoints (uhm, ok so they have a 3D look now), ... Ah and they finally got rid of that awkward Toolbox list thingy and replaced it by a much more useable expandable list control with an actual scrollbar this time. Good work.

    Ok, already a quick non-GUI impression: I've had it installed only for a few minutes and it already crashed once. Alpha software is so cool :-) Now - to get me some sleep!

    Thursday, January 15, 2004 1:27:32 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    PropertyGrid#

    Cool, they added the PropertyGrid to the toolbox by default in Visual Studio .NET Whidbey. Actually a very useful control I tend to use quite often so I'm glad they did :-)

    Wednesday, January 14, 2004 11:59:13 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Partial types trick in PDC build#

    As I mentioned before: the WinForms designer and DataSet generators don't create partial types yet in the PDC build of Whidbey. However, you can work around that if you're using Visual Basic .NET: in contrast to C#, VB doesn't require all participating classes to declare themselves as partial. So you can keep the generated file as such, and create another file with a class which is declared partial (Expands Class Form1 for example) and it will work :-)

    Wednesday, January 14, 2004 11:26:13 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    Usability issue in Solution Explorer#

    Pressing F2 (the well-known shortcut for Rename all over Windows) pops up the Object Browser in Visual Studio .NET Whidbey. Not bad if you're in code view (where 'rename' doesn't make any sense) but very annoying if you're trying to rename a solution/project/file in the Solution Explorer :-( Some shortcuts should always preserve their meaning. What if CTRL-C would suddenly mean "Close Visual Studio"? Man, would I be annoyed ;-)

    Wednesday, January 14, 2004 11:20:59 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    The unfortunate return of the Make command in Visual Basic .NET#

    Hmm this is kinda crappy actually: you can't build a Visual Basic .NET project anymore but you have to select "Make" in the File menu. There's also no default shortcut for it so the CTRL-SHIFT-B combination (which is the shortcut for Build of course) that has been burnt in my fingers for two years now is just a shortcut for 'beep' in VB.NET. Why revert to a "way of life" that existed in a different platform (errrr 'version' if we should believe MS marketing) when an intermediate 'version' did it another way - and a more consistent way at that?

    So feature disposal request for the release version of Whidbey: please kill Make!

    Wednesday, January 14, 2004 10:55:08 AM (Romance Standard Time, UTC+01:00) #    Comments [3]  | 

     

    Whidbey Time!#

    All right, I finally got some dedicated time do some Whidbey this week: I'm at Microsoft Belgium for a few days looking into all the new stuff :-)

    One of the perks of being at the source: you get the latest build, in stead of the PDC build which misses some features. For instance, a new Windows Forms class isn't declared as a partial type yet (with the designer-generated code in a separate file). The same goes for typed DataSets: no partial types there yet in the PDC build. And the narrowing property visibility feature doesn't work yet either (e.g. have a public getter and an internal setter). All fixed in the latest build though :-)

    I'll try to blog a lot about my findings - sort of as an "I'm sorry" for the fact that I didn't cover the PDC very well (hardly at all actually). On the other hand: a lot of people have done a much better job at that than I could have. I still have a thing or two to say about the PDC but it's getting pretty outdated don't you think ;-)

    Wednesday, January 14, 2004 9:24:40 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

     

    All content © 2010, Jelle Druyts
    On this page
    Article: Customizing generated Web Service proxies in Visual Studio 2005
    Downloading Visual Studio 2005 RTM
    Are you ready for the launch?
    Copy To Output Directory
    Generics & Invariance: An Interesting Problem
    Two Cool Tools
    Assert.AreEqual not working properly for Arrays
    ASP.NET 2.0 References
    Deleting source-controlled items
    Releasing E = m c² 1.3
    Static Classes And The HasShutdownStarted Property
    Article: Applied Visual Studio 2005 Enhancements In WeFly247
    WeFly247 now available in Australia
    TechEd Day 2
    TechEd Day 1 - Building Connected Systems Today
    When ASP.NET 2.0 throws 404's at you...
    Generics at the Indigo service boundary
    WeFly247 Overview Webcast
    WeFly247 Developer Interview
    WeFly247 Screenshots
    Visual Studio .NET 2005 Beta Experience
    DataSets Are Not Evil
    Indigo March CTP "Hello World" Server & Client
    TechEd Europe 2005
    ASP.NET Comments
    Tiny but great DataSet change in Whidbey
    Avoiding WebSite_1 when pulling an ASP.NET Site from SourceSafe
    PDC 2005!
    Edit & Continue in C#... Why?
    Enhanced feature request about icon sets in Visual Studio 2005
    The ASP.NET 2.0 Profile
    Whidbey Beta 1 Available
    My.Family.Feed()
    Last-Minute Whidbey Feature Request: Easy Global Interception
    Last month on WeFly247.NET
    Visual Studio Team System
    ADO.NET 2.0 Quickies
    Easy sorting with generics and anonymous methods
    Random Visual Studio Whidbey Annoyances
    The ASP.NET 2.0 ObjectDataSource Revisited - or - Give Me That Extra Inch!
    Working around some ASP.NET AdRotator limitations
    DataBinding in ASP.NET 2.0
    Server Explorer On Steroids
    Setting a general base class for all your ASP.NET pages
    Last week on WeFly247.NET
    Visual MemoryLeak .NET 2005
    ASP.NET & XAML - I'm so slow
    Some more info on Microsoft WeFly247.NET
    Inheritance modelling in a relational database
    MVP Global Summit - I want in!
    WeFly247: A piece of the lid just came off
    Whidbey Impressions
    Good stuff coming up!
    Whidbey Delayed - You Bastards!
    Cake anyone?
    MSBuild In 30 Minutes
    Events Under The Hood
    ASCII Blitting
    ClickOnce Manifest
    Dessert anyone?
    Whidbey Trouble
    More impressions of the new Whidbey build
    New Whidbey Build
    PropertyGrid
    Partial types trick in PDC build
    Usability issue in Solution Explorer
    The unfortunate return of the Make command in Visual Basic .NET
    Whidbey Time!

    Recent Photos
    www.flickr.com
    This is a Flickr badge showing public photos from Jelle Druyts. Make your own badge here.
    Advertising
    Top Picks
    Statistics
    Total Posts: 350
    This Year: 4
    This Month: 2
    This Week: 2
    Comments: 526
    Archives
    Sitemap
    Disclaimer
    This is my personal website, not my boss', not my mother's, and certainly not the pope's. My personal opinions may be irrelevant, inaccurate, boring or even plain wrong, I'm sorry if that makes you feel uncomfortable. But then again, you don't have to read them, I just hope you'll find something interesting here now and then. I'll certainly do my best. But if you don't like it, go read the pope's blog. I'm sure it's fascinating.

    Powered by:
    newtelligence dasBlog 2.0.7226.0

    Sign In