Wednesday, October 29, 2003

I got to talk to AndersH for an extended period of time today. I take back what I said in an earlier post -- the only thing better than hearing the inventor of C# talk about the language is being able to sit down with him and have him answer your questions.

I've always wondered if the following syntax would be supported:

[LessThan( delegate{ return System.DateTime.Now; } )]
System.DateTime.Date MyProperty
{
   get{}
   set{}
}

It's official, folks: it won't be. Sad. But we sure did have a great conversation!

We also talked about the typeof() opertator. I asked him if we'd see a more generic info_of() operator...the word was that they were considering it, but it proably won't show up in Whidbey. Which is too bad, since the generic databinding API in Avalon depends a lot on you passing the string representation of a data-bound property name...I'd really like to be able to find out that I fat-fingered this string at compile time instead of runtime.

Wednesday, October 29, 2003 5:51:07 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

One of the great things about being here at this PDC is the way that you get information straight from the source. For example, going to a presentation on the new C# features is cool – going to a presentation on those features that’s being given by the guy who designed the language is even better.

Anders Heijlsberg (the man so smart I can’t even spell his last name) did a really fantastic job and gave a very consumable presentation. Even though he cruised through fairly abstract academic topics like the difference between open and closed generic types, anonymous procedures, and outer local variable captures, I still felt that the presentation was “down to earth” and pretty grokable by people who might have accidentally left their PhD’s in their hotel rooms.

Once I get my Whidbey box set up, I’m going to be playing around quite a bit with this stuff. I’ll post code samples when I create them.

Exciting data point: the implementation of generics in Whidbey are REALLY fast. Anders did a demo comparing an ArrayList to a List<int>, with the generic implementation being almost twice as fast as the loosely-typed implementation. The performance gains come from the fact that since the JITed is operating directly on integer data types there’s no boxing/unboxing overhead. And since all retrieval operation on the generic type are typed in terms of int’s, the generic implementation eliminates the need to downcast as well as the associated performance cost thereof.

The generic implementation is really heavily optimized to reduce code footprint. Unlike generic implementations that do compile-time type expansion (like *cough* Java), there’s always only one instance of a given generic type present in the IL – in other words, the IL is itself generic. Actual instances of a closed generic type are created only as necessary – so if you declare List<int>, List<float>, List<Foo> and List<Bar> but only do a runtime instantiation of List<Bar>, the other 3 closed typed won’t incur any additional performance overhead. This is a substantial improvement over C++ templates, which did compile-time expansion. In the C++ world, the compiler would have actually instantiated those other types even though they were never actually used at runtime.

Once a particular closed generic type is actually instantiated at runtime, there are additional optimizations that the runtime takes to reduce the amount of overhead required to JIT-compile the code. When the closed generic type is parameterized in terms of value types, the JIT will generate new code for that type. If it didn’t do this, you’d incur the overhead of boxing and runtime performance would suffer. However, when a closed generic type is parameterized only in terms of reference types, the JIT will reuse the native instructions for all possible instantiations of that generic. That is, List<Foo>, List<Bar>, and List<Baz> will actually all use the same JITed code underneath the hood.

There are other cool things in store as well…briefly, the implementation of anonymous proc’s in Whidbey are full-on lambda forms with full support for capturing outer local variables. I can’t wait to start playing with these!

 

Wednesday, October 29, 2003 10:07:22 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Tuesday, October 28, 2003

I learned something really interesting in the Indigo talk that I did manage to go to -- although Indigo is very closely tied to the logical model of the XML Infoset (basically it assumes XML 1.0 + Namespaces as the logical lingua franca), there's no requirement for that logical model to be persisted as a text-based stream of UTF-8 encoded characters. Indigo is actually wire-format agnostic, relying on a formatting mechanism similar to that of .NET Remoting's infrastructure to handle reading and writing an infoset to the wire.

I would imagine that most Indigo scenarios would use the standard UTF-8 encoded XML wire format for communication. This text-based representation is great for readability and interoperability. However, there are some downsides to this wire format -- it's expensive to parse, costly to transmit, and is a generally inefficient representation. There are times when these characteristics are not desirable.

For example, say you're deploying two services that coexist within the same AppDomain. In this case, it makes no sense to use UTF-8 encoded XML as the communication format -- it's just too expensive, and you don't need the benefits of readability and interoperability that the formats provide. It's specifically for cases like this -- where performance trumps interop -- that Indigo's support for custom wire formats become useful.

