Scott Hanselman

Computer Zen - Meaning

March 23, 2005 Comment on this post [2] Posted in Musings
Sponsored By

A chinese fellow asked recently about my Blog's Logo. When I say 善/Zen" I mean Nice, Good, Postive. Arguably I could have used 禪/Zen to mean Buddist-like Enlightenment, but I like that 善 is pronounced (more or less) like "Zen."

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

Hanselingo - The Language of the Hanselman

March 23, 2005 Comment on this post [3] Posted in Speaking
Sponsored By

OMG. Travis has a glossary now to explain my "way of speaking." Hanselingo - The Language of the Hanselman. Travis, you suck. :)

Now I need to come up with new phrases.

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

Enabling Evil - Tunnelling Xml within Xml using the XmlSerializer and some Magic

March 23, 2005 Comment on this post [1] Posted in ASP.NET | DasBlog | XmlSerializer
Sponsored By

I'm ashamed to even post this, as Dare and Oleg will likely balk at the audacity and pure poo of the solution.

That said, sometimes you have to support a legacy evil, er, solution and one's (mine) overdeveloped sense of code smell must be supressed.

So, there's some XML, it's as a schema and it's cool and strongly typed. It might look something like:

<?xml version="1.0" encoding="utf-16"?><ns0:SignOnResponse xmlns:ns0="http://www.corillian.com/Voyager/Authentication/Messages/2004/05"><ns1:Header xmlns:ns1=http://www.corillian.com/operations/2004/11">
<ns1:Something>somethingCoolio</ns1:Something>
...blah blah blah...
</ns0:SignOnResponse>

You get the idea...it's generated, but it's legit. Here's the weird part...for a legacy app, another XML Document (arguably a Fragment) is "tunnelled" within one of the the larger document's elements:

