Scott Hanselman

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

July 12, '04 Comments [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 twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Obscure Off-Topic Tip of the Day - How to Get Windows Explorer File Copy/Move to "Yes to All" or "No to All"

July 10, '04 Comments [2] Posted in Musings
Sponsored By

Thanks to John Elliot, how to get Windows Explorer to "Yes to All" or "No to All":

If you are copying manually in the GUI with a drag and drop or a
CTRL+C/CTRL+V then press SHIFT when you click 'Yes/No' the first time you are prompted and it will remember that as the default answer for all other files in the copy operation.

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 twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Creating your own Custom PatternLayout, PatternParser, and PatternConvertor with log4net

July 9, '04 Comments [4] Posted in ASP.NET
Sponsored By

Log4Net was ported over from the stunning and wonderful Log4J.  Log4Net supports a large series of Appenders that let you, via a config file, setup a series of destinations for your logging calls.  For example, without recompiling your app, you can send Logging information to a Database, or a File, or ASP.NET Tracing.  It's very flexible, and easier to use (IMHO) than the Microsoft Logging Application Block.

Additionally there's a concept called a Layout that affects the logging data and either formats or adds extra information like the thread id, username, etc.  It's very powerful because your Layout will work for and affect any Appender which makes for nice reuse.  So, for example:

    <!-- A1 is set to be a ConsoleAppender -->    
<appender name="A1" type="log4net.Appender.ConsoleAppender">
<!-- A1 uses PatternLayout -->
<layout type="Corillian.Whatever.Log4NetStuff.CustomPatternLayout, Corillian.Whatever.Log4NetStuff">
<conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline %G" />
</layout>
</appender>

Here's we're outputing the message, as well as timestamp and thread info. 

I wanted to add my OWN CustomPatternLayout and add additionally %whatever tokens.  This is done all the time in Log4J.

HOWEVER, in the log4net source, there's a function "FinalizeConverter" in PatternParser.cs that you need to override when you derive you own CustomPatternParser from PatterParser.  But, it's not marked virtual.  Crap. 

It makes total sense though, as everything in Java (where this code was ported from) is virtual and can be overridden.  They just forgot to set that log4net 1.2-beta8.  That's why it's beta. :)

So, if you make this change in PatternParser line 237:

protected virtual void FinalizeConverter(char c)

...then you'll be all set to do something like this:

public class CustomPatternLayout : log4net.Layout.PatternLayout
{
  
public SecurityPatternLayout() : this(log4net.Layout.PatternLayout.DEFAULT_CONVERSION_PATTERN){ //whatever }
  public SecurityPatternLayout(string pattern) : base(pattern){ //whatever }
  protected override PatternParser CreatePatternParser(string pattern)  //where we override and return US as a PatternParser
  {
    return new SecurityPatternParser(pattern == String.Empty ? log4net.Layout.PatternLayout.DEFAULT_CONVERSION_PATTERN : pattern);
  }
}

public class SecurityPatternParser : log4net.helpers.PatternParser
{
 
public SecurityPatternParser(string pattern) : base(pattern){}
 protected override void FinalizeConverter(char c)
 {
  if (c == 'G') //where 'G' is your custom token like %G in the format string
 
{
   
AddConverter(new SecurityPatternConvertor()); //Where we add ourselves into the mix, since our token (%G) appears in the format string
 
}
  else base.FinalizeConverter(c);
}

public class SecurityPatternConvertor : log4net.helpers.PatternConverter
{
 
public SecurityPatternConvertor() : base(){}
 
public SecurityPatternConvertor(FormattingInfo formattingInfo) : base(formattingInfo) {}
 
 override protected string Convert(LoggingEvent loggingEvent)
 
{
    
return MessWithThisMessage(loggingEvent.RenderedMessage); //Where we mess with the string however we decide %G should affect 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 twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

"The dependency whatever.dll cannot be copied to the run directory because it would conflict with the dependancy...

July 9, '04 Comments [4] Posted in ASP.NET | Bugs
Sponsored By

This is always a lovely error to get:

"The dependency whatever.dll cannot be copied to the run directory because it would conflict with the dependancy..."

And again, it all comes down to knowing the places to look.  If you open up the .csproj (or .vbproj) files you'll often see something like:

<Reference
 Name = "Corillian.Voyager.Thingie"
 AssemblyName = "Corillian.Voyager.Thingie"
 HintPath = "..\..\..\build\bin\Corillian.Voyager.Thingie.dll"
/>

And assume that the HintPath is the place that VS.NET looks to resolve the reference.  But, it's only a hint to the IDE.  Often you'll have a situation where a project builds fine on one machine but not other, then the real evil resides in a file that you don't (shouldn't) check into source control and share, the .csproj.user file.  In that file you'll find something like:

<VisualStudioProject>
    <CSHARP LastOpenVersion = "7.10.3077" >
        <Build>
            <Settings ReferencePath = "C:\Dev\VoyagerThingie\source\lib\Voyager\; C:\Dev\VoyagerThingie\source\lib\log4net\; C:\Dev\VoyagerThingie\build\bin\" >

What tends to happen is that folks forget about these files, and as versions change schmutz can creep into these files.  So, when debugging bizarre reference problems, remember to check out the .user file! (or delete it and build it up again)

 

 

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 twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Bad-ass ASP.NET contractor needed

July 9, '04 Comments [0] Posted in ASP.NET
Sponsored By

If you're a ruthlessly competent ASP.NET/C#/*.* developer in the Portland/SW Washington  Area, and you grok most of the technical stuff posted on my blog, email me a resume.
Scott Hanselman - Corillian Corp
scott@corillian.com
--------------------------
Sent from my BlackBerry Wireless Handheld

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 twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

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