How to cancel a request in BeforeSendRequest

899 Views Asked by At

When using the IClientMessageInspector interface, can I cancel a request from the BeforeSendRequest method? Returning null sends the request anyway.

 public object BeforeSendRequest(ref Message request, IClientChannel channel)
 {
    if(Condition)
    {
        return null; //I want cancel my send
    }
    else
    {
       return request;
    }
  }
2

There are 2 best solutions below

0
On

You can cancel the request with IClientChannel's Abort method. But your client's dispatch method throws CommunicationObjectAbortedException.

public object BeforeSendRequest(ref Message request, IClientChannel channel)
 {
    if(Condition)
    {
        channel.Abort();
        return null;
    }
    else
    {
       return request;
    }
  }
0
On

There are probably multiple ways to handle this scenario, but I think they all involve simply throwing an exception out of your IClientMessageInspect.BeforeSendRequest to prematurely end the client operation. The type of exception you throw probably varies depending on what the consuming application expects in your scenario, or something you can catch upstream some where else.

In my case, I was building a WCF RESTful proxy/routing service. My IClientMessageInspect was required to inspect outgoing messages bound for our texting vendor, and not allow the outgoing message to be sent to the vendor's Service API unless the outbound phone number was "white listed" in the router proxy/routing service web.config

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
    if (!WhiteList.IsWhiteListed(outboundNumber))
    {
        throw new WebFaultException<RouterServiceFault>(new RouterServiceFault {Message = $"Phone number {outboundNumber} is not white listed." }, HttpStatusCode.Forbidden);
    }

    // Save the routed to service request address so we can see it after receive reply (in correlationState)
    return request.Headers.To;
}

Where RouterServiceFault is a simple class I can pass a message back in to display/log in the consuming application.

[ServiceContract]
public class RouterServiceFault
{
    [DataMember]
    public string Message { get; set; }
}