call for testing System.Xaml.dll

| No Comments | No TrackBacks

This year was disasterous for me regarding machine troubles. I had to send my Acer laptop three times for repair (I have to say, their product is too fragile) and I also got Macbook white broken, which was worse, it was after 15 months since I bought it (out of warrant). And every time I got them broken, I suspend ongoing work and moved to some lightweight tasks. So that's how I started ongoing System.Xaml work these days.

Our System.Xaml.dll was initially written in last string, which was included in Mono 2.8 and had basic type system support. It also contained XAML readers and writers too, but they were far from usable. They were tested only in a few primitive use cases, and I didn't have much time to hack them either.

After System.Xaml.dll in our git master is a lot better. I have rewritten all of XamlObjectReader, XamlXmlWriter, XamlXmlReader and XamlObjectWriter with the actual object graphs. It also involved a lot of fixes in the type system (XamlType etc.).

In addition to our class status page, I created a wiki page on System.Xaml.dll work that describes the status in human language.

It should work fine with ordinal constructs such as Type (TypeExtension), Array (ArrayExtension), List, Dictionary and IXmlSerializable (XData). But it still doesn't support lots of "settings", and attachable properties are not supported either (as we don't have WPF or anything that provides them).

Now that I feel I am done with basic features, I'd like to ask anyone who uses this System.Xaml.dll in .NET 4 try our System.Xaml.dll in git master and see if it works. Make sure that your Xaml usage is independent of things like WPF (we don't have it, so it won't work). To check this, there is MoMA.

Current WCF 4.0 status in Mono

| 5 Comments | No TrackBacks

Mono 2.8 is approaching and I should indeed blog about it, but this post is about my recent hack in git head. Within the current future plan, we will be releasing 2.8.2 based on the git head, and by that time we'll deliver our results that I'm going to write here.

