Jelle Druyts .NET Consultant
Just another ignorant weirdo from Antwerp, Belgium trying to make sense out of it all
Yes! I just got my first Indigo sample up and running!
I started off with a clean Windows XP SP2 installation, and I just installed the March CTP of Avalon/Indigo/WinFX (build 2.0.50110) without anything else - no Visual Studio .NET, no IIS, no nothing - so it's definitely back to basics here while I'm downloading the February CTP of Visual Studio .NET 2005... On the other hand, it's quite a lot of fun to just try and get anything working without any major productivity booster such as Visual Studio, IntelliSense or any form of actual documentation installed. For now, I'll consider notepad and ildasm.exe my best friends in the Indigo space. Long time no see, welcome back guys
The first thing to try was to get any of the prepackaged samples working. I unzipped the AllSamples file in the "C:\Program Files\Microsoft SDKs\WinFX\samples" directory and seeing I had no Visual Studio installed I just tried to run MSBuild on the solution files. Although I think this should work, it was complaining to me about not being able to copy some files or something. Weird.
I then decided to take Clemens Vasters' Indigo Hello World sample and see what I could make of that. I just copied it into a new file and ran the compiler on it:
csc /r:"C:\Program Files\Microsoft Indigo Preview\System.ServiceModel.dll" IndigoHelloWorld.cs
Unfortunately, I got an error straight away: the BasicProfileHttpBinding class wasn't found. So here's ildasm to the rescue already. As it turns out, they recently must have renamed the class to BasicProfileBinding, so a simple change to the sourcefile fixes the problem and we're all set and compiled. Step 1 complete! The server code is now just:
BasicProfileHttpBinding
BasicProfileBinding
using System;using System.ServiceModel;namespace IndiHello{ [ServiceContract] public class Hello { [OperationContract] public string SayHello(string name) { return "Hello " + name; } } class Program { static void Main(string[] args) { ServiceHost<Hello> host = new ServiceHost<Hello>(new Uri("http://localhost/hello")); host.AddEndpoint(typeof(Hello), new BasicProfileBinding(), "ep"); host.Open(); Console.WriteLine("Press ENTER to quit"); Console.ReadLine(); host.Close(); } }}
So with my newborn Indigo service now up and running on my machine, I figured I should be able to make this do something, right? So because I couldn't really think of anything else, I just took the ASMX approach, which is to surf to the endpoint (http://localhost/hello/ep) and observe the magic: Indigo provides a very similar model to ASMX with an informative html page if you access the endpoint via HTTP/GET and is so kind as to give a hint what you could do next. Not only does it tell you how to generate a client proxy for the service, but it also gives some basic info about how to use the proxy afterwards.
So off I am building a client proxy using svcutil.exe (think wsdl.exe for Indigo) on the wsdl:
"C:\Program Files\Microsoft Indigo Preview\svcutil.exe" http://localhost/hello/ep?wsdl
This just creates a proxy class in a file named tempuri.org.cs (since I haven't changed the default namespace, it just takes the tempuri.org namespace as the base name) with the contract interface and some kind of channel interface (I'm not sure what that does yet but I'll find out sooner or later):
[System.ServiceModel.ServiceContractAttribute()]public interface Hello{ [System.ServiceModel.OperationContractAttribute(Action=http://tempuri.org/Hello/SayHello, ReplyAction="http://tempuri.org/Hello/SayHelloResponse")] [return: System.ServiceModel.MessageBodyAttribute(Name="SayHelloResult", Namespace="http://tempuri.org/")] string SayHello([System.ServiceModel.MessageBodyAttribute(Namespace="http://tempuri.org/")] string name);}public interface HelloChannel : Hello, System.ServiceModel.IProxyChannel{}public partial class HelloProxy : System.ServiceModel.ProxyBase<Hello>, Hello{ public HelloProxy() { } public HelloProxy(string configurationName) : base(configurationName) { } public HelloProxy(System.ServiceModel.Binding binding) : base(binding) { } public HelloProxy(System.ServiceModel.EndpointAddress address, System.ServiceModel.Binding binding) : base(address, binding) { } public string SayHello(string name) { return base.InnerProxy.SayHello(name); }}
Looks good. Next up: adding a test driver. Simple enough, the service's informative html page shows me how to create a simple console app that uses the proxy:
HelloProxy proxy = new HelloProxy();string result = proxy.Hello("some data");System.Console.WriteLine("The Hello service returned '" + result + "'");proxy.Close();
So I just whipped that into the generated proxy class file, and tried to compile the bunch:
csc /out:Client.exe /r:"C:\Program Files\Microsoft Indigo Preview\System.ServiceModel.dll" tempuri.org.cs
Too bad, there seems to be a little bug in the way the service generates the html page (I bet you didn't spot that just now, neither did I), since the service operation isn't called "Hello", it's "SayHello". So a small change here as well, run the compiler again - which seems to give me an actual executable this time - and we're ready to try and run the client:
C:\IndigoTest>Client.exeUnhandled Exception: System.InvalidOperationException: Could not find Channel element for contract Hello, Client, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null at System.ServiceModel.Design.ConfigLoader.LoadChannelDescription(ChannelDescription channelDescription, ContractDescription contract, String configurationName, EndpointAddress address) at System.ServiceModel.Design.ChannelLoader..ctor(Type contractType, String configurationName, EndpointAddress address) at System.ServiceModel.ChannelFactory`1..ctor(String configurationName) at System.ServiceModel.ProxyBase`1..ctor() at Test.Main(String[] args)
Whoops, that's not good. Here's that Channel thing again. But then again, I didn't really provide an actual uri where the client could locate the service. So I decide to use one of the generated HelloProxy constructors that seems to make sense: the one with an EndpointAddress and Binding.
A quick look in Ildasm at the EndpointAddress class reveals a constructor that takes a uri string, so I'll just take that and then paste in the same binding as I used on the server side:
HelloProxy proxy = new HelloProxy( new System.ServiceModel.EndpointAddress( "http://localhost/hello/ep" ), new System.ServiceModel.BasicProfileBinding() );string result = proxy.SayHello("some data");System.Console.WriteLine("The Hello service returned '" + result + "'");proxy.Close();
Throwing the compiler at the code creates me a new executable, so I run that and voila:
C:\IndigoTest>Client.exeThe Hello service returned 'Hello some data'
Wicked! My first Indigo client is talking to my first Indigo service over a basic profile HTTP binding, without even having IIS installed. Ain't that something...
Here are the files if you want to try it out yourself: IndigoHelloWorld.cs (service), tempuri.org.cs (client)
In retrospect, I could also have used the Indigo CTP SDK docs Don Box pointed at, but, well, it just didn't come to my mind. I was so happy to see ildasm again, I guess I didn't want to trade our new-found relationship for some long-distance relationship with a remote webserver
Now that I have this basic stuff out of the way, I can start digging in the articles, posts and documentation for Indigo to get a better hands-on view of the API.