The specifics of this extensibility point won't be covered until Thursday, but I do know that Whidbey will support some sort of binary XML representation. This binary form will be isomorphic to regular text-encoded XML (and probably can be readily converted to text for debugging purposes), but has a smaller memory footprint and parses faster than text.

There are other uses for binary XML inside outside of Indigo. I think portions of the Avalon stack use a custom binary representation of their XML vocabulary to minimize download times for tricke-feed applications (which are apparently now called "Drizzle Download"). If I remember correctly, this new format is called BAML (binary Application Markup Lanugage)...

It will be interesting to see how the decision to support binary XML will be taken up by the community. There's already been a lot of debate about this -- I imagine that the "XMLness" of binary XML will continue to be debated for some time.

 

Tuesday, October 28, 2003 2:49:20 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

I built my first Indigo service in the hands-on labs. I got totally sidetracked by some new things I noticed about how Indigo does WSDL generation...

  • WSDL.EXE is replaced by WSDLGEN.exe in the Longhorn SDK
  • There's a whole set of message-oriented types to control serialization, like System.MessageBus.TypedMessage, [MessageAttribute] and [MessageBodyAttribute].
  • When WSDLGEN.exe generates schemas for these types, it looks like it does so by generating named elements at the global scope, not by generating actual XSD types. I need to confirm this with some more experimentation, but it looks like Tim Ewalds views on schema have propagated :)
  • Type schemas look like they are generated into separated XSD files that are then imported into the WSDL file. Score one for Yasser and the WSDL-first folks!

 

Tuesday, October 28, 2003 12:11:13 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

[12:31 am] I knew this session would be good when I ran into Benajamin Mitchell totally by happenstance. We’d been playing email tag all day, and then there we were, sitting in the same row. I’ve had good luck meeting people today.

Don’s talk was good. It was essentially a futher investigation of the same things he touched on at the XML DevCon back in July (I have my notes for that in my archive which I can’t get to right now…). Essentially, the message boils down to this: object-oriented programming was a good metaphor for building systems that reside in memory, but that metaphor breaks down when you think about trying to build distributed systems that are stable over time. During the 90’s, MS and others tried to “stretch” the interface-based object metaphor and make it a legitimate distributed platform, but nobody’s succeeded. The problem is that OO systems assume too much shared infrastructure and don’t provide a way of answering the question “what happens when that infrastructure changes?”

The problem is that distributed systems don’t respect logical boundaries. In the real world, there are boundaries that govern human interaction – a point which DBox drove home by hauling a volunteer up on stage and violating both his personal space as well as his privacy (Don asked him how much money he made last year – in front of 1000+ people). Needless to say, that relationship didn’t last very long. If there are logical boundaries that govern human interaction, why aren’t there similar logical boundaries that govern the interaction of software components?

Indigo is a set of API’s that make it easy to create service-oriented software systems on the .NET platform. These API’s are built around four guiding principles:

  1. Boundaries are explicit. Developers opt-in to exposing service functionality.
  1. Services are autonomous. Services must be able to be deployed, versioned, secured, and consumed independently.
  1. Services share schemas and contracts, not classes and types. Integration is based upon message formats and message exchange patterns, not interface congruence and binary compatibility.
  1. Policy-based compatibility. Instead of a common centralized type system, services use policy to reference well-known semantic elements via XML elements and URI’s.

Number 3 begs the question “what the difference between a schema and a type?” Schemas speak solely in terms of wire format – they define the legitimate contents of a message. Unlike types, which can include both state and behavior, schemas only deal with state. Also, types are absolute – IMarshal is IMarshal, no matter where you are – where as schemas are relative to the client (each client might enforce similar but different schemas on incoming data according to their own needs.

These four design tenets give rise to four areas of note when it comes to writing code:

  1. Boundaries are explicitly stated in Indigo. Everything that gets exposed to the outside world is done so via metadata, which is orthogonal to the CLR’s notion of accessability. This maintains a mental separation between the internal and external views of the object, as well as making it easier to special-case the inproc scenarios. Consider the following code, which I hurredly copied from the demo:

using System.ServiceModel;
using System.Runtime.Serialization;

[ DataContract ] //Indicates that this CLR type has a
                 //corresponding schema representation
                 //More on this in Doug Purdy’s session…

public class Person
{

    [DataMember] //opt in!
    private int age;

    [DataMember] //opt in!
    private string name { get{} set{} }
}

[Service] //explicit opt-in mechanism
public class MyService
{

   [ServiceMethod] //note that this is applied to a private method!
    
              //Accessability to services is independent from CLR
                   //accessibility. This lets to treat the in-proc
                   //scenario differently

   private void f(Person p){}
   public void g(){}
}

2) Indigo and unification -- the grand unified XML architecture. In the 1.x framework, there are at least 3 API’s for doing interservice communication (ASMX, .NET remoting, and Enterprise Services). These 3 disparate API’s will be semantically combined in Indigo. One API to rule them all!

 

