Blog Home  Home Feed your aggregator (RSS 2.0)  
.Net Jonesie - July, 2009
A simple programmers blog
 
# Thursday, July 23, 2009

After posting about using TCP with the .Net Service Bus and making it look sooooo simple, I’ve lost most of today trying to get the fracking thing working!  I doesn’t matter what I do in the config, the service host keeps prompting me for a Card (from CardSpace) even though I had everything setup for UserNamePassword creds.

After much stuffing around I noticed that my solution had the wrong version of the service bus DLL (0.15.0.0 – March CTP I think).  This was my bad – I had copied the DLL to a solution folder.  So I grabbed the '”new” version (0.16.7.0) from the July CTP Assemblies folder and tried that.

Same result!  Arg!

Looking in the GAC I could see it had version 0.16.0.0.  What the ?!!

Time for a reinstall me think.

Download from MS.  Install. Chug chug….

Ok, now I have version 0.16.71.1.  Right. Fine.

But the GAC still has 0.16.0.0 and my app still is broked.  Lord - give me strength!

I re-added the project assembly reference to my local non gac copy and set copy local and now it all works again.

I can’t delete the old version from the GAC without uninstalling the SDK completely so it will have to stay there.

Weird!  The Joy of CTP.

Thursday, July 23, 2009 2:54:08 PM (New Zealand Standard Time, UTC+12:00)  #    Comments [2]   Azure  | 
# Wednesday, July 22, 2009

Checkout this cool video if you want a 4 minute elevator pitch (ok, so a slow elevator).

http://blog.smarx.com/posts/what-is-windows-azure-a-hand-drawn-video

Wednesday, July 22, 2009 11:27:25 AM (New Zealand Standard Time, UTC+12:00)  #    Comments [0]    | 

We recently implemented the .Net Service bus to expose some in-house WCF services to the world wide world. It may be useful for me and others if I describe how to do this :) This setup allows you to switch between tcp and http relay binding with configuration.

The Host

For the in-house systems you need to create a host – you cant use IIS as the service bus requires a connection to be initiated by both ends of the communication.  We created a Windows Service application that also runs as a console app.  This is much simpler when developing and debugging.  To create this service:

1) create a new windows service using the standard VS template and add a reference to Microsoft.ServiceBus (in addition to your service and data contracts which I hope are in separate assemblies!)

2) change the Application Output Type to Console Applications.

3) add some code to Program.cs to flick to console mode:

if (args.Length > 0 && args[0].ToLower() == "/console")
{
  myService.RunConsole(args);
}
else
{
  ServiceBase.Run(ServicesToRun);
}

4) in your service code add the following method:

internal void RunConsole(string[] args)
{
  OnStart(args);
  Console.WriteLine("My ServiceHost is running... Press Enter to stop the service");
  Console.ReadLine();
  OnStop();
}

Now for the service bus stuff.

5) in the service class, add a member for the service host:

ServiceHost _host = null;

6) in the OnStart method of your service add the following :

// create a behavior for the service bus – it need creds of some type
TransportClientEndpointBehavior behavior = new TransportClientEndpointBehavior();
behavior.CredentialType = TransportClientCredentialType.UserNamePassword;
behavior.Credentials.UserName.UserName = Properties.Settings.Default.ServiceBusSolutionName;
behavior.Credentials.UserName.Password = Properties.Settings.Default.ServiceBusPassword;

// create an address for the service bus.  config allows a switch between tcp and http
Uri address;

if(Properties.Settings.Default.ServiceBusBinding == "nettcp")
{

  address = ServiceBusEnvironment.CreateServiceUri("sb", Properties.Settings.Default.ServiceBusSolutionName, Properties.Settings.Default.ServiceBusServiceName);
}
else
  if(Properties.Settings.Default.ServiceBusBinding == "basichttp")
  {
    address = ServiceBusEnvironment.CreateServiceUri("http", Properties.Settings.Default.ServiceBusSolutionName, Properties.Settings.Default.ServiceBusServiceName);
  }
  else
    throw new ArgumentException("Invalid binding for Service Bus");

// create the host
_host = new ServiceHost(typeof(MyService), address);

// update all the end points with the new behavior – you may need more than one – or not – up to you
foreach (ServiceEndpoint endpoint in _host.Description.Endpoints)
{
    endpoint.Behaviors.Add(behavior);
}

