0

At my workplace we are in the process of upgrading our Time and Attendance setup. Currently, we have physical terminals that employees use to check in and check out. These terminal communicate to a 3rd party T&A system via web service calls.

About the T&A web service:

  • Hosted on IIS 6
  • Communication is with WCF over HTTP
  • We're only interested in one of the exposed methods (let's call it Beep())

What I need to do:

  • Leave the original T&A system in place, untouched
  • Write a custom service that also reacts to calls to Beep()

So, essentially, I need to piggy-back on all the calls to Beep(), but I'm not sure what the best approach is.

What has been considered already:

  1. Write a custom webservice that implements the exact same same contract as the T&A service and direct all the terminals to that custom service. The idea being that I can then invoke the original T&A service from my custom service, as well as applying any other logic required.
    • This seems overly invasive to me, and seems needlessly risky. We want to leave the original system as unmodified as possible.
  2. Write a custom HTTP Handler to intercept calls to the original T&A service.
    • We've actually already done something like this in house, but our implementation takes the original HttpRequest, extracts the contents, invokes a custom service, and finally create a new HttpRequest based on the original request so that the original web service call to Beep() is made.
    • What I don't like about this approach is that the original HttpRequest is lost. Yes, a second, supposedly identical, request is created, but I don't know enough about HttpRequests to guarantee this is safe.

I prefer option 2, but it's still not perfect. Ideally we wouldn't need to destroy the original HttpRequest. Does anyone know if this is possible?

If not, can anyone suggest another way of doing this? Can IIS be configured to fork requests to two destinations?

Thanks

UPDATE #1

I have found a solution (documented here), but I'm still open to other options.

UPDATE #2

I like flup's solution (and justification). He gets the bounty :) Thanks flup!

4

4 回答 4

1

You can configure the web service to use a custom operation invoker, an IOperationInvoker.

WCF deserializes the original HTTP request as always, but instead of calling Beep() on the existing web service class, it will call your invoker instead. The invoker does its special thing, and then calls Beep() on the original service.

Advantage over implementing an IHTTPModule would be that all things HTTP are still handled by the original web service's configuration, unchanged. You fork off at a higher level of abstraction, namely on the web service's interface, at the Beep() method.

The nitty gritty of setting up a custom operation invoker without changing the existing service class (which makes it harder):

  • Implement a custom IOperationBehavior which sets the custom IOperationInvoker on the service's Beep() method in its ApplyDispatchBehavior method.
  • Implement a custom IEndpointBehavior which sets the custom IOperationBehavior in its ApplyDispatchBehavior method.
  • Put these two behaviors, with your IOperationInvoker, in a class library and add it to the existing service
  • Then configure the service to use the IEndpointBehavior.

See When and where to set a custom IOperationInvoker? and http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx for the invoker bit.

See Custom Endpoint Behavior using Standard webHttpEndpoint on how to configure a custom endpoint.

于 2013-03-21T21:00:57.593 回答
0

Sounds actually like you want to integrate your system into an ESB pattern. Now the MS solution to the ESB problem is Biztalk. Biztalk is the thermonuclear warhead nut cracker in this case. You don't want Biztalk.

Check out the results here for lightweight alternatives

于 2013-03-18T07:47:29.060 回答
0

I have found a solution using a custom IHttpModule. See sample below:

using System;
using System.Text;
using System.Web;

namespace ForkHandles
{
    public class ForkHandler : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.BeginRequest += new EventHandler(application_BeginRequest);
        }

        void application_BeginRequest(object sender, EventArgs e)
        {
            var request = ((HttpApplication)sender).Request;

            var bytes = new byte[request.InputStream.Length];
            request.InputStream.Read(bytes, 0, bytes.Length);
            request.InputStream.Position = 0;

            var requestContent = Encoding.ASCII.GetString(bytes);

            //  vvv
            // Apply my custom logic here, using the requestContent as input.
            //  ^^^
        }

        public void Dispose()
        {
        }
    }
}

This will allow me to inspect the contents of a webservice request and react to it accordingly.

I'm open to other solutions that may be less invasive as this one will require changing the deployed 3rd party web service's configuration.

于 2013-03-18T14:05:13.957 回答
0

If you want to intercept the message to the T&A WCF service i would suggest using custom listener which can be plugged into the service call by making changes in the web.cofig.

This will be transparent.

Please look for WCF Extensibility – Message Inspectors.

system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>          
          <add name="ServiceModelMessageLoggingListener">
            <filter type=""/>
          </add>
        </listeners>
      </source>
    </sources>
</system.diagnostics>
于 2013-03-20T05:38:13.193 回答