3) Indigo and Interoperability. Indigo is built with the full knowledge the not everyone will have Indigo. On the wire, it speaks purely WS-* compliant XML, making it interoperable with other implementations of those specs.

 

4) Indigo and Continuity. There’s a large amount of non-Indigo code already out there, and Microsoft recognizes this. Although the PDC bits do not include this functionality, there will be ways to interop Indigo with COM+, MSMQ, and Enterprise Services.

 

Going forward, the best way to future-proof your existing applications is to make sure that they communicate with the outside world via ASMX/WSE. Although these implementations are not perfect, they are least flawed. Inside of that boundary (where you have control of the deployment and evolution of the system), use Remoting or ES as needed. But whenever you’re going to be talking to another entity that’s outside of your direct control, communicating with that entity via the existing Web Services technologies will ease your transition to Indigo.

More on these topics tomorrow after the Indigo drill-downs, which I will be attending with great vigor.

 

Tuesday, October 28, 2003 8:11:32 AM (Pacific Standard Time, UTC-08:00)  #    Comments [4]
 Thursday, October 16, 2003
For me, one of the most anticipated sessions at this year's PDC is Doug Purdy's talk on object serialization in Whidbey/Indigo.

 
I have somewhat of a love/hate relationship with the current XmlSerializer. On one hand, it's very nice to have a nice object-oriented way to manipulate XML. On the other, I find myself often times fighting against the serialization framework -- either because I'm using a schema that doesn't map nicely into OO-space, or because there are outright bugs in the 1.0 framework.
 
Rectifying two type systems that are acknowledged to be at least partially orthogonal is a really big challenge. The current serialization framework is a really great start -- but I'm very keen on seeing what the serialization team has come up with now that the problem domain is better understood.
 
Personally, I think the XmlSerializer is the singular most innovative feature of the 1.x .NET framework -- not so much for what it accomplishes in the end, but because of the way it does its work. I'm in love with the whole concept of attribute-driven runtime code generation. It's too bad that that the practical application of this technology in the XML Serialization domain is less than complete. However, for a first effort I think that the 1.X serialization framework is profoundly cool -- and I can't wait to see what 2.0 has in store!
 
 
 
Thursday, October 16, 2003 7:31:42 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Sunday, September 21, 2003

Part IV of Bruce Eckel's conversation with Anders Hejlsberg is up. This time, it's all about virtual functions and versioning.

For those of you who don't know, Anders is the guy who designed C#. He's so smart, I can't even pronounce his last name.

Sunday, September 21, 2003 6:25:56 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Wednesday, September 17, 2003

Ok, let’s assume for the moment that everyone buys Microsoft’s vision of the future: software systems as compositions of services provided by multiple vendors who integrate spontaneously and seamlessly by utilizing the common communications framework of XML and SOAP messages. We have the rudimentary toolset in place, but those tools are distributed across many different API’s in the current version of the CLR. What’s needed is a strong set of framework technologies to make dealing with these XML messages more consistent across transport layers and messaging patterns.

There’s an overabundance of messaging API’s in the .NET framework right now. We’ve got:

  • System.Messaging: The foundation for sending messages (which are first-class citizens) reliably across a persistent, reliable transport mechanism. Putting SOAP inside of these messages and sending them across an MSMQ transport might be a viable way to achieve reliable messaging within the enterprise – if you can figure out how to get this transport mechanism to interact properly with the other messaging stacks.
  • System.Remoting: The remoting stack offers the most flexibility when it comes to messaging patterns and transport options, but it does so at the expense of interoperability. RPC is a walk in the park with remoting, and it’s relatively easy to roll a pub/sub framework for asynchronous communication because it’s very easy to have a remoting host act as both a message consumer and a message originator. However, because remoting assumes strong type fidelity on both sides of the remoting boundary, interop is the Achilles heel of remoting.
  • The ASMX Stack: Great for building interoperable web services using SOAP and XML. The extensible architecture allows the pre- and post-processing of messages, but the stack is really geared toward synchronous RPC-style messaging. While it’s possible to communicate with an ASMX web service asynchronously, there’s almost no support for a pub/sub messaging style. Also, there’s no support non-HTTP transports.
  • WSE 2.0: ASMX for the real world. Extensibility is made easier via the pipeline architecture. Lots of good WS-* support for solving tough problems like security, but still tied to the problems of the ASMX stack in the general case. However, if people are willing to abandon the ASMX stack and use the native messaging classes (SoapReceiver and SoapSender), the possibilities for doing non-RPC messaging over alternative transports are exciting.