It is about WCF 4.0 implementation status in Mono. While it was not my priority, I have been somehow working on it (initially it was due to my laptop's crash and repair, now I rather want to finish this ongoing side work), it seemed good to write about it.

WCF 4.0 had added a lot of new features that didn't exist in 3.5/SP1. An excellent article by Aaron Sconnard is on MSDN, so I'll describe our ongoing effort based on the items he described.

featured areacurrent status
Simplified Configurationalmost done
DiscoveryAnnouncement: done. Discovery: ongoing.
Routingdone
REST improvementsnot done.
WF4 supportno plan yet.

(Note that this table does not contain other components such as WCF Data Services.)

Simplified configuration

In WCF4, configuration description can be reduced and it became much simpler to write. It's not always good as it also hides what WCF actually does from application developers, but almost everyone wouldn't understand what the engine does anyways, so no need to worry about that.

Default Endpoint was the last thing I actually hacked (as of now). In WCF 3.x, you always had to add service endpoints either in your app.config or by call to AddServiceEndpoint(). Since you wouldn't host more than two contract interfaces at a time and had to specify explicit endpoints for each, it is almost always waste of time, so in WCF4 it is automatically configured if you didn't provide explicit endpoint.

To achieve Default Endpoints, contract, binding and endpoint address must be provided. Since contract and endpoint can be given at ServiceHost constructors, only binding needs to be automatically guessed. And here is the practical use of Protocol Mapping. It is URIscheme-to-BindingType mapping, and the base addresses in a service host contain URI scheme.

The default Protocol Mappings are not visible in the machine.config in .NET 4.0, but they are filled at ProtocolMappingSection's InitializeDefault method. (You cannot see this overriden method in MSDN API reference - it could be confirmed through our class status pages, or some people like me could smell it because ClientSection also had overriden InitializeDefault implementation like this and hence it lacked the actual config section.)

Standard Endpoints are implemented in accordance with WCF Discovery work. While I don't really like WCF configuration stack, there would be a couple of samples that are based on configuration to run, and I didn't want to get messed just by lack of it while dogfooding.

File-less activation is also what I think nice-to-have feature, but not implemented yet. (Well, and actually whatever I haven't written here aren't yet either.)

Discovery

WCF Discovery is a WS-Discovery implementation, which enables us to dynamically register and dispatch the destination information for specific type of services by announcement by service providers and queries by client consumers. Sadly it is SOAP-based and useless for other bindings.

WCF Discovery needed some tricks and underlying layers that I had to (and need to) work on:

  • Standard endpoint support. Both AnnouncementEndpoint and DiscoveryEndpoint are standard endpoints that needed extra work on WCF 4.0 stack done earlier.
  • UDP transport. It is so far available only through those standard endpoints (ServiceEndpoint's Binding property). .NET UDP transport implementation as well as ours has some hacky code, for example it repeats sending messages a couple of times so that the recipients will rarely miss it, so I can understand why it's not exposed as part of public API. (Repeating UDP messages won't fit other UDP uses such as sending OSC messages to instruments.)
  • Multiple WS-Discovery spec. version support. There are WS-Discovery 1.1, WS-Discovery CD1 (committee draft), and WS-Discovery April 2005. They reside in different namespaces, yet have almost identical set of elements and functionality. Different namespaces means different service contracts, but there are no contract types in WCF Discovery assembly (System.ServiceModel.Discovery.dll). In fact those types exist as "internal" interfaces which are implemented in AnnouncementEndpoint, DiscoveryService or DiscoveryProxy.
  • The trickiest part is that the contract type differs when the binding supports request-reply and when the binding supports duplex. I got request-reply style discovery (actually only Find operation) working, but not for duplex discovery yet so far. Actually, this complexity affects all over the API (indirectly).

Routing

Actually our WCF Routing implementation had been there since Mono 2.6 and I have already wrote about it, so I don't write duplicates here.

Routing configuration types are implemented, so at some stage it will be completed when some people (or we) would like to use it in practice.

Other tasks

REST improvements is sort of on our stack, but I have no concrete plan to work on it yet. It also applies to some new features such as receive context. WF4 support too, but it's very different as we don't have WF4 itself. BTW WF4 is made into System.ServiceModel.dll and now it messed me a lot by injecting a lot of our class status pages. As compared to that of 3.5, the number of missings looks quite big, but we don't lack new features that much.

And, while I wrote about 4.0, my primary hacking area is 3.0 stack. I'm likely go back to components that make up WSHttpBinding and further ones once I achieved duplex Discovery work.

ServiceMetadataExtension refactoring story

| No Comments | No TrackBacks

I had been fixing several bugs in our WCF code these months. Yeah, I kept silent just because it is too boring topic to blog :p

One of the most problematic one was ServiceMetadataExtension support, which is for WSDL output on the service site (the ones you get when you access to http://yourwebsite/yourservice.svc?wsdl). Yes, surprisingly. You would not understand why that is so problematic.

(0) (re)introduction

For public API wise, I once wrote an entry-level entry for entrypoint to service metadata support last year. I didn't give any explanation on its internals at all. Now it's time.

A simple code for hosting a WCF service with metadata support would look like:

var host = new ServiceHost (typeof (FooService), new Uri (uri));
host.AddServiceEndpoint (typeof (ITestService),
    new BasicHttpBinding (),
    new Uri ("", UriKind.Relative));
host.Description.Behaviors.Add (
    new ServiceMetadataBehavior () { HttpGetEnabled = true });
host.Open ();

Today, in the example above, what actually creates a working service listener is only the last line: host.Open (); only the last line matters. I explain what it's doing there, step by step.

(1) ServiceHostBase and Binding

First, I'll explain what ServiceHostBase supports and what you can do only with Binding.

Basically, ServiceHost(Base) manages more than one service "endpoint". You can call "AddServiceEndpoint" on the same host multiple times. A service endpoint is a set of an "endpoint address", a "binding" and a "service contract". You can implement multiple service contract interface within a service type (FooService) and serve requests to different interfaces at different endpoint URIs (addresses), using the same or different binding. A binding can be things like BasicHttpBinding, NetTcpBinding, WebHttpBinding, WSHttpBinding (not supported in mono yet) or anything that derives from Binding.

You might know that Binding class has a method that creates an IChannelListener object that is to actually listen for requests. Actually, to receive requests in Message form, you don't have to even use ServiceHost. Instead, you can do this:

var binding = new BasicHttpBinding ();
IChannelListener<IReplyChannel> listener =
   binding.BuildChannelListener<IReplyChannel> (
      new Uri ("http://localhost:8080/"));
listener.Open ();
IReplyChannel ch = listener.AcceptChannel ();
ch.Open ();
RequestContext ctx = ch.ReceiveRequest ();

RequestContext has a request Message that is created from the HTTP SOAP request it received. You can use Reply(Message) method to return a message in whatever form you want.

You wouldn't find it very useful. You'd rather use strongly-typed services instead so that you don't have to get messes by Message object. Also you wouldn't like to call ReceiveRequest() every time explicitly. Hence, there is ServiceHost(Base). It handles those tasks.

(2) ChannelDispatcher and EndpointDispatcher basics

When ServiceHostBase.Open() is called, the host creates a set of "ChannelDispatchers" in the host. A channel dispatcher is created for each Binding used in the ServiceHostBase (actually for each of its service endpoints).

A ChannelDispatcher manages an IChannelListener created from Binding.BuildChannelListener<TChannel> method. TChannel can be something other than IReplyChannel, but I don't explain it here (not primary topic today).

A ChannelDispatcher holds one or more "endpoint". In ServiceHostBase, there could be multiple ServiceEndpoints and they have a Binding and an EndpointAddress. Actually the Binding instance can be shared, and in such case, those ServiceEndpoints that shares the same Binding also shares the same ChannelDispatcher.

In ChannelDispatcher, the set of endpoints is represented as Endpoints property and an endpoint becomes an EndpointDispatcher. EndpointDispatcher is hence bound to a contract. When a request to the channel listener arrives (e.g. HTTP request), the ChannelDispatcher has to determine which "endpoint" (EndpointDispatcher) should process the request. Usually it is determined by its ContractFilter and AddressFilter properties, and since usually service endpoint URIs differ, it does not matter much (Use "/foo" for IFooService and "/bar" for IBarService.

... well, I wrote "basics". Yes, it is basic part. The core part starts from here.

(3) IMetadataExchange, ServiceMetadataBehavior and ServiceMetadataExtension

With BasicHttpBinding, an IChannelListener is created for HTTP scheme, and its listening URI is typically a local HTTP URI. In mono, it is either done by ASP.NET (xsp) or HttpListener (non-ASP.NET). In both cases, the services blocks the listening URI, and if we simply try to serve WSDLs using another HttpListener, there is no more room. Since WSDL requests could be sent to the same URI of the service itself, typically only differentiating the query parameter, there sould be some trick. (Do you understand it's getting messier?)

Another complication factory is that there is ServiceMetadataBehavior and ServiceMetadataExtension that have some Binding and Uri properties and show capability of handling "metadata exchange" requests. So it's not only about WSDL. Its endpoints must be exposed at users' will.

Interestingly, MetadataExchangeBindings class exposes a couple of static methods that creates a Binding for mex endpoints. And they are actually used by ServiceMetadataExtension, that is an IExtension for ServiceHostBase and realizes ServiceMetadataBehavior's requirements. Since Binding instance are different, it can create another IChannelListener, which typically has the identical listen URI as the service endpoint itself has.

The different Binding instance results in different ChannelDispatcher in the ServiceHostBase. I was originally aware of the fact that when the ServiceHostBase is opened there are two ChannelDispatchers (the reason came later). Different channel disptatchers have (again) different IChannelListener instances. And they still point to the same listen URI.

That's problematic. It makes request dispatching difficult. To make it worse, ChannelDispatcher has MessageVersion property. If they resided in the same ChannelDispatcher, it would have been easier since we could use message filters to select appropriate EndpointDispatcher. HTTP request interpretation varies dependin on the target MessageVersion. So the target ChannelDispatcher and EndpointDispatcher must be selected before IChannelListener.ReceiveContext() is done.

(4) HTTP listener manager

Hence we have to create another management layer for HTTP channel listener to reuse the same HttpListener (and some equivalent management layer for ASP.NET). Actually when Mainsoft hackers were working on it, they were aware of this issue, and created a management layer. It mostly worked until we reached the point that we have to handle more strict differentiation.

Basically, we determine if the request is GET and if the target URL matches the wsdl GET URL, then it is for WSDL. Actually there is ServiceDebugBehavior so we also handle it (if you omit "?wsdl" query parameter in your HTTP request, you'll see some "help page" for the service. It is what ServiceDebugBehavior is for).

BUT, we can't bindly determine such requests as for WSDLs. Do you remember there is WebHttpBinding? With this binding, you can access services by UriTemplate, and it is todally done by GET request (with no request stream). Whenever applicable, we should handle requests to the RESTful services within the binding. Interestingly, WebHttpBinding uses WebHttpBehavior to adjust endpoint behaviors, and it actually raises its EndointDispatcher's FilterPriority(!). So IF the endpoint dispatcher is in the same ChannelDispatcher as ServiceMetadataBehavior yields, there was no problem. Sadly, WebHttpBinding is, again, a different binding that ServiceMetadataBehavior gives, so it creates different ChannelDispatcher (as BasicHttpBinding does).

To get the higher priority settings working, we have to "hack" the order of searching appropriate ChannelDispatcher to dispatch an HTTP request, by its Endpoints (EndpointDispatchers).

All of those behaviors cannot be completely done within WCF public API. So, ServiceMetadataBehavior and ServiceMetadataExtension are special. You cannot create functionally-equivalent one without giving up some aspects (e.g. it would be able to be done if you don't allow hosting WSDL on the same URI as the service is listening).

(5) done

It had been a longstanding issue that attacked me over and over again (fix->regress->fix->regress...), and history may repeat, but I rewrote the HTTP listener stack and relevant stuff last week, it should work today, hopefully in more reliable state. And since that fixes I feel much comfortable than those annoyed days in my hacking life :)

initial System.Xaml work

| No Comments | No TrackBacks

These days I have been running away from WCF and hacking new System.Xaml.dll which is new in .NET 4.0 last week. I needed some break and fresh air.

It is already in mcs tree, and not a few of them are implemented and already working, though there's a lot of things left to do.

In .NET land, there seems to be some class libs such as WPF and new Workflow that depend on it. And I'm guessing it could be reused for some sort of my own designing tool.

My primary work area is still WCF so I won't be able to finish it soon, but I hope I get it practically working by the next 2.8 release (which is not in certain scope yet).

Mono WCF Advent Day 13: WCF 4.0 Routing

| 1 Comment | No TrackBacks

While we don't have some significant parts of WCF 3.0 stack such as working message security, we have some new stuff, like WebHttpBinding I explained on Day 9. It also applies to WCF 4.0. We have new routing stack.

WCF router support is only in SVN trunk, in System.ServiceModel.Routing assembly, mostly in System.ServiceModel.Routing namespace. Note that .NET 4.0 is still in beta, so things may change as .NET 4 development goes on.

Router usage

Message router is to dispatch messages that it received from clients, to certain servers. A WCF router is a WCF service for router client users, while the router works as a WCF client for routed services (which may not be WCF).

Routing design is almost simple: a WCF router service has a table of a message filter that is used to test if a message matches it or not, and a set of endpoints to dispatch messages it received. The table is represented as MessageFilterTable<MessageFilter,IEnumerable<ServiceEndpoint>>.

(Usually just one service endpoint is enough; simplex or duplex channels may dispatch messages to more than one service endpoints.)

Message router often has to rebuild the input message, like, adjusting message versions and To message header.

I haven't prepared an entire routing example (I tested it with MS sample in 4.0), but router usage would look like:

var host = new ServiceHost (typeof (RoutingService));
host.AddServiceEndpoint (
  typeof (IRequestReplyRouter),
  new BasicHttpBinding (),
  new Uri ("http://localhost:8081/router"));
var config = new RoutingConfiguration ();
var clientEndpoint = new ServiceEndpoint (
  ContractDescription.GetContract (typeof (IRequestReplyRouter)),
  new BasicHttpBinding (),
  new EndpointAddress ("http://localhost:8080/service"));
var list = new List<ServiceEndpoint> ();
list.Add (clientEndpoint);
config.FilterTable.Add (new MatchAllMessageFilter (), list);
host.Description.Behaviors.Add (new RoutingBehavior (config));

Internals

There is not many things to explain for WCF routing, so I'd explain its internals instead so that some people might want to write similar code for several purposes.

To host a routing service, RoutingService is used. It has four interfaces for several channel interface types;

  • IRequestReplyRouter for typical request-reply channels
  • ISimplexDatagramRouter for input/output channels
  • ISimplexSessionRouter for input/output sessions channels
  • IDuplexSessionRouter for duplex session channels

To add routing with a specific table, you'll first have to create the table. It is represented as FilterTable property in RoutingConfiguration class. Once you have created a configured RoutingConfiguration instance, then use RoutingBehavior object, which is of IServiceBehavior interface (a behavioral extension to ServiceDescription, see Day 5 for quick introduction to "service behaviors") and takes RoutingConfiguration as its constructor argument.

Once you have set routing configuration in above manner, then what to do next is to call AddServiceEndpoint() with (1) an interface type I listed above, (2) a binding for the router "(as a) service", and (3) an endpoint address for the router "(as a) service". (1) must be determined as to comply with the routed servers' requirements, and (2) and (3) represent the endpoint information for routers' client (and of course, a client must comply with (1) to properly communicate with the router).

Those four routing interfaces I listed above, all have Message as its one input argument (and output for IRequestReplyChannel). Since the contracts are very generic, a routing service can handle any communication between the client and the routed server (i.e. since they just take Message, it involves no typed serialization regardless of the contract of the routed service).

When a RoutingBehavior is called its ApplyDispatchBehavior() with a ServiceHostBase argument, it adds RoutingExtension to the service host. Then (1) it updates its service "instance context provider" (IInstanceContextProvider) that instantiates a RoutingService (which has no public constructor) and sets the routing configuration to it, and (2) creates a set of clients for the dispatched services internally.

There is another "endpoint behavior" SoapProcessingBehavior. It takes part in the router-to-service communication and adjusts messages (as I explained above e.g. updating message versions). You don't have to deal with it.

It is in very early stage and in fact I only tried request-reply style router.

Bonus

Our Routing stack should work on .NET 3.5 too. Try "make" under mcs/class/System.ServiceModel.Routing - it will build mcs/class/lib/net20/System.ServiceModel.Routing.dll i.e. for 2.0 profile. There is nothing new I depended for its underlying layer.

Mono WCF Advent Day 12: NetPeerTcpBinding

| 1 Comment | No TrackBacks

With related to NetTcpBinding, I have also implemented NetPeerTcpBinding, which is based on peer-to-peer communication.

NetPeerTcpBinding involves a lot of complicated things, so I'm not likely to explain a lot.

Peer to peer channel overview

NetPeerTcpBinding itself is a binding for duplex messaging with binary message encoders (like NetTcpBinding) and its own transport, namely PeerTransportBindingElement. It also involves a "peer resolver" which is used to manage peer node statuses.

PeerTransportBindingElement is a transport binding element like HttpTransportBindingElement or TcpTransportBindingElement. While HTTP endpoint is a typical http URI (locally it is most likely only about the port), and TCP endpoint is about an IP endpoint (I forgot to mention yesterday, but its URI is like "net.tcp://localhost:808"), peer transport endpoint is about a "mesh" name which is handled by a "peer resolver". Its URI looks like "net.p2p://mymesh/" . Messages are transmitted to all the "peer nodes" in the specified peer "mesh".

(If you read PeerTransportBindingElement API, you'd notice that it takes an IP endpoint for listening peer connections. But it is not the endpoint - peer transport indirectly uses it, unlike an IP endpoint for TCP endpoint.)

Actually, a peer resolver, which is represented as PeerResolverBindingElement, is more inportant to know the actual peer transport destination. On .NET there are (nominally) two ways to "resolve" peer nodes to transmit messages: (1) PNRP, represented as PnrpPeerResolverBindingElement is Windows peer node resolution protocol, and (2) custom resolver, represented as PeerCustomResolverBindingElement, is resolver-instance-by-user peer resolver with IPeerResolverContract and CustomPeerResolverService API.

With PNRP you don't have to specify anything to resolve peers. It is however not available in Mono (PNRP is Windows specific and I haven't spent any time to implement it). With custom resolver, you have to (only) specify a service endpoint (Binding and EndpointAddress) to IPeerResolverContract service, which is typically CustomPeerResolverService.

Having your host is simple. Just create a ServiceHost with CustomPeerResolverService and add a service endpoint for IPeerResolverContract.

Usage example

(NOTE: As it depends on NetTcpBinding and it has some blocking issues right now, this binding does not likely work fine either.)

I haven't written any cool net-peer application beyond simple tests. Instead, I used chat application which used to be the top Google results for "WCF application". The server isn't really a peer channel server but rather a custom peer resolver, but the clients show basic use of net-peer communication.

The example code makes use of PeerNode and its interface IOnlineStatus.

Implementation internals

The public peer resolver API does not tell much, but its internals are complicated. It has to provide several operations such as, register node to the target mesh (Register), resolve nodes in the target mesh (Resolve), updates node availability statuses (Refresh) and unregister the node from the mesh (Unregister).

Microsoft has a dedicated Windows protocol documentation. The expected peer resolver mechanism is documented as [MC-PRCR] and [MC-PRCH].

In .NET, CustomPeerResolverService internally uses PNRP to implement IPeerResolverContract, So, while "nominally" custom peer resolver is one of the two peer resolver kinds, there is actually only PNRP on .NET.

In Mono, I created BasicHttpBinding-based ad-hoc peer resolver service that is launched within a mono process that uses custom resolvers (the internal "LocalPeerResolverService" class in System.ServiceModel.dll implements the service). It checks port 8931 availability, and if it is already used then it premises as if it were occupied by another custom resolver of our implementation. This behavior may change in future versions.

For paranoiac

It is a trivia I found during NetPeerTcpBinding hacking. You cannot expose WSDL for IPeerResolverContract using ServiceMetadataBehavior (see Day 5) because of duplicate global element for 'http://schemas.microsoft.com/net/2006/05/peer:Update' . 99.999% of WCF users wouldn't have to do it though (say, you don't have to implement CustomPeerResolverService).

The reason for this is complicated: it is because RegisterResponseInfo and UpdateInfo have conflicting return element name "Update" (in the same XML namespace) due to its MessageBodyMemberAttribute. That's my guess though - as IPeerResolverContract methods use message contracts for its argument and return value types. But as the contract there wouldn't be other possibilities so it should be almost precise.

The above story is almost nothing for you. But this kind of faulty contract design could happen by chance and it cannot be checked very obviously. The only way I can suggest to try to avoid such problem is to check WSDL generation frequently (like, every time you change the message contract).

Mono WCF Advent Day 11: NetTcpBinding

| 6 Comments | No TrackBacks

Until today I have explain only two Bindings (or three): BasicHttpBinding and WebHttpBinding (and CustomBinding if it counts). But as I implied earlier, we have more. Today I'd explain TCP transport and NetTcpBinding and couple of new things.

In short, NetTcpBinding is WCF-only, non-interoperable binding based on binary messages and TCP transport.

Binary XML serialization

"Binary XML" is not really XML. It is fake, a buzzword. It actually means, a binary representation based on XML Infoset (or something, depending on what it would describe). In WCF land, binary XML usually means an XML binary format used by XML reader and writer from XmlDictionaryReader.CreateBinaryReader() and XmlDictionaryWriter.CreateBinaryWriter().

While we have corresponding implementation since 2005, its data format has been recently published as [MC-NBFX] as part of Microsoft's Windows Protocol documentation.

In WCF, there is BinaryMessageEncodingBindingElement that uses this binary XML representation to serialize and deserialize messages. You can explicitly use it as message encoder part of your binding (using CustomBinding) as I did on Day 3. NetTcpBinding uses this one without customization.

Request/Response vs. Duplex

Message transport protocol also involves its own binary representation, but I have to explain "channel types" in prior. Until today I haven't explain about channel types, in other words types of IChannel interface variety - as BasicHttpBinding and WebHttpBinding are both for request-reply style communication. WCF is not only about it - it actually supports:

  • request-reply messaging: represented as IRequestChannel and IReplyChannel. A client sends a request to a server, then the server receives it and sends reply back to the client, and the client receives it.
  • simplex messaging: represented as IOutputChannel and IInputChannel. A client sends a message to a server, then the server receives it. No further communication is performed.
  • duplex messaging: represented as IDuplexChannel. Either of the communication sides may perform simplex messaging.

They may also involve sessions and in such case they become IFooSessionChannel (e.g. IRequestSessionChannel). To know which kind of messaging is supported by the Binding you are using, you can use CanBuildChannelFactory<TChannel>() method for clients or CanBuildChannelListener<TChannel>() method for servers.

It may look strange, but duplex messaging could be still used to support service method that has both invocation parameters (request) and return value (reply).

TCP binary data exchange

Back to NetTcpBinding, it supports two kinds of above, under different configuration; NetTcpBinding has TransferMode property and it indicates the communication channel style. If the property value is TransferMode.Streamed, then it creates request-reply type channel. If it is TransferMode.Buffered, then it results in duplex channel. While duplex channel could be used for RPC-style service calls, the underlying communication protocol becomes different. So you have to adjust the transfer mode between client and server.

The communication protocol is also documented, as [MC-NMF] and some related docs in Windows Protocol documentation.

NetTcpBinding example

Here is an example pair of NetTcpBinding client and server, using buffered == duplex communication mode.

[NOTE] It turned out that I brought some regressions which broke some binary message communication. It has been a while since I have implemented a couple of months ago. I've been fixing some bugs these days.

// client
using System;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;

public class Test
{
  public static void Main ()
  {
    var binding = new NetTcpBinding ();
    binding.Security.Mode = SecurityMode.None;
    var endpoint = new EndpointAddress ("net.tcp://localhost:8080/");
    var proxy = new ChannelFactory<IFoo> (binding, endpoint).CreateChannel ();
    Console.WriteLine (proxy.Echo ("TEST FOR ECHO"));
    Console.WriteLine (proxy.Add (1000, 2000));
  }
}

[ServiceContract]
public interface IFoo
{
  [OperationContract]
  string Echo (string msg);

  [OperationContract]
  uint Add (uint v1, uint v2);
}
// service.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

public class Tset
{
  public static void Main ()
  {
    ServiceHost host = new ServiceHost (typeof (Foo));
    NetTcpBinding binding = new NetTcpBinding ();
    binding.Security.Mode = SecurityMode.None;
    var uri = new Uri ("net.tcp://localhost:8080");
    host.AddServiceEndpoint ("IFoo", binding, uri);
    host.Open ();
    Console.WriteLine ("Hit [CR] key to close ...");
    Console.ReadLine ();
    host.Close ();
  }
}

[ServiceContract]
public interface IFoo
{
  [OperationContract]
  string Echo (string msg);

  [OperationContract]
  uint Add (uint v1, uint v2);
}

class Foo : IFoo
{
  public string Echo (string msg)
  {
    return msg;
  }

  public uint Add (uint v1, uint v2)
  {
    return v1 + v2;
  }
}

Limitation

.NET NetTcpBinding is actually capable of handling some complicated things such as message security, but we don't provide message security support yet. If you have NetTcpBinding configured to use message security, NetTcpBinding.Security.Mode has to be set as None.

Mono WCF Advent Day 10: ASP.NET AJAX Integration

| 3 Comments | No TrackBacks

Well, yes, it continues a bit more...

Yesterday I explained WebHttpBinding which is dedicated to REST world. It is however just one aspect of the new REST support in .NET 3.5. Here is another one - you can invoke remote WCF services from ASP.NET AJAX.

Javascript proxy generator

What's done here is, basically the same as what ASP.NET AJAX do for System.Web.Services asmx support. In asmx integration land, there is Javascript proxy generator that accesses to the remote service and returns server responses back to Javascript land. The Javascript proxy source is retrieved at http://your.host.name/service.svc/js or http://your.host.name/service.svc/jsdebug (with debugging info).

The implementation is in ProxyGenerator class in ASP.NET AJAX assembly (System.Web.Ext.dll). By using ProxyGenerator.GetClientProxyScript() method, you can see how the raw Javascript proxy code is generated from your service contract, without actually deploying your service at your host.

It matches the Javascript code that you can see at somewhere like: http://your.host.name/service.svc/jsdebug

WebScriptEnablingBehavior

The next question is, how to provide such Javascript proxy at ./js or ./jsdebug for each service (endpoint). When there are two or more services, there will be two or more js proxies (foo.svc/js and bar.svc/js).

To resolve this, there is "WebScriptServiceHostFactory" which adds support for those js proxies for each service endpoint. It internally uses WebScripeEnablingBehavior which is derived from WebHttpBehavior. When WebScriptEnablingBehavior is attached to a service endpoint, it adds a special request "dispatcher" (precisely, EndpointDispatcher) to the host to handle requests to ./js or ./jsdebug as to return js proxy string.

I don't explain the mechanism a lot here, but in case you are curious, ChannelDispatcher, EndpointDispatcher and DispatchRuntime have a lot of customizible things at service host.

(In my previous post, I didn't explain much about WebHttpBehavior, an implementation of IEndpointBehavior. It actually plays the primary role on the REST binding support such as, setting "message formatter" to serialize request parameters using JSON serializer, to bind to and generate parameters from "URI template", etc. etc.)

Anyways, now we have a dedicated endpoint for Javascript for each service endpoint from the service instance. The service instance should be adjusted to use WebHttpBinding which is configured to use JSON as its message format so that the service can communicate with the JS proxy running in users' browser.

ASP.NET hosting

The entire service host setup above is valid to standalone ServiceHost too. But it does not make sense to do so - the primary purpose of those js proxies is reference from ASP.NET AJAX web pages. Hence there is almost no use for standalone hosting.

I don't write a lot to explain how to use <asp:ServiceReference > and proxies in your ASP.NET AJAX web page (Javascript) here - our bug #525575 shows simple usage.

Xmas!

| No Comments | No TrackBacks

It's 5am here so I don't think I can give long explanation on my hack so I'll do it in later days, but here is one of my hobby hack of this year: visual MIDI player based on Moonlight desktop.

mldsp-gtk-2009xmas.png

Sources and brief introduction are on github.

Merry Christmas!

Mono WCF Advent Day 9: RESTful WebHttpBinding

| 6 Comments | No TrackBacks

REST support has been introduced in .NET 3.5. It includes JSON support for message serialization, and support for RSS and Atom for consuming web feeds (as serialization contract). It is implemented as WebHttpBinding in System.ServiceModel.Web.dll.

Unlike some of the topics I wrote earlier, our REST support compatibility for .NET 3.5 is almost feature complete (yes I prefer RESTians than SOAPy people).

URI Templates

REST services have "resources" identified by URLs, like: http://localhost/ShoppingService/Products/by-name/RupertsDanceLesson_DVD

While HTTP transport stack is reusable, the existing BasicHttpBinding does not fill such needs - the destination of its request is identified by SOAP request header or HTTP request content body. A dedicated message encoder is required.

The alternative mechanism used for processing such requests in WebHttpBinding is "UriTemplate" which is a syntax based on URI but includes expressions like '{x}'. For example: "/ShoppingService/Products/by-name/{name}"

When a client is to send a request with certain set of parameters, the client first determines the request URI by filling dynamic parts of the URI template. Then the client sends the request to the service. When the service received a request, it tries to determine which operation in the service should handle it, and extract parameter values from the actual request URI. There won't be files at the corresponding destination URI. It's all virtual.

JSON reader, writer, serializer

Requests in WebHttpBinding are created as an URI. Responses in REST services are often returned as JSON. With WebHttpBinding, you can read and write JSON in certain structure - since WCF Messages are serialized as "XML", which strictly means, XmlDictionaryReader/Writer, the JSON input and output are also represented as the XML reader and writer. I don't explain the details, but you can start reading from JsonReaderWriterFactory.

There also is another specialized type for JSON serialization i.e. DataContractJsonSerializer. It reads and writes JSON instead of XML.

JSON serializer could be also used for serializing complex request parameters.

Of course, WebHttpBinding does not always use JSON. Rather, it uses POX (plain old xml) by default.

RSS and Atom serialization

Another typical practice in REST world is use of syndication feeds such as RSS and Atom. WCF 3.5 added support for serialization of those feeds. In System.ServiceModel.Syndication namespace there is a couple of types for data contract serialization of feeds and feed items.

Operations using WebGet and WebInvoke

With WebHttpBinding the existing OperationContractAttribute is not sufficient to provide how to host services. A URI template must be associated to each operation. WebGetAttribute or WebInvokeAttribute are used onto an operation method to bind URI template. Though, you don't have to explicitly design the service URI; it will be automatically inferred like: http://...[baseuri]/[operation]?argFoo={argFoo}&argBar={argBar}...

Adding [WebGet] or [WebInvoke] does not automatically work for WCF engine to assure that it is RESTful service. You also have to use either a dedicated channel factory or a service host, or WebHttpBehavior, a custom IEndpointBehavior. While WebHttpBehavior plays the primary role for everything I explained above and more, former approach would be easier.

Now we are ready to write sample code and run.

// client
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Web;

[ServiceContract]
public interface IMyService
{
  [OperationContract]
  [WebGet (RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json)]
  string Greet (string input);
}

public class Test
{
  public static void Main (string [] args)
  {
    string name = args.Length > 0 ? args [0] : "anonymous joe";
    string url = "http://localhost:8080";
    WebHttpBinding b = new WebHttpBinding ();
    var f = new WebChannelFactory (b, new Uri (url));
    IMyService s = f.CreateChannel ();
    Console.WriteLine (s.Greet (name));
  }
}

// service
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;

[ServiceContract]
public interface IMyService
{
  [OperationContract]
  [WebGet (RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json)]
  string Greet (string input);
}

public class MyService : IMyService
{
  public string Greet (string input)
  {
    return "hola, " + input;
  }
}

public class Test
{
  public static void Main ()
  {
    string url = "http://localhost:8080/";
    WebHttpBinding b = new WebHttpBinding ();
    var host = new WebServiceHost (typeof (MyService), new Uri (url));
    host.AddServiceEndpoint (typeof (IMyService), b, "");
    host.Open ();
    Console.WriteLine ("--- type [CR] to quit ---");
    Console.ReadLine ();
    host.Close ();
  }
}

In the example above, I used WebChannelFactory<T> instead of client class which is derived from ClientBase<T>, but as long as you use a gives instance of IMyService from it, its role is almost the same as ClientBase.

Limitations

Sadly WebHttpBinding is not available in Moonlight (nor Silverlight). It is not because the REST style does not fit Silverlight or RIA land in general, but because Silverlight API lacks behavioral extensibility API. I see there is no reason to not add things like IEndpointBehavior, but that's what Microsoft API does.

While WebHttpBinding is more WWW-friendly, it is not always possible to handle RESTful services. To handle JSON objects, it automatically adds type IDs during serialization and expects the IDs on deserialization.

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • anonymous: Chinese FurnitureAffordable residence handmade handmade furnishings have to have to read more
  • anonymous: Chinese oriental decorDesk Globes engraved chinese a Chinese classic handmade read more
  • atsushieno: There can be always more words to explain things, but read more
  • Danica: I have observed that you don't explain all the mechanism read more
  • Danica: I have observed that you don't explain all the mechanism read more
  • Zaib: Was stuck with some problems and issues regarding programming and read more
  • Anna Marie: I don't know actually what are these stuff means. Can read more
  • atsushieno: The sources are now in github (like other mono modules) read more
  • Jason Cook: atsushieno, You say you applied the fix, but I see read more
  • Chris Bowdon: I tried to modify the Day 2 example to expose read more

Recent Assets

  • mldsp-gtk-2009xmas.png
  • sshot-mt-wcf.png
  • moonlight2-wcf-md.png
  • mldsp.png
  • linqdatasource.png

Categories

Pages

Powered by Movable Type 4.21-en