By default the Xbase++ WebHandler does negotiate the content type encoding automatically. The following simple AddressService returns a Object and leaves the content negotiation up to the WebHandler and the request sending party. The great benefit of that approach is that your service interfaces can be used within your application by calling the method directly (in-process) business-logic as well as remote (out-of-process) web or mobile client application.

Xbase++:
CLASS AddressService FROM WebHandler
  EXPORTED:
  METHOD getAddress()
  METHOD getGreeting()
ENDCLASS

METHOD AddressService:getAddress()
   LOCAL oAddress

   // just create a dataobject with some members
   oAddress := DataObject():new()
   oAddress:ID      := "NU01"
   oAddress:Company := "NCC1701"
   oAddress:Contact := "Nyota Uhura"

RETURN oAddress

METHOD AddressService:getGreeting()
RETURN "Hello from europe: öäü é è!"

Pre-Requsite for the following experiment​

Run the WebHandler, use your own code or the simplified console service shown below.
To send requests use CURL . If you do not use it already we recommend it as an great tool for WebHandler request/response analysis. You can get it from here https://curl.haxx.se/windows/

Xbase++:
#include "inkey.ch"
#include "web.ch"

PROCEDURE Main
  LOCAL oEndpoint

  SET CHARSET TO ANSI

  // Starts http endpoint at port 8023 and binds all classes dervied from WebHandler to
  // that endpoint via the classnames as the servicename and the exported methodname
  // as the interface.
  oEndpoint := HttpEndpoint():new(8023, "*")
  IF( !oEndpoint:start() )
    ErrorLevel(-1)
    RETURN
  ENDIF

  WAIT
  oEndpoint:stop()
RETURN

Content negotiation experiment​

In the following table we are using CURL to send requests to our webhandler. As shown, depending on the Accept-Type of the request the Xbase++ Webhandler does automatically negotiate the content type, serializes objects or arrays into the proper data stream and send it back to the client. Of course, in case of text/html only texts data can be returned since there is no representation of an Object in HTML. However if character data is returned by the method of an webhandler and content type is text/html then HTML encoding is applied automatically as outlined with the :getGreeting() interface.

RequestResponse (italic implies header information)
curl -H "Accept: text/html" http://localhost:8023/AddressService/getAddressContent-type: text/html
DataObject
curl -H "Accept: application/json" http://localhost:8023/AddressService/getAddress Content-Type: application/json
{"ID" :"NU1", "Company" :"NCC1701", "Contact" :"Nyota Uhura"}
curl -H "Accept: application/xml" http://localhost:8023/AddressService/getAddressContent-Type: application/xml
<object classname="DataObject">
<character name="ID">NU1</character>
<character name="Company">NCC1701</character>
<character name="Contact">Nyota Uhura</character>
</object>
curl -H "Accept: text/plain" http://localhost:8023/AddressService/getGreetingContent-type: text/plain *)
Hello from europe: öäü é è!
curl -H "Accept: text/html" http://localhost:8023/AddressService/getGreetingContent-type: text/html
Hello from europe: &#246;&#228;&#252; &#233; &#232;!
*) The content-type is also text/plain in case of a request with Accept-Type: */*

Enforcing a content-type​

To enforce a specific content-type irrespective which accept-type the request was, simple set the accept-type in your WebHandler using the HttpResponse which is a member of your WebHandler instance. Simple add the following code to your :getAddress() method. If you want to change the behavior for all of your interfaces simple overload :execute() and add the folllowing code before you call SUPER.

Xbase++:
// response of this interface is always in json
::HttpRequest:AcceptTypes[1] := "application/json"