There’s room here for something that combines the best features of all of these messaging API’s:

·         The messages-are-first-class-entities idea from System.Messaging.

·         The configurability and transport-agnosticism of the Remoting stack.

·         The extensibility and declarative nature of the ASMX stack.

·         The pipeline model, interoperability, WS-* support, and support for multiple messaging patterns offered by WSE.

It’s entirely possible that Indigo will realize some of these goals. While no one can say for sure, my guess is that WSE 2.0 is going to be positioned as “proto-Indigo” post-PDC. I do think it’s interesting that Omri Gazitt is a PM on the Indigo team and also owns WSE. Clearly, the two technologies are at least in some way related.

Like everything at this point, this is all speculation – can’t wait to learn what Indigo really is at the PDC!

Wednesday, September 17, 2003 3:09:26 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Saturday, September 13, 2003

BTJ is talking about the nasty tricksey XML serializer bug our team discovered yesterday.

In order to reproduce this, do the following:

·         Make sure you’re running 1.0 of the framework (this has been fixed in 1.1).

·         Define an enum and decorate it with the [Flags] attribute (non-[Flags] enums seem to work ok).

·         Inside of this enum, define more than 16 values.

·         Expose this enum over a web service.

·         Try to consume this web service.

If you run into the same bug we found, you’ll get a exception back that says “The assembly xsd fskj.dll, or one of its dependencies, could not be found” the first time you try to instantiate the service proxy. The name of the assembly will vary, because the exception is being thrown trying to locate the dynamically-generated assembly the XML Serializer creates to serialize the enum into XML.

Weird stuff -- Anybody else seen this?

 

 

Saturday, September 13, 2003 2:50:15 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Wednesday, September 03, 2003

Kent Sharkey points to a site that’s aggregating user-provided feature requests for Visual Studio.

Since I don’t feel like registering for the site, I guess I’ll just post my feature request here: I want a way to make XML Comments (and comments in general) less intrusive.

I like the idea of storing documentation as XML in the same file as the code. By keeping the documentation close to the code, it increases the likelihood that the comments will evolve alongside the code they document. I really like the idea of keeping them around as XML, because that lets me run a tool like NDOC over my solution and get nice, professional looking documentation almost effortlessly. The problem is, when I’m writing code I want to look at the code – and not have inches worth of ugly comments littered with distracting XML tags taking up valuable screen real estate that could be used to show me my code.

What I’d really like to see is a Documentor-style window that provided a real-time rendering of the XML comments contained in the source file I’m currently editing. I’d like to see this window be able to float outside of the Visual Studio .NET window, so I can move it to another monitor when I’m running dual-head without having to maximize Visual Studio across both displays. This documentation window would allow me to flip back and forth between a rendered view and an XML view, so I could edit the documentation easily. Any updates I make would be persisted when I saved the parent .cs file.

It would be very cool if, while this documentation window was open, any evidence of XML comments would disappear from the code view. However, when I saved a .cs file to disk, the documentation should appear in the exact same place it does today. This would let me view the plain old source file in a text editor and still see everything.

While I’m living in a fantasy world, I say get rid of regions. They’re a good idea and I know a bunch of people who really like them, but they’re they most friggin’ annoying things ever. They always seem like they’re collapsed when I want them to be expanded, and expand when I want them collapsed. And when they are expanded, there’s all of these ugly #region directives spamming up my code. Bleargh. Now that the CLR supports partial types, I say break up the file into separate chunks and rely on Visual Studio to give me an easy way to hyperlink to a file using a single-line editor comment (which should be preceeded by the comment token of whatever language I’m using at the time).

Wednesday, September 03, 2003 6:46:27 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Sunday, August 31, 2003

