The other day I had the chance to peruse the work of another developer, a Microsoft MVP. The code was less than impressive. To be frank, it stunk, but it stunk in a strange way. It had a weird combination of advanced technique and rank naiveté. There was separation of concerns, but it was much more convoluted than it needed to be. The things the code were relatively trivial, but it was hidden behind a bag of patterns and the structure of the classes made finding the code that did the real work an exercise in spelunking.

I mentioned it to a friend of mine, and he shared his story about a hiring interview with an MVP carrying job candidate. The story was eerily similar. The candidate was well versed with the latest and greatest development methodologies, but seemed to lack a grasp of writing a simple “fizz-buzz”. To make matters worse, part-way through the interview the candidate starting listing their “requirements”, which conferences they’d be attending, which technologies they would use, etc.

I was flabbergasted. Granted, my friend was glad the candidate was so forthcoming with his lack of professionalism. It helped make his decision not to hire the guy much easier. After I thought about it a little bit more, I realized that the fault wasn’t totally with the MVPs in question. All of us share a little of the blame.

More…

Just posted a new entry on adding properties to a WCF behavior that get their values from the config file.

http://steverb.com/post/2008/11/25/Passing-Configuration-Values-into-WCF-Behaviors.aspx

Behaviors in WCF are so stinking useful, and once you get past the basics of WCF they’re arguably a necessity. Microsoft has saved itself from hundreds of hours of cursing by including the ability to define custom behaviors.

So far, my favorite use of behaviors is to use them to address some cross cutting concerns that we consistently have to address in our WCF services. Specifically logging, service registration, wsdl tweaking, and error handling. Which brings us around to the IErrorHandler interface.

More…

I’ve moved to my own domain, finally.

See you at http://www.steverb.com

I spent an hour last night fighting with the free wordpress account to try and get code to format properly, to no avail.

I used Windows Live Writer tonight, with no luck.

So I’ve gone ahead and bit the bullet.  I’m now the proud owner of steverb.com, where this blog will be moving in the next few days.

Stay tuned.

If you’ve done any work with WCF and non .NET clients, you’ve probably had the need to make WCF emit a flattened WSDL that doesn’t use xsd includes. You’ve probably run across Tomas Restrepo’s InlineXSDInWSDLBehavior and Christian Weyer’s FlatWSDL extension. They both work quite well. Possibly too well.

We noticed .NET behaved strangely when referring to a service that had a flattened wsdl.  Everything was a string and all collections were arrays.  Basically, rather than having the luxury of telling the proxy what the underlying data type was and having it handle the appropriate serialization we had to cast everything to and from the underlying on the wire data. It was workable, but in truth it kinda sucked. So, I figured there had to be a way to make WCF emit flat wsdl only when we wanted it.

After spending way too much time chasing down blind alleys I finally decided to just implement a IDispatchMessageInspector as a ServiceBehavior and be done with it. There’s proably a nicer, better way to do this, but I haven’t found it.

The first thing that needed to be done to make this work was figure out if the request that was about to be sent was in response to a wsdl query.  I didn’t find a straight forward way to get that information in BeforeSendReply, so I just grabbed the request URI in the AfterReceiveRequest method and spit it back out as the correlation state object.

 

 public object AfterReceiveRequest (ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
      //set the uri to the correlation property
      return request.Properties.Via;
    }

 

Once I had the uri, then I pulled the query string out in BeforeSendReply and if it was a wsdl request (at the standard address) and it specified flat, we can intercept the response and send the flat wsdl instead. While I was in there intercepting things, I thought it would be nice to add a link to the flattened wsdl in the default service description page. So, in the case that a request comes in at the base address with no arguments, then we look and see if the response is the default page and if so, we add our new link to it.


public void BeforeSendReply (ref System.ServiceModel.Channels.Message reply, object correlationState)
{
      Uri URL=(Uri)correlationState;
      string query=URL.Query;
 
      string baseaddress=OperationContext.Current.Host.BaseAddresses[0].ToString();
      
     //is there any possiblity that this is a wsdl request?
      if (query.StartsWith(“?”, StringComparison.OrdinalIgnoreCase)) 
     {
        query=query.Substring(1);
        List<string> queries=new List<string>((query.Length>0)?query.Split(new char[]{‘&’}):new string[0]);
 
        //if it’s a flat wsdl request we need to fix it up
        if (queries.Contains(“wsdl”) && queries.Contains(“flat”)) 
       {
          reply=BuildFlatWsdlReply(reply);
        }
      }
 
      //if they’re just going to the base address, then we need to spruce up the default page
      else if (URL.ToString().ToLower()==baseaddress.ToLower())
     {
        reply=BuildDescriptionPage(reply, baseaddress);
      }
    }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

   

BuildFlatWSDLReply creates a new WsdlExporter, uses it to export the endpoints of the current ServiceHostBase, and sends it along to the methods cribbed from Tomas Restrepo’s code for export. Once the wsdl comes back it writes it out to a memory stream and passes it along in a reader to Message.CreateMessage and copies the original method’s header and properties to our new and improved message.

 

private System.ServiceModel.Channels.Message BuildFlatWsdlReply (System.ServiceModel.Channels.Message reply)
{
      //create a wsdl exporter and export the endpoints
      WsdlExporter exporter=new WsdlExporter();
      ServiceHostBase myHost=OperationContext.Current.Host;
 
      //creates the wsdl doc
      exporter.ExportEndpoints(myHost.Description.Endpoints, new System.Xml.XmlQualifiedName(myHost.Description.Name, myHost.Description.Namespace));
      System.ServiceModel.Channels.Message replyMessage=null;
      
    //write the wsdl as xml to a memory stream
      MemoryStream meStream=new MemoryStream();
      XmlWriter meXML=XmlWriter.Create(meStream);
      ServiceDescriptionCollection myServices=GetFlatWsdl(exporter);
      myServices[0].Write(meXML);
      meStream.Position=0;
 
      //create a reader to pass into the message body
      XmlReader meRead=XmlReader.Create(meStream);
      replyMessage=System.ServiceModel.Channels.Message.CreateMessage(reply.Version, reply.Headers.Action, meRead);
 
      //copy everything else from the original message
      replyMessage.Headers.CopyHeadersFrom(reply.Headers);
      replyMessage.Properties.CopyProperties(reply.Properties);
      reply=replyMessage;
      return reply;
    }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

   

The code for building the description page does something similar, but in this case it checks to see if the reply includes the wsdl url and if it finds it, appends the instructions for getting the flattened wsdl if needed. This particular piece of code is ugly, and could benefit from a judicial use of regular expressions. I’m including it here for completeness sake. Don’t flame me about it unless you decide to include the code to fix it. 😉

private static System.ServiceModel.Channels.Message BuildDescriptionPage (System.ServiceModel.Channels.Message reply, string baseaddress)
{
      string body=reply.ToString()+“</HTML>”;
 
      //reply stream omits the closing tag for some reason;
      string stringToFind=“<A HREF=\”"+baseaddress+“?wsdl\”>”+baseaddress+“?wsdl</A></PRE></P>”;
      int foundat=body.IndexOf(stringToFind);
 
      //if the wsdl string is found, fix up the reply otherwise, just send it back since we can’t deal with it.
      if (foundat>0) 
     {
        System.ServiceModel.Channels.Message replyMessage=null;
 
        //modify the standard page and shove it in a string
        StringBuilder insertText=new StringBuilder();
        insertText.Append(“<P class=’intro’>If your client requires a flattened version of the wsdl, it can be retrieved at:”);
 
        insertText.Append(“<P><PRE><A HREF=\”"+baseaddress+“?wsdl&amp;flat\”>”+baseaddress+“?wsdl&amp;flat</A></PRE></P></P>”);
 
        string newMessage=body.Insert(foundat+stringToFind.Length, insertText.ToString());
 
        //create a memory stream and shove our new message into it
        MemoryStream memStream=new MemoryStream();
        XmlWriter meWrite=XmlWriter.Create(memStream);
        meWrite.WriteRaw(newMessage);
        meWrite.Flush();
        memStream.Position=0;
 
        //create a reader for the stream and use it to create the message
        XmlReader meRead=XmlReader.Create(memStream);
        replyMessage=System.ServiceModel.Channels.Message.CreateMessage(reply.Version, reply.Headers.Action, meRead);
 
        //copy everything else from the original message
        replyMessage.Headers.CopyHeadersFrom(reply.Headers);
        replyMessage.Properties.CopyProperties(reply.Properties);
        return replyMessage;
      }
      else 
     {
        return reply;
      }
    }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

That’s it in a nutshell. This code is without warranty, either expressed or implied. Hopefully it’ll save someone a little bit of pain.

Also, sorry about the code formatting. WordPress won’t let me do a lot about it without upgrading, so it looks like I’ll be moving to my own domain soon. Any recommendations for a .NET blogging engine are greatly appreciated.

I’ve been working with WCF a fair bit lately, and frankly it’s mostly been a breeze. I did run into two head scratchers that I thought I would document since I had a hard time finding a straight answer on the intertube.

The first one has to do with WCF and Microsoft Enterprise Library. If you don’t know what Microsoft Enterprise Library is, it’s basically a collection of code that everybody keeps writing over and over again. Stuff like logging, error handling and database connectivity. If you needed that explanation, then you should quit reading this and go download it. Seriously, this blog will still be here when you get back.

Got it installed? Skimmed the documentation? Good, now you can stopwriting all that code that everybody gets almost right and go back to doing useful work.

So, using the logging block with WCF is fairly straight forward. Just make sure whatever process your service is running under has access to the db, and to the stored procs. I know, I’m an idiot. Of course it will need access to the stored procs. No, giving it access to the tables won’t magically give that login access to the stored procs. I know it’s stupid, but when I was trying to find out why my logging wasn’t working I saw the same question over and over again, and never saw an answer.

Just so you don’t have to look it up, if you ran the standard sql script to add the table and stored procs, then the stored procs are named: AddCategory, ClearLogs, InsertCategoryLog and WriteLog.

The other big, bone headed gotcha I ran into was during integration testing. For some reason, none of the changes I made to the service to fix things seemed to take effect. I restarted the service, I restarted the server, I restarted the computer. I stepped through the tests, I attached a debugger to the service and could never get it to hit a break point. I stopped the damned web service, and still my tests kept coming back with the same results. After reconfiguring the web service reference and making sure it was pointing at localhost (where I was testing) I still couldn’t get a breakpoint to hit, or see any of my changes taking effect in the code.

Yeah, you’ve already figured it out. The web service reference was pointing to the wrong box. Well, to be more accurate, the settings for the web service reference in the app.config for the tests were pointing to the wrong box. Even though the configuration for the web service reference said it was pointing to localhost, a quick look in the app.config showed that it was pointing to the box of another team member who had also been working on this web service.

If you point the web service reference to localhost, visual studio is “smart” and goes behind your back and inserts the actual machine name in there. I changed all the references in app.config to localhost as well, and suddenly all the changes I had made started working. Amazing! It only took me two hours of beating my head against the desk to figure that out.

Hopefully, the spiders find this entry and keep you from having to do the same.

If you liked this, check my other posts at my new site http://www.steverb.com.

I got handed a nicely interesting project and given mostly free reign to use whatever I wanted to for it. Of course, the first thing I did was look at .Net 3.5 and ask myself what seemed cool that I haven’t had a chance to play with yet. LINQ was the obvious first choice.

I decided to try using LINQ to SQL in the data access layer. It seemed like an obvious thing to do, but a funny thing happened on the way to finishing up the app. It looked more and more like LINQ to SQL shouldn’t be in the DAL, but that it should replace it.

So far so good.  And I have to say, after using LINQ for a week I don’t ever want to go back to writing T-SQL again. The syntax is little yoda-ish at first, but after a short warming up period I find myself using it everywhere, not just for SQL.

I’m still not sure how well LINQ to SQL will hold up as the app ages and expands, but my first gut is that it shouldn’t fare any worse than with a traditional DAL. 

BTW, I was joking about the other TLAs. Three is enough.

So, I’ve left Edfinancial and am at Bechtel now.

I’d forgotten how annoying changing jobs can be. New paperwork, gotta move all the crap you’ve accumulated, can’t remember where the damned bathroom is.

Life is good!