<ns1:Something><![CDATA[<holycrap><sweetlord>it's another xml document! hiding inside! Wow, it has no namespace? Oy.</sweetlord></holycrap>]]</ns1:Something>

Notice above that there's another entirely different document inside the larger one.  Additionally the fragment has a root node of "sweetlord" perhaps I want it to be deserialized into a "SomethingType." Since "SomethingType" was defined in XSD and generated earlier, I can't change it's [XmlRoot] without editing the generated code.

But, I can override it. So, this technique below shows two things.

  • Taking an Xml fragment that has no namespace and fooling the XmlSerializer (or any XmlTextReader consumer) into thinking it does using Clemen's/Chris's (dasBlog's/BlogX's) XmlNamespaceUpgrading Reader.
  • Using XmlAttributeOverrides to force the XmlSerializer to "no no, use THIS XmlRootAttribute!"
// myLargerResponse was deserialized from Xml.

// The Something property is a string containing an Xml Fragment

// as shown above. That fragment has no namespace, but there is a

// generated object WITH a namespace that it could deserialize into

// (it matches the "data contract.")

string tunnelledString = myLargerResponse.Something;

if(savedSerializer == null)

{

    XmlRootAttribute xra = new XmlRootAttribute("holycrap");

    xra.Namespace = "http://www.corillian.com/something/messages/2004/05";

 

    XmlAttributes attrs = new XmlAttributes();

    attrs.XmlRoot = xra;

 

    XmlAttributeOverrides over = new XmlAttributeOverrides();

    over.Add(typeof(SomethingType),attrs);

 

    savedSerializer = new XmlSerializer(

            typeof(SomethingType),

            over);

}

SomethingType info = savedSerializer.Deserialize(

        new XmlNamespaceUpgradeReader(

            new StringReader(tunnelledString),

            String.Empty,

            "http://www.corillian.com/something/messages/2004/05"))

        as SomethingType;

Here's the XmlNamespaceUpgradeReader. Notice that it's used above passing in String.Empty as the oldNamespaceUri, and the namespace we WISH it had as the newNamespaceUri. That's the namespace we told the XmlSerializer in the AttributeOverrides.

Note also that we save away the XmlSerializer because of the XmlSerializer leak for its complex constructor overrides. As an alternative to saving it off, we could use the very cool Mvp.Xml.XmlSerializerCache.

public class XmlNamespaceUpgradeReader : XmlTextReader

{

    string oldNamespaceUri;

    string newNamespaceUri;

 

    public XmlNamespaceUpgradeReader( TextReader reader, string oldNamespaceUri, string newNamespaceURI ):base( reader )

    {

        this.oldNamespaceUri = oldNamespaceUri;

        this.newNamespaceUri = newNamespaceURI;

    }

 

    public override string NamespaceURI

    {

        get

        {

            // we are assuming XmlSchemaForm.Unqualified, therefore

            // we can't switch the NS here

            if ( this.NodeType != XmlNodeType.Attribute &&

                base.NamespaceURI == oldNamespaceUri )

            {

                return newNamespaceUri;

            }

            else

            {

                return base.NamespaceURI;

            }

        }

    }

}

 

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

Visual Studio Team System and Pricing - My brief historical perspective

March 22, 2005 Comment on this post [14] Posted in Programming
Sponsored By

A lot of folks are up in arms about the Visual Studio Team System (VSTS) Pricing announcements. It looks to be a little spendy, and targeted directly at large companies.

Now, I have a tendency to over-simplify, largely because I'm a simpleton. Here's what I think via historical analogy:

  • Most Windows Developers didn’t use Source Control in the early 90’s until Microsoft bought OneTree Software’s “SourceSafe” and make it available for free.
    • Conclusion: Free integrated SourceSafe arguably made source control happen in Windows development. Before, 99% of casual and small-company developers were just zipping stuff up.

So, it follows that

  • While the ingredients of for TDD (Test Driven Development) and CI (Continuous Integration) are free and Open Source, they are varied and confusing.
    • Conclusion: If there isn’t a Free (or darn near free) integrated solution with VS.NET (that we already own) for TDD and CI, then most developers won’t use ever get the dramatic benefits of Test Driven and Continuous Integration development.

Thoughts?

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

Separating a Web Service's Implementation from the ASMX File

March 20, 2005 Comment on this post [5] Posted in ASP.NET | Web Services | DasBlog
Sponsored By

A fellow said recently that he wanted to build a "monster web service" with over 20 classes and over 20 methods (well, not THAT monster, but not Hello World). He said:

Is there any way to provide my consumers with a single end-point (.asmx) exposing these methods from several different class files? I can't see my dev team all working on a single ASMX file...what am I missing here?

It's easy to make the assumption that the ASMX file has some magic and that everything needs to go in it. But the ASMX is just an endpoint like an ASPX or ASMX. It gives IIS and ASP.NET something to think about, but it's just a broker - even less - it's a front.

DasBlog has a Web Services interface, thanks to Clemens and the crew before Omar and I, and here's the contents of it's EditService.asmx.cs:

[WebService(Namespace="urn:schemas-newtelligence-com:dasblog:edit-services")]

 public class EditService : EditServiceImplementation

 {

 }

That's it. Seriously. It lives in our main Web Project.  So, how does this work? Well, look at what the class it's derived from. It's not System.Web.Services.WebService (yet), it's EditServiceImplementation.

RULE: Don't mix your implementation with your presentation

A Web Services endpoint is arguably just a presentation of some logic. Hopefully that logic exists somewhere that's NOT the ASMX file. The ASMX file is just a way to call something somewhere else.

For example, here's part of the source for EditServiceImplementation.cs that's in a totally different assembly and project.

public class EditServiceImplementation : WebService

{

    [WebMethod]

    public string CreateEntry(Entry entry, string username, string password)

    {

        SiteConfig siteConfig = SiteConfig.GetSiteConfig();

        if (!siteConfig.EnableEditService)

        {

            throw new ServiceDisabledException();

        }

 

        if (SiteSecurity.Login(username, password).Role != "admin")

        {

            throw new Exception("Invalid Password");

        }

 

        // ensure that the entryId was filled in

        //

        if (entry.EntryId == null || entry.EntryId.Length == 0)

        {

            entry.EntryId = Guid.NewGuid().ToString();

        }

 

        ILoggingDataService logService = LoggingDataServiceFactory.GetService(Context.Server.MapPath(siteConfig.LogDir));

        IBlogDataService dataService = BlogDataServiceFactory.GetService(Context.Server.MapPath(siteConfig.ContentDir), logService);

 

        SaveEntry(entry, "", null, siteConfig, logService, dataService);

 

        return entry.EntryId;

    }

    //SNIP...

This shows EditServiceImplementation (remember, NOT in the ASMX.cs file) deriving from WebService. It also shows the CreateEntry method that is marked as a [WebMethod] and exposed to the outside world.

Note that this method takes an Entry, a username and a password. Internally it checks to see if Web Services are enabled, tries to log the user in then calls the existing .NET API method "SaveEntry".

SaveEntry already existed. the CreateEntry WebMethod is a stateless rollup of Login and SaveEntry.

So, in this example:

WebService Request -> EditService.asmx -> EditService class, deriving from EditServiceImplementation -> Validate the User, etc -> Broker to existing SaveEntry API.

We leverage the existing dasBlog DataService, we easily create other endpoints (foo.asmx) in a number of ways, the implementation doesn't even live in the Web Project, and even then, the Implementation is ten lines of code.

Don't let your [perception] of the  ASMX file cramp your style. You can add a few small layers and not only make development of your Web Service easy, but also friendly for large development groups. Idea: If you're concerned about collision, folks can test and work on their own atomic endpoints before rolling everything up into one WSDL. Also, remember Contract First.

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.