ASP.NET Web Controls support the addition of arbitrary user-defined via the Attributes property. This collection (of type System.Web.UI.AttributeCollection) is a handy place to programmatically add client-side event handlers to a control's rendered HTML.

I noticed today that the Add() method of AttributeCollection has slightly different semantics than the Add() method defined in other framework collection types. Most other name-value collections will throw an exception if you try to use Add() to insert a key that already exists. AttributeCollection.Add() will happily overwrite exsisting values. As such, these two calls are semantically equivalent:

control.Attributes.Add("foo", "bar");
control.Attributes["foo"] = "bar";

Whether this is a Good Thing or a Bad Thing is highly context-dependent. Regardless, it's something to watch out for.

Sunday, August 31, 2003 1:05:12 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Thursday, August 28, 2003

Harry Pierson and Phil Weber are talking about the fun that you can have using JavaScript’s intrinsic support for function pointers to achieve interception-like behavior.

This pattern is so useful – when it comes to extending the client-side functionality of ASP.NET, it’s really tough to extend the framework cleanly. This is because so much of the JavaScript that ASP.NET relies on is either generated at render-time ( doPostBack) or tightly coupled to an unmodifiable framework (the stuff in WebUIValidation.js). Function pointer interception provides a pretty good way around these problems.

For example, let’s say that you’re using the ASP.NET client-side validation controls. How do you set focus to the first invalid control without triggering a postback? Conceptually, it’s not that difficult – after client-side validation is complete, just find the first validator that’s in the “invalid” state and set focus to its corresponding control. This can be accomplished with the following loop:

for( var i=0; i < Page_Validators.length; i++ )
{
   if( !Page_Validators[i].isvalid )
   {
     document.getElementById(
             
Page_Validators[i].controltovalidate ).focus();
     return;
   }
}

Logically, you’d want this loop to execute any time that client-side validation completes. The ASP.NET framework function that kicks off client-side validation is called Page_ClientValidate() (it’s implemented in the file WebUIValidation.js, which lives in a version-specific subdirectory of the wwwroot\aspnet client\system.web directory). Unfortunately, it’s not extensible without modifying WebUIValidation.js (which creates deployment headaches and versioning problems). One way to get the desired functionality would be to implement the above loop in standalone function, and call that function immediately after any call to Page_ClientValidate(). However, since all calls to Page_ClientValidate() are generated, this would require some fairly ugly hacking to accomplish. A better way would be to use function pointer interception to add the desired behavior to the framework’s definition of Page_ClientValidate().

Function pointer interception takes advantage of the fact that function names in JavaScript are just variables whose values happen to be function implementations. Like variables of any other type, they are assignable. Using this language feature, it’s possible to swap out the old implementation of Page_ClientValidate() with a new, improved version of Page_ClientValidate() without having to modify any of the code that calls that function (it’s also possible to use this pattern to do all sorts of nasty things that could totally violate all reasonable assumptions that callers make about the behavior of the functions they call. Play nice and use discretion when applying this pattern).

Using function pointer interception, the extended version of Page_ClientValidate() looks like this:

//Make sure the Page_ClientValidate function exists
if( typeof( Page_ClientValidate ) == "function" )

     //Stash the old implementation in a temp variable
     Page_ClientValidateOld = Page_ClientValidate; 
     
     //Create a new implementation and store it
     //in Page_ClientValidate. Callers will now get
     //this implementation.

     Page_ClientValidate = function()
     {
          var isValid;

     
    //Call the old implementation first…
          isValid = Page_ClientValidateOld(); 
          
    
     //and then call our extension
          if( !isValid )
          {
            FocusOnInvalidControl();
          }

          return isValid;
      }
}

Once this code is included on a page, the any call the framework makes to the implementation stored in the Page_ClientValidate variable will include the desired extension functionality. All you have to do is include this after the script include for WebUIValidation.js. ASP.NET has a bad habit of putting that include pretty much wherever it wants, so putting the extension at the top of the page is not the best idea. However, putting it after the last control on the page works pretty well.

Addendum: I really like JavaScript, because it's powerful and flexible enough to make this kind of abstraction very easy. However, as I learned from Spider Man, with great power comes great responsibility. Writing code using this pattern is fun and exciting and potentially useful, but also potentially confusing to the point of being unmaintainable. Injecting just a few intercepted functions into a codebase can be very confusing precisely because it's so transparent to downstream callers. People unaware of the fact that interception is happening will be totally mystified by the behavior they see, and looking at the functions implementation will be of no help whatsoever. Use this pattern judiciously, and only as a last resort.