// open the portal to another dimension – a dimension of sight and sound
_host.Open();

Now for some config.  For me this was the hardest part.  Hard coding WCF config is much simpler!

7) create some service model bindings for netTcpRelayBinding & basicHttpRelayBinding

<bindings>
  <netTcpRelayBinding>
    <binding name="default" />
  </netTcpRelayBinding>
  <basicHttpRelayBinding>
    <binding name="default">
      <security mode="None" />
    </binding>
  </basicHttpRelayBinding>
</bindings>

8) add an endpoint for your service:

<endpoint name="MyServiceEndpoint"
          address=""
          binding="netTcpRelayBinding"
          contract="MyApp.ServiceContracts.IMyService"
          bindingConfiguration="default" />

 

9) if you want to use  basic http then add this instead:

<endpoint name="MyServiceEndpoint"
                address=
http://mysolution.servicebus.windows.net/MyService
                binding="basicHttpRelayBinding"
                contract="MyApp.ServiceContracts.IMyService"
                bindingConfiguration="default" />

And that’s about it for the service host.  If you need to have metadata support (WSDL) then that’s a whole other story that I will try to blog about seperately.

The Client

Azure worker roles do not have a web or app .config you can use for WCF configuration settings.  Web roles do have a web.config but this can only be changed by a redeploy of package so it’s not the best idea to put anything but service configuration in there.  In my case, I needed to access the in-house services from both the web and worker roles so I created a class lib project with a single helper class.

1) create a Windows Class Library and add references for Microsoft.ServiceBus plus your service and data contracts.

2) Create a static class with a single static method – call it what you like but something like GetClientChannel() will do.  Add the following code:

IMyChannel channel;  // this is a simple combo interface of IChannel and IMyService

Uri address;


// create the behavior for SB creds
TransportClientEndpointBehavior behavior = new TransportClientEndpointBehavior();
behavior.CredentialType = TransportClientCredentialType.UserNamePassword;

// get the creds from the cloud config
behavior.Credentials.UserName.UserName = RoleManager.GetConfigurationSetting("ServiceBusSolutionName");
behavior.Credentials.UserName.Password = RoleManager.GetConfigurationSetting("ServiceBusPassword");

// create a channel factory

ChannelFactory<IMyChannel> channelFactory = new ChannelFactory<IMyChannel>();

// create the binding – config allows us to select http or tcp

if (RoleManager.GetConfigurationSetting("ServiceBusBinding").ToLower() == "basichttp")
{
  channelFactory.Endpoint.Binding = new BasicHttpRelayBinding(EndToEndBasicHttpSecurityMode.None, RelayClientAuthenticationType.None);
  address = ServiceBusEnvironment.CreateServiceUri("http", RoleManager.GetConfigurationSetting("ServiceBusSolutionName"), RoleManager.GetConfigurationSetting("ServiceBusServiceName"));
}
else if (RoleManager.GetConfigurationSetting("ServiceBusBinding").ToLower() == "nettcp")
{
  channelFactory.Endpoint.Binding = new NetTcpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.None);
  address = ServiceBusEnvironment.CreateServiceUri("sb", RoleManager.GetConfigurationSetting("ServiceBusSolutionName"), RoleManager.GetConfigurationSetting("ServiceBusServiceName"));
}
else
{
  throw new ArgumentException("Invalid service bus binding configuration option: " + RoleManager.GetConfigurationSetting("ServiceBusBinding"));
}

// update the factory for A B & C

channelFactory.Endpoint.Address = new EndpointAddress(address);
channelFactory.Endpoint.Behaviors.Add(behavior);

channelFactory.Endpoint.Contract.ContractType = typeof(ICRMChannel);

channel = channelFactory.CreateChannel(new EndpointAddress(address));
channel.Open();

return channel;

 

Tada!  All done.  Provided I haven’t introduced any bugs then this should give you a connection to you in-house services, by passing any firewall crap that those pesky IT people seem to insist on.

Enjoy :)

Wednesday, July 22, 2009 9:42:56 AM (New Zealand Standard Time, UTC+12:00)  #    Comments [0]    | 
# Friday, July 17, 2009

