Scott Hanselman

Use of Posters and Flow Charts in Lieu of Prose for Documentation - Is a Visio is Worth a Thousand Words?

July 22, 2004 Comment on this post [0] Posted in XML | Web Services | Tools
Sponsored By

We've got fairly powerful (but some say, complicated) Code Generation process that uses XML Schema along with (with thing) an interesting use of WSDL with an alternate binding.  Voyager is our flagship snazzy eFinance Server and using standard modelling tools (XMLSpy, VS.NET, etc) one (business person, computer wonk, whoever) can sit down and model all their Domain Objects, Request and Response Messages in XSD (nouns) and associate them with actual Voyager Operations (verbs) in WSDL.  Then rather than using a SOAP binding (if they were to talk to a Web Service with these messages) they can use a Voyager Binding in WSDL.  Then we run a Code Generation process on the WSDL/XSD and generate all the C# objects, messages, proxy layers, Word Documentation, yada yada yada. 

All this is built into our Continuous Integration Process so when one checks in an XSD into the Version Control System those artifacts are automatically built and made available to others.

Since this is a fairly complex experience to the non-XML initiated, a lot of prose has been written and a lot of hand waving happens to explain this process.

Some users though felt the prose was, well, too prose-y, and wanted a quicker way to grok the material. 

So, I spent two days in Visio creating a 44" by 34" poster (FOUR 11" by 17" pages or one big Plotter plot) that has the source of the XSDs, the source of the generated objects and stacks, as well as diagrams describing the relationships between objects when they exist in a running process. 

People can look at the code generation progression as well as the composition of elements:

  • Declarative XSDs (multiple ones, lots of imports, namespaces and custom attributes)
  • Generated C# code
  • Assembly names, class names, .NET namespace names
  • Resulting compiled assemblies
  • How those final build artifacts exist in a running system

I've finished the first draft (this screen shot is to give you an idea of the scope and size of this poster) and will share it with the team tomorrow. 

How often do you or your groups create one large diagram instead of writing one or more large documents?  When are architecture & design posters useful and when are just trouble?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The Computer Back - Pain and the Programmer

July 20, 2004 Comment on this post [31] Posted in Programming
Sponsored By

I'm on my butt today.  More specifically, on my back.  This weekend my lower back seized up - just one muscle it seems, as the back turns into butt.  It's amazing how a little stabilizer muscle can go nuts suddenly and mess up your whole system. 

I call it "Programmer Back" as there are a handful of other folks that sit in front of a machine all day that have had this problem. 

It seems the symptoms are nearly universal:

  • Everything is fine, often for months.
  • A seizing happens and you drop to your knees.
  • Often you can't stand without help, or if you do, you're bent over like an old person.
  • If you don't move, you're OK, but bending over, or rolling out of the bed become impossible.
  • It lasts for as little as 3 days or a much as a week and a half.

Some say ice, some say heat, some say massage.  Still others advocate chiropractic.

Have you had Programmers Back?  How do you deal with it?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Validating that XmlSchemas and their Imports are Valid and All Good with an XmlResolver.

July 15, 2004 Comment on this post [1] Posted in XML | Bugs
Sponsored By

The very awesome Oleg Tkachenko commented in a recent post of mine (as did Patrick Cauldwell, in person) that what I was doing could have been accomplished with a custom XmlResolver.  Both are absolutely right.

I did my little hack because it was quick but Oleg's right, it would have been "more correct" to do something like this:

public class XmlCustomResolver : XmlUrlResolver
{
  override public object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
  {
     //Here, mess with absoluteUri.AbsolutePath and return an XPathNavigator or Stream or whatever
 
}
}

So what happens is that you pass in the Resolver into the call to .Compile like:

foreach(XmlSchema x in w.Schemas)
{
  
x.Compile(new ValidationEventHandler(OnValidationEvent), new XmlBaseDirectoryResolver());
}

However, my problem was a smidge more subtle than it initially appeared.

The problem was, for me, that I want to resolve the schemaLocations (which look like "banking/someDomainObject.xsd") relative to the path that the WSDL is in, like "C:\dev\whatever\wsdl\".  However, by the time we get into the Resolver (when .Compile calls back to GetEntity()) the propery absoluteUrl.AbsolutePath already contains "C:\dev\MyTestConsole\bin\debug\someDomain\banking\someDomainObject.xsd."  See?  It's already "pre-resolved" the path relative to AppDomain.CurrentDomain.CurrentDirectory

At this point, I have no way (that I can see) to know what was the original relative path.  I want the schemaLocation to be "C:\dev\whatever\wsdl\banking\someDomainObject.xsd."  I could have passed the directory of the WSDL file into the constructor call to the Resolver.  So we add:

foreach(XmlSchema x in w.Schemas)
{
   x.Compile(new ValidationEventHandler(OnValidationEvent), new XmlBaseDirectoryResolver(wsdlFile.DirectoryName));
}

Note that the AbsolutePath has the Directory Separators as "/", so I have to fix those as well.  Here's the final "XmlBaseDirectoryResolver."  It's more lines of code, but it's also reusable.

