question

RandyLindsey-7120 avatar image
0 Votes"
RandyLindsey-7120 asked ·

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

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.



biztalk-server-allwindows-wcf
· 1
10 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

RandyLindsey-7120 avatar image
0 Votes"
RandyLindsey-7120 answered ·

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.

10 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.