4
votes

I am curious what options are available to me to ignore an additional property sent from client-side UI (OpenUI5) to my back-end API (ASP.NET Web API OData v1-3).


Problem

OpenUI5 always sends an additional property along with the request which causes a null parameter (where I'd typically have a Delta<Models.Item> patch), and a BadRequest response of:

{
    "error": {
        "code":"",
        "message":{
            "lang":"en-US","value":"The request is invalid."
        },
        "innererror":{
            "message":"patch : The property '__metadata' does not exist on type 'Models.Item'. Make sure to only use property names that are defined by the type.",
            "type":"",
            "stacktrace":""
        }
    }
}

(Server side) Models/Item.cs

public partial class Application
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
}

My client-side library is sending in an HTTP MERGE with only a few properties that changed, so we're able to use WebAPI's Delta<T>.

I don't get much control over how the request gets sent (see API documentation for OpenUI5 call here). I cannot control the outbound request which looks like this (let's say I only change Property1 and Property2 on my object):

MERGE http://my-api.com/odata/Items(3)

{
    "Property1": "ABC",
    "Property2": "DEF",
    "__metadata": { 
        "id": "http://my-api.com/odata/Items(3)",
        "uri": "http://my-api.com/odata/Items(3)",
        "type": "Models.Item"
    }
}

Which is almost exactly what I'd like sent, with the exception of the __metadata object. I saw a similar post that the proper way (in OData v4) is to allow DynamicProperties (https://stackoverflow.com/a/26312571/569531). However, using UI5, I am currently restricted to v2.


Question

Is it possible to implement a MessageHandler, ModelBinder or alternative to strip the __metadata property before the incoming request -or- during model binding? My only concern is that a MessageHandler will not be able to modify the incoming Request body, and that creating a custom ModelBinder might be tough due to the type used in a MERGE/PATCH request which is a Delta<T>. The ValueProvider implementation might be a struggle, but open to suggestions.

1

1 Answers

1
votes

You could make a new OData model that inherits from the original OData model. And override the _request function.

var MyModel = ODataModel.extend("sap.ui.model.rest.MyModel",{
  constructor : function(sServiceUrl, mParameters) {
    ODataModel.apply(this, arguments);
  }
});
MyModel.prototype._request = function(oRequest, fnSuccess, fnError) {
  if (oRequest.data) {
    if (oRequest.data.__metadata) {
      delete oRequest.data.__metadata;
    }
  }
  return ODataModel.prototype._request.apply(this, [oRequest, fnSuccess, fnError]);
};