Thursday, August 28, 2003 9:55:28 AM (Pacific Standard Time, UTC-08:00)  #    Comments [9]
 Wednesday, August 20, 2003

I wish I’d had Korby Parnell’s blog around about 10 months ago; it would have saved a lot of headaches.

A long time ago (well, a long time ago by .NET standards), I was trying to get the directory structure of a project set up. The project already existed in Source Safe, and I was trying to figure out how to get integrated source control to work properly with the two web-based components of the solution.

The project consisted of a Web Services (ASMX) tier, a web client (ASPX), and a bunch of component libraries. It was laid out pretty much like this in VSS:

$ProjectRoot
   /SOURCE
       /ProjectNamespace.WebApp
       /ProjectNamespace.WebServices
       /ProjectNamespace.ComponentPackage1
       /ProjectNamespace.ComponentPackage2

Etc. There was a lot more in VSS, but you get the picture.

This structure was intended to be mirrored on the physical hard drive like so:

d:\project
d:\project\source\
d:\project\source\ProjectNamespace.WebApp  -> Hosted in IIS VRoot named “WebApp”
d:\project\source\ProjectNamespace.WebServices -> Hosted in IIS VRoot named “WebServices”
d:\project\source\ProjectNamespace.ComponentPackage1
d:\project\source\ProjectNamespace.ComponentPackage2

I say “intended to be mirrored” because I had some problems actually achieving this with VSS integration. Visual Studio would pull down the appropriate files during the “Open From Source Control” operation, but it insisted in creating the VRoots for the web projects at c:\inetpub\wwwroot. This was problematic because the source code for everything else lived under d:\project\source and I didn’t want code stored in two places on the physical drive.

I attempted to outsmart Visual Studio, by creating the VRoots in IIS ahead of time – the theory being that VSS Integration would create the projects using the existing VRoots, which were pointed at the correct physical location. However, that didn’t work because Visual Studio complained that there was already a VRoot with that name! I learned several months later via an MSDN TV episode that Visual Studio 1.0 will happily use existing VRoots so long as the name of that VRoot matched the name of the physical directory to which that VRoot is pointed (this is a bug in the project creation routines in VS 1.0). Things were breaking because there was a VRoot named “WebApp” pointed at a directory named “ProjectNamespace.WebApp”, which Visual Studio wasn’t very happy about. Had I changed the name of the physical directory to match the VRoot it probably would have been just fine – but, like I said, I didn’t know about that particular bug at the time all this was going on.

Someone suggested a different workaround that involved changing the physical location of the default website from the IIS default (c:\inetpub\wwwroot) to our project’s home directory (d:\project\source). While this eliminated the need to pre-create VRoots and ensured that the VRoots were created by Visual Studio in the correct physical location, it had the side effect of breaking Visual Studio’s ability to actually put files into those VRoots! By default, Visual Studio uses UNC file shares to do file IO for web projects. It assumes that any files accessible via a VRoot will be accessible through some subdirectory off the \\machineName\wwwroot$ share. The problem is that the wwwroot$ is an administrative share created and maintained by Windows, and as such you can’t delete it, rename it, or change it’s location very easily (at least not on Win2K, from what I found). Again, I probably would have been OK if I’d hacked the registry on the dev box to point wwwroot$ at d:\project\source, but I didn’t think of that at the time. Thinking back on it, I wish I would have investigated this a little more, but still – I shouldn’t have to hack locations of administrative shares just to get Visual Studio to put my files where I want them.

I managed to get things sort of working by pulling down all the project files via SourceSafe Explorer, setting up the appropriate VRoots in IIS, and then opening the solution for the first time in Visual Studio. In order to do this, the web projects had to be added to SourceSafe by hand – and I ended up with some of Visual Studio’s top-secret files in Source Safe when they shouldn’t have been. This caused numerous problems with SourceSafe bindings and things just didn’t seem to ever work “quite right.” At that point, I ripped out Visual Source Safe integration and just decided to use SourceSafe Explorer exclusively. As a consequence, I wasn’t able to take advantage of the productivity gains that integrated source control offers.

Now that it’s nine months later and I’ve learned a thing or two (check out this article on MSDN), I wish I had the opportunity to set that project up from scratch again. Looking back with the aid of the knowledge I’ve gained since then, I’ve realized that I took a few wrong turns:

  • Not naming our physical directories the same as the IIS VRoots they corresponded to
  • Adding ASP.NET projects to Source Control by hand
  • Not starting with the “blank solution in SourceSafe” approach
  • Trying to use both SourceSafe Explorer and Visual Studio to set up the solution.

I think Visual Studio 1.1 solves the naming bug, but I’m not sure. Regardless, I don’t the VSS Integration story is fully baked yet (especially when it comes to web projects). It’s too bad that I had to fight so hard against the tools to get the desired results – which I could only achieve by abandoning the tools entirely. Word on the street is that Visual Source Safe will undergo some hefty changes in the Whidbey timeframe; all I can say is that I'm looking forward to them.

Wednesday, August 20, 2003 6:20:08 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Thursday, August 14, 2003

I was looking at my referrer logs today, and noticed that my blog came up in a search on "XML Serializer read only property" -- which is funny in some ways, because I've never written anything about that topic. I have had to solve that problem, though.

The XML Serializer will only operate on publicly visible read/write properties or fields. Anything that's not public or not read/write will be invisible to the XML serialization mechanism -- and there's not much you can do about it. It would be great if this type of thing could be controlled via an attribute or something, but to my knowledge it's not...there's not much you can do except make sure that any property you want exposed is read/write.

Actually, that's not quite the requirement -- each property exposed to the XML serializer has to have both a getter and a setter defined. There's no requirement for that setter to actually do anything, however. One way to serialize a read-only property in XML would be to implement that property as follows:

public string MyReadOnlyString
{
   get{ return "I dare you to try and change this!"; }
   set{ }
}

MyReadOnlyString will be present in the XML representation, but the user cannot change it's value. Properties that need to be write-once can write directly to the property backer during construction to get the same effect.

The downside to this is that the property will look read/write to the client, who will probably expect it to behave differently than it really does. This can be addressed out-of-band (ugh) through documentation.

Thursday, August 14, 2003 2:08:47 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]
 Tuesday, August 12, 2003

Pretty cool presentation/talk on WSE 2.0 Hard Core Messaging by Keith Ballinger on MSDN-TV.

Messaging -- SOAP doesn't discriminate, but developers do. SOAP promised to bridge the religious gap between traditional RPC-style coding and document oriented messaging. With Web Services Enhancements (WSE) 2.0, the Microsoft platform now supports both styles of SOAP messaging, RPC request/response and sync/async messaging