So far, so good. Twitter has not taken over my life.  I’ve tweeted and chirped a little this week and have found a few colleagues to follow and vice versa. It’s also been a little useful and has helped me solve a couple of problems quicker than the usual methods (forums and web searches).

It’s interesting to see Twitter going main stream.  When one of our sales guys asked which twitter client to use I thought ‘oh well, twitter is surely dead now!’ but then I read that CRM 5 will have a Twitter interface and I’m guessing (truly – no insider info anymore) we will see similar functionality in Office 2010. Google Wave has this too.

I’m not tempted to create the next killer twitter client yet.  Tweetdeck works well enough for me at this stage but I can see that I will soon run out of screen real estate.

Best thing about twitter?  It’s go me blogging again :)

Friday, July 17, 2009 3:42:30 PM (New Zealand Standard Time, UTC+12:00)  #    Comments [0]   General  | 

PowerShell takes a while to learn – especially if you have an aversion to manuals as I do – I prefer to learn on the fly.  So, when I wanted to convert a variable containing a comma delimited string into an array I was lost.  After a bit of playing and ‘binging’  I found that it was actually very very easy:

# start with a string
$roles = "db_owner"

# now it’s an array of 1 element
$roles = ,$roles

Sweet!

Friday, July 17, 2009 11:33:27 AM (New Zealand Standard Time, UTC+12:00)  #    Comments [1]   General | PowerShell  | 
# Wednesday, July 15, 2009

I searched for a while to find an easy way to run a command from a PowerShell script and wait for it to finish.  Most of the example I found use Invoke-Expression but this wont wait.  In the end I resorted to the tried and true .Net Fx:

# run a command line and wait for it to be done   
function RunAndWait([string] $command, [string] $arguments)
    {
    $proc = New-Object     System.Diagnostics.Process
    $proc.StartInfo.FileName = $command
    $proc.StartInfo.Arguments = $arguments
    $proc.Start()
    $proc.WaitForExit()
    }

You need to seperate the command (aka FileName) from any arguments, but otherwise this seems to work nicely.

However, PowerGui doesn’t always wait when you are debugging so be careful if you are stepping through your script and expect it to stop in logical places.

Wednesday, July 15, 2009 10:39:11 AM (New Zealand Standard Time, UTC+12:00)  #    Comments [0]   General | PowerShell  | 
# Thursday, July 09, 2009

The July CTP of the .Net Services SDK only support 2008, Vista or Windows 7.  This is true of the previous CTP’s but it was not enforced until the latest release.  Luckily for me there is a simple workaround.

On a machine that does have the July CTP installed, take a look in C:\Program Files\Microsoft .NET Services SDK (July 2009 CTP)\Assemblies.  There is a tool in here called RelayConfigurationInstaller.exe.  Copy this and the Microsoft.ServiceBus.dll to your target machine and run the exe with /i.  Then copy the DLL to the GAC and your done.

It appears as though RelayConfigurationInstaller simply adds the required machine.config settings on the target machine.  You could also do this manually if required.

Of course, this is not officially supported but MSFT are listening.  If you really need legacy OS support for this then post a message to the forums and ask for it before it’s too late.

Full Credit to Clemens Vasters for this tip.

Thursday, July 09, 2009 8:49:59 AM (New Zealand Standard Time, UTC+12:00)  #    Comments [0]    | 
# Wednesday, July 08, 2009

Having a blog is like having a nagging wife – not blogging makes me feel guilty.  The thing is, I just don’t have the time to to write the type of blog posts I like to write – long and accurate.  Not that I’m ever very accurate, but well …

Anyways, I’ve been ranting about how stupid twitter is and what a complete time waster it is without actually trying it.  Then it occurred to me that twitter might actually be a useful alternative to long exhaustive blog posts.

So, I’ve signed up again and am tweeting a little about very development focused things.  You wont catch me tweeting about the weather or Michael Jackson etc.  Currently I’m into Azure dev so I’m finding lots of little things to chirp about.  I haven’t found a lot of tweets to follow yet apart from the obvious candidates – scottgu etc – but I did get my first reply today when I sent a message to a Microsoft tweet.  Very sweet!

Follow me if you love me :)  jonesienz

Wednesday, July 08, 2009 4:39:01 PM (New Zealand Standard Time, UTC+12:00)  #    Comments [1]   Azure | General  | 
Copyright © 2010 Peter G Jones. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme: