28 April 2010

Lambda Expressions - The Shuttle _Tidirium_ of .NET

Actually, I just said that 'cause I wanted to get my Star Wars geek on. Today I ran across this article while trying to wrap my head around lambda expressions. I was trying to wrap my head around lambda expressions because they're cool (that is, useful and geeky). So, to sum up the artical (without using his example) let's look at some code I just modified to use Lambdas. Old Code:

User u = (from u1 in Users where u1.UserName == userName select u1).First(); CurrentTicket.Reasign(u);

New Code:

CurrentTicket.Reassign(Users.ToList(). Where(u => u.UserName == userName).First());

As the article points out, these are really saying the same thing. The Lambda Expression is just more concise.

22 April 2010

Remittance Headaches

For those of you who've worked with X12 835 Remittance documents, you may know my pain. Some time ago at work, I was tasked with finding a more efficient way to handle remittance advice documents for our clients. Since I like BizTalk, I figured this would be a good time to prove its abilities, and I got to work. In short order, I was able to write the remits to a set of tables. With one, teensy problem. BizTalk is (necessarily) unaware of Database relationships. Using the WCF LOB Adapters for BizTalk worked for blowing the information into the DB very quickly, but I couldn't find a way to maintain referential integrity among the tables. Eventually I decided on an "organic key" made up progressively larger strings as one walks down the tables. So, for instance, a Claim Group (LX, TS3, and TS2 segments) would refer back the check on which they're found by using a string made up of the ST02 segment and the Check number. A Claim Payment record would refer back to the claim group by adding onto it the LX identifier and so forth. This works very well, actually, and if I know exactly the check number I want, I can find it very quickly. However, this doesn't actually take care of all of our problems. Those pesky end users want -gasp - to be able to search for remits by Patient! or Provider! What are they thinking?!?! So, I have to fix my database. But how? I mean, I still haven't found a way for BizTalk to keep that referential integrity for me, and having BizTalk pass the 835 to a .NET application kind of defeats the purpose, so what to do? Barring some divine (or reader) intervention, I've settled on this: I'm writing a .NET application which will bundle up remits at the batch level (that is, i have batch object which contains my batch data as well as a list of check objects, which, in turn, hold my check data and a list of claim group objects, and so forth). Once that is done, I'll write the records into a new database (probably nightly?) in a fashion which can be aware of record identities and referential integrity. Please, if anyone has a better option, email me or leave it in the comments- it would be a God-send.

20 April 2010

XML: Nillable="True" vs MinOccurs="0"

This came up at work today, as a coworker was strugling with a WSDL for an outside vendor. I only knew it because BizTalk runs into exactly this kind of error occassionally. The situation is this: A WSDL is defined with several elements. Let's use this for an example:

What you see here is a bunch of elements in an which my coworker is trying to show as null by not including. That is, when, for instance, "address" is null, it simply will not exist in the XML document. Here's how the same code looks as our vendor expects it.

Now, leaving aside the question of why the only way to pass data to the web method is allowed to be null, we can see that the vendor's wsdl expects the nodes to exist. Therefore, instead of simply leaving out "address" the XML document should contain a node like this: <> It makes sense when you think about it in terms of code as well. How many times in C# do we pass something like "foo = new foo(new bar(), null)?" Is there any question that this is different from "foo = new foo(new bar())"? Not really. (At least, not until C# 2zillion when Microsoft decides that any parameter which can accept a NULL is automatically an optional parameter.) I did manage to help steer the coworker in the right direction, and provided him (as I am you) a pretty good synopsis on this whole thing from IBM's website. Link here. (http://www.ibm.com/developerworks/xml/library/ws-tip-null.html) So, in summary, pay attention to your WSDL and Schemas. Nillable is not the same as MinOccurs="0".

07 April 2010

MS .Toolbox

I've been working my way (slowly) through Microsofts new http://www.microsoft.com/design/toolbox/ site. For anyone who wants to know more about UI design (which should be every Mid-tier and back-end developer everywhere), it's a really good resource. But it brings me to something I see to much in the developer world: the idea that if the "functionality" works, UI doesn't matter. "Just give 'em a button" seems to be the mantra all too often. My take on it, however, is this: If the User can't make it do what it's supposed to, or if the user decides the old way was easier than your new way, your program doesn't work. The UI is how the users interact with your functionality; if it's not good, then it's bad. There is no middle ground. With WPF and Silverlight, this consideration has become much easier to handle. Simply implement INotifyPropertyChanged on your Business Layer objects, and then use MVVM to set up the UI. However, for people not using WPF or Silverlight, some consideration has to be made at design time for how the UI will look. If you'll be populating a ListBox control, you probably need a collection of some kind, for instance. This is a place where I've fallen down in the past, and I plan not to do so any more. You should make a similar pledge.

06 April 2010

WCF WTF: Update

I attempted the solution I discovered yesterday when I got into work this morning, and it wasn't working either. I did a little more research and discovered that, for WCF to work with Streams, you really need to pass them via a BasicHttpBinding. As I'm not that great at WCF yet, I've been using the default WSHttpBinding that Visual Studio creates when you add a Service Reference. I didn't really want to spend too much more time working on this- we were already getting to the point of "diminishing returns." So I decided to take stock of where I was and move forward. The OperationContract was defined as a Stream output with a Stream input. However, since I know that a Stream is really just an Array of Bytes, I decided on an alternative approach. I created a new OperationContract (called DecryptBytes) which accepts (and returns) an array of bytes. Then, in my .svc.cs file, I created the new method which really just changes the bytes into a MemoryStream, and then hands the memory stream to my original method: public byte[] DecryptBytes(byte[] inStream) { MemoryStream _iBytes = new MemoryStream(inStream); MemoryStream _oBytes = this.Decrypt((Stream)_iBytes) as MemoryStream; return _oBytes.ToArray(); } So, for 5 lines of code (including the Attribute Tag in the Service Contract, and the Method declarations) I was able to correct the issue. I feel a little silly that it was that hard to figure out, but I'll chalk it up as "lesson learned" and archive it here in case I need it again...

05 April 2010

WCF WTF

So, I have a WCF Service I created to handle PGP encryption/decryption using the BouncyCastle .dll. We wanted just the one, internal, service so that everyone who needs to be able to decrypt data can without having to ask the developers all the time. This service receives and passes streams of data. Unfortunately, I did not realize that this doesn't actually work real well in WCF. Unless I can find a way around it, WCF changes my nice FileStream or even just a base Stream and hides it in a System.ComponentModel.Dispatcher.StreamFormatter (from memory, so that namespace may be a little off). Which is not seekable. My service requires a seekable stream. I'm sure you see the problem. I didn't discover this little gem until about time to go home today. So, tomorrow I'll write a nice little wrapper around the stream that gets passed into the service so I can treat it as a normal stream. I'll post the code here when that's done, so I'll have it someplace relatively safe.