public class XmlBaseDirectoryResolver : XmlUrlResolver
{
 
private string baseDir = String.Empty;
  public XmlBaseDirectoryResolver(string baseDirectory) : base()
 
{
   
baseDir = baseDirectory;
 
}

 
override public object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
 
{
   
if (absoluteUri.IsFile == true)
    
{
      
//Change the directory characters to the same ones that AppDomain.CurrentDomain.BaseDirectory uses
      
string newFileName = absoluteUri.AbsolutePath.Replace('/',Path.DirectorySeparatorChar);
      
//Now, yank the automatically added portion...
      
newFileName = newFileName.Replace(AppDomain.CurrentDomain.BaseDirectory,String.Empty);
      
//Add our Base Directory...
      
newFileName = Path.Combine(baseDir, newFileName);
      
//Return the file...
      
return new FileStream(newFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
    }
    return base.GetEntity(absoluteUri, role, ofObjectToReturn);
  }
}

The big problem with this particular result?  It doesn't work with relative paths that use the dotdotslash "../../whatever/this.xsd."  At this point - the point of resolution - too much has been already resolved for me. :)  The only way I could fix that would be to work backwards to figure out how many ../..'s were removed for me, and put them back.  Not worth it.

Oleg has a great article up on his blog on how to Create your Own XmlResolver.  His actually retrieves the schema (stored) in a SQL Server. 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Using the Server (rather than Workstation) Garbage Collector with the .NET Framework (CLR)

July 15, 2004 Comment on this post [2] Posted in ASP.NET | XML | Tools
Sponsored By

We run a big .NET Application Server, often on multi-proc machines, so we care about performance and, consequently, garbage collection.  I've collected a few resources around the two kinds of Garbage Collectors available in .NET, the Workstation GC and the Server GC.

From the MSDN Help:

Two different Garbage Collectors are available for the CLR: a Workstation GC and a Server GC. Console and Windows Forms applications host the Workstation GC, and ASP.NET hosts the Server GC. The Server GC is optimized for throughput and multi-processor scalability. The server GC pauses all threads running managed code for the entire duration of a collection, including both the Mark and Sweep Phases, and GC happens in parallel on all CPU's available to the process on dedicated high-priority CPU-affinitized threads. If threads are running native code during a GC then those threads are paused only when the native call returns. If you are building a server application that is going to run on multiprocessor machines then it is highly recommended that you use the Server GC. If your application in not hosted by ASP.NET, then you are going to have to write a native application that explicitly hosts the CLR.

HINT:   If you are building scalable server applications, host the Server GC. See Implement a Custom Common Language Runtime Host for Your Managed App.
  • Hosting the CLR in a generic service and Hosting the Server GC: "To load the svr GC, we created a generic Windows service that loads the svr GC, creates an AppDomain, and runs our application."
     CComPtr spRuntimeHost;
     HRESULT hr = CorBindToRuntimeEx(NULL, 
       //Retrieve latest version by default
      L"svr",
     
       //Request a Server (svr) or WorkStation (wks) build of the CLR
      STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN, 
      CLSID_CorRuntimeHost,
      IID_ICorRuntimeHost,
      (void**)&spRuntimeHost);
  • Using the Server Garbage Collector:  
    1. Create the system environment variable COMPLUS_BUILDFLAVOR to SVR
    2. SET COMPLUS_BUILDFLAVOR = SVR
    3. Generate this key in the windows registry: HKLM/Software/Microsoft/COMPlus with a single string value BuildFlavor with value "svr"
    SDH Note: This is fully unsupported my Microsoft.
  • Improvements in .NET 1.0 SP3 and .NET 1.1 SP1 and How to enable CLR Server GC?
     <Configuration>
        <runtime>
            <gcServer enabled=“true“ />
        </runtime>
    </Configuration> 

From Chris Kinsman: Here’s a way to do it that’s not a hack – right-click on My Computer in .NET Configuration in Administrative Tools. UPDATE: In fact, this is NOT so, details on this setting at OdeToCode.com

 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Validating XML schemas that have been xs:imported and have schemaLocation

July 13, 2004 Comment on this post [4] Posted in Web Services | XML
Sponsored By

In this example, Wsdl is a class that's one of our internal convenience wrappers around System.Web.Services.Description.ServiceDescription.  The Schemas property is just the XmlSchema[] that from service.Types.Schemas. 

I wasn't sure if my WSDL file was kosher, and I wanted to "validate" the whole setup.  Most of my XML Schemas were pulled in via xsd:import in my wsdl like:

 <wsdl:types>
  <xsd:schema targetNamespace="
http://www.corillian.com/thingie/operations/2199/05" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd1="http://www.corillian.com/thingie/operations/2199/05"> <!-- bogus namespaces for example -->
   <xsd:import namespace="
http://www.corillian.com/thingie/banking/domain/2199/05" schemaLocation="..\banking\BankingDomain.xsd"/>
  </xsd:schema>  
 </wsdl:types>

...and as you can see, the schemaLocation was relative.  The way I was going to force a Validation of the XML Schemas (other than physically loading each of them into memory myself) was to call .Compile().  However, it appears that the relative paths were being resolved relative to the Current AppDomain's current directory, NOT the directory the WSDL was located in!  So:

Wsdl w = new Wsdl();
w.Load(file.FullName);
foreach(XmlSchema x in w.Schemas)
{
  foreach(XmlSchemaImport i in x.Includes)
  {
    
i.SchemaLocation = Path.Combine(file.DirectoryName,i.SchemaLocation);
  
}
  x.Compile(new ValidationEventHandler(OnValidationEvent), new XmlUrlResolver());
}

Before I mess with the WSDL and Schemas, I take the directory that the WSDL file was located in and use it as a base directory for the relative schemaLocation.  Thank goodness the SchemaLocation property was not readonly! :)  Using Path.Combine has the added benefit of collapsing ".." relative paths.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.