Hello,
I have web service REST api with OData support developed in .Net Core 6/7. The entity models are a base type and several derived types. To simplify, lets assume that the base type is Shape and the derived types are Circle and Rectangle.
According to the .Net Core specification, we can use same controller from base type with specific actions to perform CRUD operation on the derived types. The routing template for derived types in our example should be:
GET PUT PATCH DELETE |
~/{entityset}({key})/{cast}
|
~/Shape(1)/Circle ~/Shape(1)/Rectangle |
The controller contains all actions, all entities are registered in EDM model and all Odata endpoints are correctly registered. I test the web service with postman and it is working fine.
On the front end i am displaying data (Shapes) in Grid. For dataSource of the grid component i am using DataManager and ODataV4Adaptor:
[html file]
<ejs-grid #grid [dataSource]="data" [editSettings]="editSettings" [toolbar]="toolbar" width="100%" (actionBegin) = "onActionBegin($event)"(actionComplete)="onActionComplete($event)">
...
[ts file]
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' }; this.toolbar = ['Add', 'Edit', 'Delete'];
this.data = new DataManager({ url: "odata/Shapes", adaptor: new ODataAdaptor()});
In the dialog for editing data, i am displaying different forms based on the entity type (odata provides the type in 'odata.type' property). So, i know the type of the current data that I am editing (or I can chose from combo when i am adding new data).
In actionBegin handler, when user click on Save button from the edit dialog (args.requestType === 'save'), I am updating the 'updateUrl' from DataSource based on the data type. For example, if editing data is from type Circle i am setting the 'updateUrl' to 'odata/Shape/Circle’. But the problem is that DataManager sets the key in the last path from the updateUrl and send PATCH request with url 'odata/Shape/Circle(1)'. The correct url should be 'odata/Shape(1)/Circle'.
So, is it possible somehow (in DataSource setting, Addapter Settings, ... ) to add type of the entity (Circle or Rectangle) at the end of the url in PATCH / PUT request i.e. to send PATCH request to url 'odata/Shape(1)/Circle?
Hi Marijke Meersman,
Thanks for contacting Syncfusion support.
You can achieve your requirement by using the “Custom Adaptor” feature which provides an option to override the default Adaptor functions and customize the URL. Please refer to the below code example and documentation link for more information.
class CustomAdaptor extends ODataAdaptor { processQuery(): Object { // Executing base class processQuery function var original = super.processQuery.apply(this, arguments); // Request URL is customized var charIndex = original.url.indexOf('?'); original.url = “changing URL”; alert('Customized request URL - ' + original.url); return original;
} |
https://helpej2.syncfusion.com/angular/documentation/grid/data-binding/remote-data#custom-adaptor
Regards,
Pavithra S
Hello Pavithra,
Thanks for the feedback, but "processQuery" method is not call during adding or updating data.
The solution that works for me was to override "insert" and "update" methods:
private updateRequestCustomData (request: Object, data: Object): void {
// Update request with support for OData inheritance CRUD.
if (this.customRemoteOptions != undefined &&
(this.customRemoteOptions.supportODataInheritance ?? false) &&
data.hasOwnProperty("@odata.type")) {
// Add the data type at the end of the url.
// Note: in .Net core Odata V8, the value of property "@odata.type" had leading "#" which should be removed!
if (((data as any)["@odata.type"] as string).startsWith("#")) {
(request as any)["url"] = (request as any)["url"] + "/" + ((data as any)["@odata.type"] as string).substring(1);
}
else {
(request as any)["url"] = (request as any)["url"] + "/" + ((data as any)["@odata.type"] as string);
}
}
}
/**
* Prepare and returns request body which is used to insert a new record in the table.
* @param {DataManager}dm
* @param {Object}data
* @param {string}tableName?
*/
override insert(dm: DataManager, data: Object, tableName?: string): Object
{
// Generate original insert request.
var originalRequest = super.insert(dm, data, tableName);
// Update request with custom data.
this.updateRequestCustomData(originalRequest, data);
return originalRequest;
}
/**
* Prepare and return request body which is used to update record.
* @param {DataManager}dm
* @param {string}keyField
* @param {Object}value
* @param {string}tableName
*/
override update(dm: DataManager, keyField: string, value: Object, tableName: string, query: Query): Object
{
var originalRequest = super.update(dm, keyField, value, tableName, query);
// Update request with custom data.
this.updateRequestCustomData(originalRequest, value);
return originalRequest;
}
Thanks for direction.
Regards,
T.M.
Trajche Manolev,
Thanks for the update.
We are glad to hear that you have managed to achieve your requirement. Please get back to us if you need any assistance.