Monthly Archives: June 2006

Taqueria Guadelajara (Bellevue, WA)

Rating:

On the northwest corner of 148th Ave NE and NE 24th St in Bellevue there is a gas station. In the morning, there is often an espresso cart parked in the corner of the gas station. After 11AM however, the parking lot becomes the exclusive domain of Taqueria Guadelajara — the “taco truck”.

The taco truck is cheap, fast, and tasty. Tacos are $1.25 each (extra $0.25 for lengua, a.k.a. tongue), served on a double corn tortilla with cilantro, onions, radish, and lime. A chicken quesadilla will run you $3.25 and is a satisfying meal of chicken, cheese, sour cream, and salsa.

If you’re anywhere in the neighborhood around lunch time and are craving no-nonsense Mexican food, you have to check out the taco truck. It’s ghetto fabulous!

UPDATE (02/06/2007): For those wondering where the truck went, I just received this notice:

Taqueria Guadalajara (the taco truck) will re-open on February 7 at our new location in 15920 NE 8th St. Bellevue, WA 98005 located in the East Crossroad Shopping Center near the Post Office.

It turns out that the truck itself is still available at lunchtime, but now at the corner of 148th Ave NE and NE 40th Street.

Beyond the .asmx/.svc suffix: Multiple Endpoints

One of the key improvements in WCF is the concept of multiple “endpoints” at a Service. Last week (when I was offsite with a customer) I had an interesting revelation. While we cover the “ABCs” of Indigo (Address + Binding + Contract == Endpoint) in every introductory talk, many users don’t fully grasp the flexibility multiple endpoint support offers. This is most acute with regards to hosting in IIS, when multiple endpoint support involves “URI space beyond the file”.

For example, let’s say I have an Image Download Service hosted at image.svc. For interop purposes I expose a BasicHttp endpoint. I also add a second endpoint that uses a binary encoding instead of text. I provide a relative address of “binary” to this endpoint for addressing purposes. In this case my interop endpoint is exposed as:
http://kennyw.com/vdir/image.svc

And the binary endpoint is addressible as:
http://kennyw.com/vdir/image.svc/binary

Yes, that’s “/binary” after the filename.

The relevant piece of config for such as service (assuming you have a “binaryHttpBinding” defined in your bindings section) looks like:

<system.serviceModel>
 <services>
  <service name="Microsoft.ServiceModel.Samples.ImageService">
    <endpoint address=""
              binding="basicHttpBinding"
              contract="Microsoft.ServiceModel.Samples.IImageService" />

    <endpoint address="binary"
              binding="binaryHttpBinding"
              contract="Microsoft.ServiceModel.Samples.IImageService" />
  </service>
 </services>
</system.servicemodel>

Building a "Composite" Transport

I’ve often written about how to write custom channels; transports in particular. In all of the examples I’ve given, the same transport is used for both sending and receiving messages (i.e. HTTP out, HTTP in). This parallelism fails in certain scenarios. For example, WS-Discovery defines a pattern where you send out a UDP Multicast probe (a broadcast request to find a peer), and expect (one or more) HTTP unicast responses back.

Constructing a binding for this scenario requires three pieces:

  1. An outgoing transport
  2. An incoming transport
  3. A correlation mechanism to tie the request to the response

For the transports, you need a BindingElement that returns the outgoing transport from BuildChannelFactory and the incoming transport from BuildChannelListener. One way of doing this is with a CompositeTransportBindingElement. A CompositeTransportBindingElement uses two bindings to build its runtime components. For example, you can pass in a binding that consists of OneWayBindingElement + HttpTransportBindingElement. Or one that contains UdpBindingElement.

For correlation, if you add CompositeDuplexBindingElement to the stack, you can configure a ClientBaseAddress and Service Model will provide correlation using WS-Addressing. You could also provide correlation yourself (which is actually a good topic for later this week :))

The relevant pieces of CompositeTransportBindingElement (posted here) are:

class CompositeTransportBindingElement
        : TransportBindingElement
{
    Binding channelBinding;
    Binding listenerBinding;

    public CompositeTransportBindingElement(
        Binding channelBinding,
        Binding listenerBinding)
    {
        this.channelBinding = channelBinding;
        this.listenerBinding = listenerBinding;
    }

    public override IChannelFactory<TChannel>
             BuildChannelFactory<TChannel>(BindingContext context)
    {
        return channelBinding.BuildChannelFactory<TChannel>(
            context.BindingParameters);
    }

    public override IChannelListener<TChannel>
            BuildChannelListener<TChannel>(BindingContext context)
    {
        return listenerBinding.BuildChannelListener<TChannel>(
            context.ListenUriBaseAddress,
            context.ListenUriRelativeAddress,
            context.ListenUriMode,
            context.BindingParameters);
    }
}