[ScottW's ASP.NET WebLog]
Tuesday, August 12, 2003 6:43:45 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Thursday, August 07, 2003
My triumph over the ASP.NET page initialization mechanism
Thursday, August 07, 2003 2:11:27 PM (Pacific Standard Time, UTC-08:00)  #    Comments [10]

I just discovered the coolest feature in Visual Studio 2003!

Try this: write a stub for a class, like so:

public class Foo
{

}

Go back and declare that class as implementing a pre-defined interface, like IDisposable by changing the first line to be

public class Foo, IDisposable

When you type the last letter of "IDisposable", you get a tool tip that says "Press TAB to implement stubs for IDisposable." When you press tab, the IDE inserts a region in your code containing no-op implementations of the interface you just decided to implement. No more hunting down "Implement Interface" in Class View!

Sweet.

Thursday, August 07, 2003 1:02:40 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Monday, August 04, 2003

One of my coworkers (one Mr. Brian Vargas, who has a blog but never posts to it) and I were having a conversation this afternoon about how much we wished C# had a nameof() operator. The job of this operator would be to “quote” a lexical token that would otherwise compile into a member ref and turn it into a string (being the name of the member being referenced). I think this would make consuming the Reflection API's a lot cleaner.

For example, to get a PropertyInfo instance for a property named “Foo”, I currently say:

            Type t = this.GetType();
     
t.GetProperty(“Foo”);

It would be better for me to be able to say:          

           Type t = this.GetType();
     
t.GetProperty( nameof(this.Foo) );

The big benefits to this:

·         I get compile-time checks for the Reflection API. If my type doesn’t expose a property named “Foo”, I’d find out at compile time instead of runtime.

·         Intellisense.

It also simplifies calling methods that wrap the Reflection API’s. Let’s say I had a function that mapped ASP.NET controls to properties on an object. The signature looks like this:

public void MapControlToProperty( Control c, Object o, string propertyName )

Underneath the hood, this function uses the GetProperty() API. Callers of this code have to say something like:

            MapControlToProperty( txtFirstName, myPersonInstance, “FirstName” );

If the caller fat-fingers the propertyName string, they won’t find out until run-time when this code gets called. It would be much safer if I could use a nameof() operator to say:

            MapControlToProperty( txtFirstName,
                           
myPersonInstance, 
                            nameof( myPersonInstance.FirstName ) );

This way, the compiler can enforce the fact that the FirstName property actually exists, and the developer writing the code gets the benefit of Intellisense.

I don’t imagine that this would be that hard to implement – after all, isn’t this basically what the compiler’s doing under the hood when it encounters the delegate keyword?  The “magic” is already there – I’d just like to have a way to explicitly access it.

Monday, August 04, 2003 11:15:02 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Thursday, July 31, 2003

Korby Parnell has some interesting comments about the future of Visual Source Safe during the Whidbey timeframe.

The good news is that it looks like Microsoft will finally stop treating VSS like the bastard child of the Visual Studio family and might actually update it for Whidbey. It's about time that codebase changed -- the File dialogs still look like the Win3.1 Common Controls, for crying out loud.

Thursday, July 31, 2003 12:30:47 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
Yet another use for remoting proxies?
Thursday, July 31, 2003 6:31:38 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Wednesday, July 30, 2003

Just in case you haven't seen it already:

http://msdn.microsoft.com/vstudio/productinfo/roadmap.aspx

Wednesday, July 30, 2003 4:19:14 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

DonXML thinks that Visual Studio’s Edit and Continue feature can lead to bad programming habits. I see his point, but I’m personally wouldn't mind seeing this feature come to C#

Like Don, I’m a huge advocate of component-wise testing using mock objects or service stubs to test components in isolation. However, there comes a time when you have to integrate them and make all the “real” components play together. Once you reach that phase of a project, starting up a debugging session is suddenly a non-trivial experience. Even in just simple client-server scenarios the amount of time it takes to bootstrap the system can be prohibitive (or even just really annoying). And it’s in these cases where Edit and Continue provides a real productivity boost.

I don’t want Edit and Continue to save me from stepping through needless amounts of code; I want Edit and Continue to save me from having to manually attach debuggers to 3 different processes every time I need to make a minor change during integration testing.

Updated: The status of Edit and Continue is still up in the air (at least for C#, anyway!) Didn't mean to suggest that is wasn't...

Wednesday, July 30, 2003 8:13:04 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Sunday, July 27, 2003
My response to Dare's response to my response to Dare.
Sunday, July 27, 2003 1:07:09 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Saturday, July 26, 2003
The one in which I disagree with people who are a lot smarter than I am.
Saturday, July 26, 2003 8:22:25 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

Ted Neward has a fantastic article over at ClrGeeks on Strongly Typed Infosets in .NET.

The solution he presents is a good compromised between the loosely-typed extensible XML world and convenience of strongly typed objects.

As we move toward a Web Services world that allows to stay closer to the native XML messages, I think we're going to see data being shipped around in these sorts of objects. All we need now is a generative framework for building these classes from XSD schemas, and we're good to go.

Saturday, July 26, 2003 6:44:06 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
More than you ever wanted to know about ChainStream()
Saturday, July 26, 2003 4:16:30 AM (Pacific Standard Time, UTC-08:00)  #    Comments [8]
 Thursday, July 24, 2003
Questioning Ingo Rammer. But not really.
Thursday, July 24, 2003 4:04:56 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

A great deck about the internals of the .NET Garbage Collector, by one of the guys who wrote it.

[Via Brad Abrams]

Thursday, July 24, 2003 3:31:29 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Wednesday, July 23, 2003

Sean Van Ness describes how to include the same C# source file in multiple assemblies using Visual Studio.NET.

Adding this to the "Things I didn't know about Visual Studio" file.

Wednesday, July 23, 2003 1:23:53 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
Why I don't like the XML serializer
Wednesday, July 23, 2003 3:41:40 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Tuesday, July 22, 2003
Deep dive with Reflector!
Tuesday, July 22, 2003 2:52:50 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Sunday, July 20, 2003
Thoughts on where .NET web services are going
Sunday, July 20, 2003 8:22:31 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Friday, July 18, 2003
The inevitable link to MSDN
Friday, July 18, 2003 2:00:34 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]