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.96k stars 1.24k forks source link

Side effects on media types (image/png) in fiori elements v4 are not working as expected #3530

Closed xpr0gamers closed 2 years ago

xpr0gamers commented 2 years ago

OpenUI5 version: 1.102.1

Steps to reproduce the problem:

  1. create a table/object page view for one entity with fiori elements v4
  2. show a field from type Media on the object page (with annotations)
  3. create an bounded action with side effects for this media type field
  4. implement this action and change the media file
  5. after executing this action by clicking the button on the frontend, a incorrect get request for the field is performed
  6. the media file of type image is not refreshed in the frontend
  7. after refreshing the page, the new meda file is displayed

What is the expected result? The frontent shoud show the new saved media file after the side requests are excecuted.

image image image https://user-images.githubusercontent.com/25172624/172723694-d23a3554-c370-4d60-8246-3d1aabd97aca.mp4

ThomasChadzelek commented 2 years ago

Hello @xpr0gamers !

When you say "a incorrect get request for the field is performed", do you refer to the last screenshot? What exactly is wrong with that GET from your point of view? Isn't GETting "mImage" and "sAbkuerzung" exactly what the side effect tells us to do? Note that "in" refers to the action's binding parameter and does not appear in $select.

Best regards, Thomas

xpr0gamers commented 2 years ago

Hello Thomas,

yes, a get request on "mImage" is correct and exactly what the side effects tells us. But i think, the way, how this get request is sent, is not correct. In this specific use case, "mImage" is from type binary and is annotaed with media type "image/png". The GET request is send with the header "Accept: application/json". But the server cannot send back files in json format. In my opinion, requesting side effects on fields from type binary are not possible inside batch requests and must be done separately with the orginal get request.

You can also see this incorrect data request on the ui. The image on the ui is not refreshing, even though, a get request for this property is sent.

The orginal GET request for this property is: http://localhost:4004/dienstarten-srv/Dienstarten(sId=b964b9ba-ee4e-4641-a40d-0810f5a33a86,IsActiveEntity=true)/mImage Accept: image/avif,image/webp,image/apng,image/svg+xml,image/,/*;q=0.8

ThomasChadzelek commented 2 years ago

Hello Maxi!

I would say, this is a misunderstanding. Of course, the GET for mImage will typically not return the image's content. Still, that GET is useful and even required to fetch the new property annotations like "mImage@odata.mediaContentType" etc.

_When you say "the media file of type image is not refreshed in the frontend", this reminds me of a fix we did quite recently: [INTERNAL] sap.ui.model.odata.v4.lib._Cache#drillDown: allow late property requests for instance annotations_

-Can you show us the result of that GET, please?- OK, I could spot it in the video now.

--> I think I now get what you mean. You display that image on the UI and though its content changes, the image is not updated. This is currently not triggered by that side effect and might indeed be called a bug. To better understand that, can you please share the part of your XML view which displays the image? I would like to see the binding.

Best regards, Thomas

xpr0gamers commented 2 years ago

Hello Thomas,

thank you for your quick reply.

My specifiy application is the following: -on the UI i have a button which executes an odata action when it's pressed -on the backend, i create/generate dynamically an image and store it in the database -this stored image should be shown on the UI (at the moment, this is not working, because requesting the side effects are not working as expected)

The UI is builded by fiori elements v4 with these annotations:

 FieldGroup #General : {Data : [
            {Value : sTitel},
            {Value : sAbkuerzung},
            {Value : mImage},
            {
                $Type  : 'UI.DataFieldForAction',
                Label  : 'dummy test',
                Action : 'maxit.solutions.medicare.srv.DienstartenService.generateSymbol',
            }
]}

Best regards, Maxi

uhlmannm commented 2 years ago

We will track this internally as CPOUI5ODATAV4-1628.

1110101 commented 2 years ago

Hello Maxi,

we worked on your issue and came up with https://github.com/SAP/openui5/commit/efafe50bb4442b515ef6faac8b03ab634f87a764 for it, but we do not recommend to actually using it.

It is now possible to use requestSideEffects for a Picture property and getting the “new value” of it. As Thomas already pointed out, the answer will not return the image’s content but an URL where the image is located.

The issue here is, the URL will remain unchanged. That is an issue in several layers. First of all, the ManagedObject of UI5 will check whether the new content is different from the old. That is not fulfilled if the URL remains unchanged. We have not addressed this, as the second point of caching in the browser also needs to be considered.

Images are typically cached in the browser to avoid unnecessary network traffic. If the URL does not change, the browser will not request the image with the same URL from the server because it has this image already in the local cache.

There is no way for a web application to overcome the caching mechanism of a browser WITHOUT changing or modifying the image URL. If you do not modify the URL (and the server does not use “Cache-Control: no-cache”) it will be always loaded from cache.

A client-side solution could be to append a custom parameter to the URL. This could be done by using a formatter on the image binding to append an artificial parameter to the URL:

<Image src="{path: 'YourPicture', formatter:'.myFormatter }"></Image>

myFormatter: function(oValue) {
     return oValue + "?time=" + +new Date();
}

The big disadvantage is that you will lose all caching of the image, as the URL changes on each application start and never stays the same. The formatter will not only run after a refresh, but also every time the control/binding is loaded.

However, even if the image could be changed in an application, it is displayed more often than changed. Hence, we recommend a different solution that keeps caching in the browser functional. The stream property may come with an odata.mediaReadLink, see http://docs.oasis-open.org/odata/odata-json-format/v4.0/errata03/os/odata-json-format-v4.0-errata03-os-complete.html#_Toc453766638. The server may append a cache token to the URL provided in the mediaReadLink to change the URL when the content of the picture changes. This way caching in the browser and reloading after uploading a new picture both work.

Best regards, Oliwer