How to prevent WCF-WebHttp Send Port from encoding a space in query parameter to a plus sign

Randy Lindsey 96 Reputation points
2021-06-09T23:20:30.98+00:00

I am calling a REST API in a commercial-off-the-shelf application to search for customers by phone number. These phone numbers are formatted like this: "(888) 888-8888"

My problem is the space " " after the right parenthesis. The BizTalk 2013 R2 WCF-WebHttp adapter seems to encode the URL after I build it, and it replaces the space with a plus sign "+". The COTS application does not decode this back to space, so my search always fails.

If I call the COTS application from a REST request using SoapUI it encodes the space as "%20" and the COTS app decodes this properly and returns the result.

I am using WCF-WebHttp Transport Properties URL Mapping to substitute the phone number from the message into the URL. Excerpt:
Method="GET" Url="/search?q={PHONENUMBER}&skip=0&take=1000"

I've tried substituting the space in the phone number with the following, but here is the result for each trial (as logged by a test IIS web site):

  1. Sent (097) 579-8888, end result was (097)+579-8888
  2. Sent (097)+579-8888, end result was (097)%2b579-8888
  3. Sent (097)%20579-8888, end result was (097)%2520579-8888
  4. Send (097) 579-8888, end result was (097)%26nbsp%3b579-8888

How can I prevent the WCF-WebHttp adapter from encoding my URL? I will take responsibility for encoding it myself.

Microsoft BizTalk Server
Microsoft BizTalk Server
A family of Microsoft server products that support large-scale implementation management of enterprise application integration processes.
358 questions
.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,573 questions
{count} votes

Accepted answer
  1. Randy Lindsey 96 Reputation points
    2021-06-23T14:45:55.617+00:00

    I'm using BizTalk 2013 R2. There was no additional helpful information in the WCF-WebHttp Adapter link posted above. I had already tried everything suggested there and elsewhere.

    To follow up, ultimately what I did was to create a dynamic send port rather than using a static send port as I initially tried.

    First I manually encoded my output parameter to replace any spaces with the web standard "%20".

    In a Message Assignment shape I set various properties on the outgoing message to configure the dynamic send. I pulled certain values from the ESSO database so they can be configured at runtime:
    MsgMyAppCustSearchRequest(WCF.HttpMethodAndUrl) = "GET";
    MsgMyAppCustSearchRequest(WCF.HttpHeaders) =
    XXX.Common.Helpers.SSOInterface.SSOInterface.Read("YYY.MyAppAdapter", "HttpHeaderContent") +
    System.Environment.NewLine +
    XXX.Common.Helpers.SSOInterface.SSOInterface.Read("YYY.MyAppAdapter", "HttpHeaderAuthorization");
    MsgMyAppCustSearchRequest(WCF.SuppressMessageBodyForHttpVerbs) = "GET";
    // Security is set later in a separate Decide shape
    MsgMyAppCustSearchRequest(BTS.SendPipelineResponseConfig) =
    "<Root xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Stages><Stage CategoryId='9d0e4103-4cce-4536-83fa-4a5040674ad6'><Components><Component Name='Microsoft.BizTalk.Component.JsonDecoder'><Properties><RootNode vt='8'>Root</RootNode><RootNodeNamespace vt='8'>http://XXX.YYY.MyAppAdapter.MyApp_CustSearchResponse_JSON</RootNodeNamespace></Properties></Component><Component Name='Microsoft.BizTalk.Component.XmlDasmComp'><Properties><AllowUnrecognizedMessage vt='11'>-1</AllowUnrecognizedMessage></Properties></Component></Components></Stage></Stages></Root>";
    MsgMyAppCustSearchRequest(WCF.VariablePropertyMapping) = System.String.Empty;
    MsgMyAppCustSearchRequest(BTS.RetryCount) = 0;
    MsgMyAppCustSearchRequest(WCF.MaxReceivedMessageSize) = 200000;
    MsgMyAppCustSearchRequest(WCF.OpenTimeout) = "00:01:00";
    MsgMyAppCustSearchRequest(WCF.CloseTimeout) = "00:01:00";
    MsgMyAppCustSearchRequest(WCF.SendTimeout) = "00:01:00";
    MsgMyAppCustSearchRequest(BTS.LRPMsgBodyTracking) = 1; // you could parameterize or use other message tracking settings

    Since you can't use If-Then-Else in a Message Assignment shape, separately I set other properties depending on whether we were using https or http:
    MsgMyAppCustSearchRequest2 = MsgMyAppCustSearchRequest;
    MsgMyAppCustSearchRequest2(WCF.SecurityMode) = "Transport"; // or "None" for http

    Finally I set some dynamic send port properties in an Expression shape, including crucially the properly encoded URL:
    Dynamic_Send_MyApp_CustomerSearchByPhone(Microsoft.XLANGs.BaseTypes.Address) =
    XXX.Common.Helpers.SSOInterface.SSOInterface.Read("YYY.MyAppAdapter", "ServerURL") +
    XXX.Common.Helpers.SSOInterface.SSOInterface.Read("YYY.MyAppAdapter", "OperationGetCustomerSearch") +
    "?q=" + MsgMyAppCustSearchRequest2(phoneNumber) +
    "&skip=0&take=2"; // Hopefully we only ever get one, but by allowing 2 we can debug if we do get multiples
    Dynamic_Send_MyApp_CustomerSearchByPhone(Microsoft.XLANGs.BaseTypes.TransportType) = "WCF-WebHttp";

    You can configure the Send and Receive Pipelines on the Port shape.

    This works. Seems silly that I had to do all this in order to gain control over the URL encoding of my parameter.

    0 comments No comments

0 additional answers

Sort by: Most helpful