none
Configuring Rest Actions in WCF-Custom/WebHttpBinding RRS feed

  • Question

  • BizTalk 2013/R2 - I am about to try a custom behavior, so need to use WCF-Custom. 
    First I'm testing with out the behavior. 

    I took my Soap Action header from a WebHttpBinding: 

    <BtsHttpUrlMapping>
        <Operation Name="Dispatch" Method="POST" Url="/shipments" />
        <Operation Name="Tracking" Method="POST" Url="/statuses/query" />
    </BtsHttpUrlMapping>

    and changed to the root: 

    <BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Operation Name="Dispatch" Method="POST" Url="/shipments" />
    <Operation Name="Tracking" Method="POST" Url="/statuses/query" />
    </BtsActionMapping>

    but when I past them in and click the reply button, I go back and see the following value: 

    <BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Operation Name="Dispatch" />
      <Operation Name="Tracking" />
    </BtsActionMapping>

    I'm getting this error, and I think it's because the actions are not there: 

    System.ArgumentNullException: Value cannot be null.
    Parameter name: key
       at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
       at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.InitializeValues(IBaseMessage message)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfTransmitter`2.GetClientFromCache(String spid, IBaseMessage message)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfAsyncBatch`2.BatchWorker(List`1 messages)

    Thanks,
    Neal Walters 

    Update 1 - I just noticed in a sample that you say specify 'ACTION="POST"' instead of 'METHOD="POST"'; but don't see multiple URLs are allowed.  I tried one of the URL suffixes above and putting on the actual URL and see then I got this error: 

    System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
       at System.Xml.XmlTextReaderImpl.Throw(Exception e)
       at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
       at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
       at System.Xml.XmlReader.MoveToContent()
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkBodyWriter.ValidateStreamContainsXml(Stream stream)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfMarshaller.CreateWcfMessage(CreateWcfMessageSettings settings, TLConfig tlConfig, RLConfig rlConfig)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.SendRequestMessage(IBaseMessage bizTalkMessage, IRequestChannel channel)
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.SendMessage(IBaseMessage bizTalkMessage)

    The XML I'm sending works fine in the WebHttpBinding port. I have XMLToJson pipeline on the send. 

    I'm using SecurityMode=Transport and the URL starts with https:






    Monday, April 2, 2018 3:15 PM

All replies

  • So, sorry, it's not too clear why you're doing this.

    The Action Mapping and Url Mapping blobs are totally different.

    The thing is, there's nothing stopping you from adding the Behavior to the WCF-WebHttp Adapter settings.  Just select the Behavior tab and pick it/them.

    Finally, unless it's cranky OAuth, Behaviors aren't usually necessary for REST operations.

    Monday, April 2, 2018 4:22 PM
  • Johns-305 - I mistakenly thought behaviors only worked with WCF-Custom. 

    However, I tried to pick the behavior on my original working WebHttp send port, and it doesn't show in the list.  (Both are using the same Host which has the custom behavior imported.) 

    I'm doing an implementation of this behavior, which had instructions to use WCF-Custom.  I think it will allow me to capture the 400 error messages without leaving the SendPort suspended. 

    http://blogical.se/blogs/mikael/archive/2012/05/28/rest-start-kit-for-biztalk-server.aspx

    A WebHttp send port has "HTTP Method/URL Mapping", and a WCF-Custom send port has "SOAP Action Headers". Is it not possible to do the "HTTP Method/URL Mapping" in the WCF-Custom send port?  Or that would depend on how the behavior is coded? 

    Thanks,
    Neal Walters 



    Monday, April 2, 2018 4:45 PM
  • You don't (or shouldn't ;) need the Rest Starter Kit for BizTalk 2013 and higher.

    The use cases of RSK are new handled by the WCF-WebHttp Adapter itself.

    Monday, April 2, 2018 4:52 PM
  • Okay, so then why does a solicit/response two-way SendPort leave a Suspended message when the orchestration has a scope to catch it?  

    My understanding is that the WCF-WebHttp SendPort sees that as an error, will do retries, etc....

    Here's an example of the error we are getting; it could be caused by data and/or configuration, so we need to catch it and report it properly.  The scope catches it, but for some reason the SendPort is still suspended. 

    A message sent to adapter "WCF-WebHttp" on send port "spP44WebHttp" with URI "https://test.abc.com/api/v3" is suspended. 
     Error details: System.Net.WebException: The remote server returned an unexpected response: (400) Bad Request.
    {"httpStatusCode":400,"httpMessage":"Bad Request","errorMessage":"Unable to handle shipment request","errors":[{"severity":"ERROR","message":"Customer-X does not support these accessorials: AIRPU","source":"SYSTEM"}],"supportReferenceId":"e0117674-9f83-4b42-b861-2e9b9f636323"} 

    Now that I'm reading the code in BLogical, it may not handle this scenario either.  But I think a custom behavior can help, yes or no? 

    Neal 

    P.S. Other research/references: 

    https://stackoverflow.com/questions/31613171/biztalk-catch-http-response-code, which referred to Blogicalhttps://social.technet.microsoft.com/wiki/contents/articles/16625.biztalk-server-rest-services-error-handling.aspx which says ", it looks like the XlangSoapException behavior we observed before is still the same in BizTalk 2013, so initially the same customBinding approach followed with BizTalk 2010 would apply here. "

    Also: https://cdijkgraaf.wordpress.com/2016/08/12/biztalk-2013-r2-known-bugs-issues-quirks/ 

    Details: When you get a non 200 series http status code from a RESTful service using the WCF-WebHttp adapter, the SOAP fault message published to the message box does not have the context property MessageType.  This means you cannot map it or catch it in a Fault on the Logical Port in the Orchestration

    This next point is not really important, but I do see now the probably reason for the XML error described in my "Update 1". The BLogical code does a " var requestBody = XElement.Load(request.GetReaderAtBodyContents());" - and must be converting XML to JSON itself, where as my pipeline had probably already converted XML to JSON before it go there. 

    P.P.S - I have submitted my bottom-line real question here: https://stackoverflow.com/questions/49617062/how-to-prevent-biztalk-2013-r2-wcf-webhttp-rest-senfdport-from-suspending-on-htt.  This thread kind of got off of my original topic.
    Monday, April 2, 2018 5:31 PM
  • Okay, so then why does a solicit/response two-way SendPort leave a Suspended message when the orchestration has a scope to catch it?  

    My understanding is that the WCF-WebHttp SendPort sees that as an error, will do retries, etc....

    Here's an example of the error we are getting; it could be caused by data and/or configuration, so we need to catch it and report it properly.  The scope catches it, but for some reason the SendPort is still suspended. 

    A message sent to adapter "WCF-WebHttp" on send port "spP44WebHttp" with URI "https://test.abc.com/api/v3" is suspended. 
     Error details: System.Net.WebException: The remote server returned an unexpected response: (400) Bad Request.
    {"httpStatusCode":400,"httpMessage":"Bad Request","errorMessage":"Unable to handle shipment request","errors":[{"severity":"ERROR","message":"Customer-X does not support these accessorials: AIRPU","source":"SYSTEM"}],"supportReferenceId":"e0117674-9f83-4b42-b861-2e9b9f636323"} 

    Now that I'm reading the code in BLogical, it may not handle this scenario either.  But I think a custom behavior can help, yes or no? 

    Neal 

    P.S. Other research/references: 

    https://stackoverflow.com/questions/31613171/biztalk-catch-http-response-code, which referred to Blogicalhttps://social.technet.microsoft.com/wiki/contents/articles/16625.biztalk-server-rest-services-error-handling.aspx which says ", it looks like the XlangSoapException behavior we observed before is still the same in BizTalk 2013, so initially the same customBinding approach followed with BizTalk 2010 would apply here. "

    Also: https://cdijkgraaf.wordpress.com/2016/08/12/biztalk-2013-r2-known-bugs-issues-quirks/ 

    Details: When you get a non 200 series http status code from a RESTful service using the WCF-WebHttp adapter, the SOAP fault message published to the message box does not have the context property MessageType.  This means you cannot map it or catch it in a Fault on the Logical Port in the Orchestration

    This next point is not really important, but I do see now the probably reason for the XML error described in my "Update 1". The BLogical code does a " var requestBody = XElement.Load(request.GetReaderAtBodyContents());" - and must be converting XML to JSON itself, where as my pipeline had probably already converted XML to JSON before it go there. 

    P.P.S - I have submitted my bottom-line real question here: https://stackoverflow.com/questions/49617062/how-to-prevent-biztalk-2013-r2-wcf-webhttp-rest-senfdport-from-suspending-on-htt.  This thread kind of got off of my original topic.

    Neal, did you solve your problem? I also have the problem that the response with error 400 (validation error) is treated as a webexception. The message is retried a couple of time by the WCF webhttp sendport and then fails. I can catch error in a Scope with System.Exception handler but the message will remain suspended in the messagebox.
    I would like to receive the Error 400 message which is a JSON message and then save it to inform the caller of the failure.

    Using BizTalk 2016.


    Ralf

    Tuesday, July 14, 2020 10:59 AM
  • We solved this problem by

    1) Catching it in a System.Exception scope in the Orchestration and handling the error there

    2) Switching on Routing for Failed messages on the Send Port and have another send port with a custom NULL adapter that subscribes to all error message from the send port e.g. ErrorReport.SendPortName == SendPortName.  The Null Adapter does what the name implies, it just throws the message away. You can find a NULL Adapter on GitHub.  If you can't install that, just write it to a FILE location and have a cleanup job delete them.




    Wednesday, July 15, 2020 2:52 AM