Oh my. Has it really been *THAT* long? Obviously, yes. Some folks have asked me if I stopped blogging. No, I did not. I just took a way long break from it (which will likely resume the instant I hit the Post button), as I was busy working on other things such as How do I videos for NAV (you can look them up on MSDN and PartnerSource), working on the digital learning for NAV (which is partly available on PartnerSource already, and partly will shortly be), preparing and delivering presentations and some other things.
A month ago, I’ve delivered a session at Directions EMEA 2013 in Vienna where I’ve talked about the .NET ineteroperability and Web services tips & tricks, and presented a series of demos (13 of official ones), and then promised to make them available on my blog. The problem was – I honestly intended to make them available, I just didn’t set a deadline. I work best when I have the deadline, but even then it’s not a granted thing.
This time, in Nashville, I was a bit smarter – I’ve actually set myself a pretty demanding deadline, promising my Directions US 2013 audience to actually post this on my blog this very afternoon. So here I am, sitting at the Paisano’s pizzaria and vino terrace, enjoying the kitschy extravagance of a view of a monstrosity of a place called the Gaylord Opryland Hotel & Resort, and writing this to keep up with my commitment.
So, here’s the deal. I’ve attached all the files including all the demos, tips, tricks and everything else I showed. All is inside. And here’s the link where you can grab all this. Click here.
To make this all work, you’ll also need to publish the following web services:
So far, so good.
At both my presentations, Vienna and Nashville, Tip #7 failed. Demo gods, or something. Both demos worked when I got back to my room – obviously, a service tier restart was needed, as some old objects remained cached and it used an old version instead of the final deployed version. Anyway, I’ve fixed Tip #7 and it now works. If it doesn’t, yell, scream, comment, or do whatever you normally do when things you expert to work don’t do so.
If you’ve been to my presentation, then you probably know the context. For all others, I’d provide some context here. I’d like to upload the presentation slide deck here, but I’m afraid it might violate the Directions conference policies.
Tip #1: Global Assembly Cache deployment
Open the Visual Studio solution and check the Post Build events in the properties for the Directions Demo project. There are these three lines of code:
call “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat”
gacutil /i “$(TargetPath)” /f
gacutil /l “$(ProjectName)”
As I’ve shown during the demo, the first one may differ from machine to machine, and you can grab it from target property of the Developer Command Prompt shortcut deployed by Visual Studio.
This tip makes your life a lot easier when developing and testing. And it forces you to make your solution safer to use by your end-users.
Demo #2: Weak typing is bad
It’s just bad, you don’t want me to elaborate on this. This demo shows one probably inadvertent aspect of the design decision by Microsoft to wrap all .NET interoperability into a higher-level class.
This demo shows how NAV actually boxes stuff into generics, which are all instantiated from the System.Object class. Kind of violates the first principle of generics. I don’t know what that principle is, because I’ve just made it up, but if it existed it would go something like this: generics should be instantiated from actual types, duh!
I’ve already ranted about generics not being properly supported here, and most of the first part of the session was explaining how to use generics in the proper way in C/AL.
Demo #2: A nice idea that fails because of “generics” based on System.Object
The nice idea is this: have a nice .NET class that allows you to foreach through a collection in C/AL while at the same time allowing for generic strongly-typed use.
So, in the VIsual Studio, the DirectionsDemo project contains the ForEach.cs class that is itself generic and allows you to iterate through a generic collection from C/AL and accessing the content of the collection in its actual type, not as System.Object.
The idea is nice, because it would have you write code such as this:
WHILE ForEachHelper.ForEach(List,i) DO
Where i is integer, and List is List<int> (in C/AL, though).
However, it fails. It does so because the generic is of System.Object type, and it fails at unboxing for some reason or other. Maybe a bug, maybe a glitch, maybe a prank, but whatever it is, even if it worked, it would still use boxing/unboxing anti-pattern, and would be just as bad as it theoretically is. So good thing it does not even work.
The fact that the demo errors at the end is expected. The demo is here to demonstrate that this does not work because it should not work.
Tip #2: Always create strongly-typed generics
Even though NAV makes it complicated for you, you can still instantiate generics from actual types and overcome the limitation imposed by C/SIDE environment. For that I’ve provided the Generic Management codeunit. It has two functions and may contain as many functions as many generic types you can reasonably expect your classes to use. I’ve added only two, because one is most common, two is occasional, and generics beyond two types should be taken out and shot anyway. If you ever need three or more, it would be a half-minute exercise to add those functions.
The Tip 2 codeunit shows how to instantiate a strongly-typed generic in one line of code, courtesy of the Generic Management codeunit:
Demo #3: A nice idea that works because of strongly-typed generics
Now we are talking business. This demo shows how to have a strongly-typed foreach loop in C/AL:
WHILE ForEachHelper.ForEach(List,i) DO
Not as elegant as the foreach C#-style, but accomplishes the job, and is strongly typed. This i in the code above is integer, but it can be anything else, and it will always be an actual type that you need, never System.Object.
Pretty cool if you ask me, but I admit that I am biased.
Demo #4: Tight coupling leads to unmanageable code
This demo opens up another theme of my presentation: tight coupling. NAV is full of it. Everything in NAV is as tightly coupled as it gets. And this is bad, too. And you also don’t want to get me started on this, either.
Anyway, the Demo 4 codeunit shows a simple tightly-coupled scenario: a codeunit that logs into the Windows Event Log.
So, when you run it, it puts a nice message into your event log. That’s all it does, and it’s not overly cool by itself. The point of this demo is not to show how to log into Event Log from C/AL but to show why tight coupling is bad.
When I show this demo I always introduce a what if scenario. Tight coupling falls apart at what-ifs, and that’s why I do it. I want it to fall apart.
The what if goes more or less like this: what if you want to replace your event log logging with file system logging, database logging, or some other third-party logging system? How much code is acceptable to write to replace a dependency?
The correct answer is none. No code necessary.
Tip #3: Inversion of Control through .NET interoperability
Inversion of Control is an extremely sexy pattern with many different implementation, all of which are nothing but variations over Dependency Injection pattern. Both extremely useful, versatile, and helpful as hell when it comes to cutting tight coupling to ribbons.
Needless to say – C/AL can’t do either. It’s not an object-oriented environment and that’s why it can’t do IoC or DI patterns (or most of other patterns the civilized world has enjoyed since at least ten years ago or longer).
But, you guess already, .NET interoperability makes this possible.
So, tip #3 shows how. Populate the Dependency Setup table with the types, assembly names and class names (I intentionally only support GAC at this stage) and run the Tip #3 codeunit to see the Inversion of Control C/AL-style in action.
I have a dream of doing a full-scale Inversion of Control framework around this, much inspired by the Structure Map opensource project, but if, when, and how much of it I’ll do I’ll let the history show. It’s kind of in direct correlation with my spare time, which is almost non-existent, so don’t hope for much. Feel free to do it yourself if you want, I won’t mind.
Demo #5: Workdate defaults to system date
This is the first demo of the Web services part, and here I give tips how to overcome some limitations of web services, namely: work date, statelessness, and flow filters. And some more tips as I go.
This demo shows that no matter what you do, the work date of a web services session always defaults to the system date.
Tip #4: Cross-call state preservation through a single-instance class
Here I present the tip that makes some people’s toenails curl up – and rightfully so – but only because they jump ahead of themselves.
This is the first step in showing how single-instance classes can enable you to store and then use the cross-call state in web services. I also blogged about it, and a commenter pointed out why this is bad, and I respectfully disagreed because while this by itself is risky (explosions are also risky, and every day in your car you make good use of hundreds of thousands of those to make your car take you from here to there), you can properly harness this powerful feature to make very useful stuff by isolating sessions.
When I explain what I do here, I run Demo #5 to show that the work date is now preserved and properly applied to consecutive calls.
And I also introduce the problem of unsafe state because it is not per-session.
Tip #5: Session isolation
And here I immediately address this issue. I introduce a new class and a call sequence of start session – do work – end session, which all together achieve exactly what the whiners whine about: isolates sessions and session state between calls.
And then I immediately introduce another problem: how to make page web service calls be session aware. This is a big problem, because page codeunits have function which have their predefined signature and you can’t change it. Or, can’t you?
Tip #6: Adding parameters to page Web service methods
Here I address this specific pain point. So I show how to add parameters to page web service methods. Nice and simple and safe.
Tip #7: Passing classes to Web service calls
Here I show how to serialize and deserialize objects when and then pass them to web service calls. I’ve also blogged about this earlier. It’s a useful tip.
Here I give an example of how to pass flow filters on to a page web service and then have them applied, all through the shared state.
Tip #8: Calling NAV Web services from C/AL
This is a concept I first showcased last year at TechDays 2012 in Antwerp and got some pretty nice response. The primary point here is not to show how to call NAV web services, but to show the power of .NET Interoperability and what it can do for you. This is probably one of the best examples of it’s power, flexibility and usefulness.
Today I got a question, with unhidden sarcasm, why would anybody want to do anything like this. Well, the question misses my point by 180 degrees. You tell me! I’m giving it as an example, and you go and see if you can put it to use. Hundreds of people already did (judging from the number of Mibuso downloads and the pristine rating of clean 5 stars it has).
Well, that was it. I hope you liked the presentation, and if so – please leave a comment here. Also – if you didn’t, please leave the comment here.
I hope to catch some time to elaborate more on the concepts I presented today in Nashville and a month ago in Vienna, but if I don’t, I hope to see you in Antwerp at TechDays 2013 at any of my three sessions. Until then, see you in the cloud! In and on!