SAP / openui5

OpenUI5 lets you build enterprise-ready web applications, responsive to all devices, running on almost any browser of your choice.
http://openui5.org
Apache License 2.0
2.95k stars 1.24k forks source link

JQuery Bug 878/1799 within JSONModel.loadData prevents from sending "??" #4064

Closed andy2018w closed 3 months ago

andy2018w commented 3 months ago

Hi :)

OpenUI5 version: 1.71 (the version which we are using) - current version

Browser/version (+device/version): Chrome 125.0.6422.141 / Windows 10

URL (minimal example if possible): https://jsfiddle.net/4ybLwjd1/

Steps to reproduce the problem:

  1. Open Dev Console - Network Tab
  2. Run the example and click the button

What is the expected result? POST-Request with following Payload: {"comment":"ui5 bug with following double question mark ??"}

What happens instead? POST-Request with following Payload: {"comment":"ui5 bug with following double question mark jQuery36009893453989128844_1718181516803"}

Any other information? (attach screenshot if possible) https://github.com/jquery/api.jquery.com/issues/878 https://github.com/jquery/api.jquery.com/pull/1005 https://github.com/jquery/jquery/issues/1799 https://github.com/jquery/jquery/pull/4754 https://stackoverflow.com/questions/17532018/submitting-jquery-ajax-data-with-string-containing-it-changes-value-to-jq image

Workaround of jQuery is not possible because the parameter contentType of this._ajax cannot be set from JSONModel.loadData method: image

Thanks in advance :)

TeodorTaushanov commented 3 months ago

Hello,

Thank you for sharing this finding. I've created an internal incident DINC0180763. The status of the issue will be updated here in GitHub.

Regards, Teo

SvBe commented 3 months ago

Hello, I had a look at your sample. In the sample you are using JSONModel.loadData with a JSON stringified Object as payload/parameter. If you have a look at the documentation https://sapui5.hana.ondemand.com/#/api/sap.ui.model.json.JSONModel%23methods/loadData then you can see following description of the second parameter: "A map or string that is sent to the server with the request. If the value of this parameter is a string, it must already be url-encoded...." If you url-encode that parameter value then the replacement as you mentioned does not happen. Regards, Sven

andy2018w commented 3 months ago

Hi @SvBe ,

thanks for your answer. How can I send the JSON object as a payload of the POST request? URL encoding results in a json string which must be decoded by server side before unmarshalling.

I tried:

  var oHeader = {"Content-Type": "application/json;charset=utf-8"};
  oJSONModel.loadData("https://posttestserver.dev/p/ui5-post-ajax-error/post", 
                      encodeURIComponent(JSON.stringify({comment: "ui5 bug with following double question mark ??"})), 
                      true, 
                      "POST", 
                      false, 
                      false, 
                      oHeader);

and

  var oHeader = {"Content-Type": "application/json;charset=utf-8"};
  oJSONModel.loadData("https://posttestserver.dev/p/ui5-post-ajax-error/post", 
                      {comment: "ui5 bug with following double question mark ??"}, 
                      true, 
                      "POST", 
                      false, 
                      false, 
                      oHeader);

-> resulting payload: %7B%22comment%22%3A%22ui5%20bug%20with%20following%20double%20question%20mark%20%3F%3F%22%7D

I want a plain json payload like this: {comment: "ui5 bug with following double question mark ??"}

Using a unencoded String (with the jquery bug) seems to be the only option or am I missing something?

Thanks in advance Andy

SvBe commented 3 months ago

Hi Andy, the JSONModel#loadData API is not intended to be used as POST with payload data. It is intended to get the initial JSON data for the model. Usually a GET is used and additional parameters can be given, that they are appended to the URL. So they have to be URL encoded. If they shall not appear in the URL you can use a POST method. Then the parameters are added to the body but they still have to be URL encoded. I think the scenario you want to get is not possible with the current implementation of JSONModel#loadData. So I assume you have to use for example the fetch API or the jQuery.ajax API directly. Best Regards, Sven

andy2018w commented 3 months ago

Hi Sven,

I double checked the API documentation and you are right. But I have a little trouble with the documentation:

loadData: "Load JSON-encoded data from the server using a GET HTTP request and store the resulting JSON data in the model." vs sType? "The type of request to make ("POST" or "GET"), default is "GET". Note: Other HTTP request methods, such as PUT and DELETE, can also be used here, but they are not supported by all browsers." vs oParameters? "A map or string that is sent to the server with the request. If the value of this parameter is a string, it must already be url-encoded. If the value of this parameter is an object (map), it is converted to a string and then url-encoded. The resulting string is appended to the URL if the HTTP request method cannot have a request body, e.g. for a GET request. Otherwise, the resulting string is added to the request body."

This last part is really unusual IMHO. POST requests are used to send a JSON payload in the request body, not a URL encoded string in (!) the request body. It is also uncommon to use query parameters with POST. However, it's quite common to use POST to retrieve JSON data when the query parameters would be too large or complex. For example, a search API. Or a store API with a processing result. Is there no way to POST and receive JSON with the UI5 API? Using the jQuery.ajax API directly would result in missing some UI5 features like loading splash (busy dialog) if the request takes some time. BTW, sending JSON strings works except for the jQuery bug mentioned above. With the existing workaround (from jQuery) it would be very easy to fix the jQuery bug and support sending JSON via POST. It's just a one-liner (?) and an update to the API documentation. I can provide a merge request if you like?

Thanks again in advance for your time. Best regards Andy

SvBe commented 3 months ago

Hello Andy, We prepared a fix for this issue in the latest snapshot version. We are just downporting the fix to 1.71. The usage of JSONP is outdated and we decided to disable this "feature" for our JSON model as we do not want that JSONP is used by mistake. With that you are able to use POST requests to load the JSON data that have a JSON stringified body and for which the automatic replacement of ?? does not happen any more. We also improved the JSDoc. Best Regards, Sven

andy2018w commented 3 months ago

Hi Sven,

sounds great. Thank you. Andy