Building Windows application on SAP Mobile Platform SDK – Part 2
Update: The code for the sample application and the How To Guide for this series is now published.
In my previous blog, I had talked about the onboarding process to uniquely identify a device with the SMP Server. The next logical progression in this blog series is to write about how devices can retrieve data from the backend and also how devices can make changes to the backend data. As part of this blog, I will try and post code for another sample application that illustrates how to retrieve data and make changes to backend using the SAP Mobile Platform SDK (hereinafter referred to as “SMP SDK” or “SDK”).
CRUD operations
In order to retrieve data from the backend, an HTTP GET request is made along with the application connection id in the headers.
HTTP Request |
---|
URL: http://<hostname>:<port>/<appid>/<CollectionName> Method: GET Header: { X-SMP-APPCID : <app connection id> } |
To accomplish this using the SMP SDK, the following steps need to be taken. Creating an ODataStore instance and calling OpenAsync is only done once for a session. From there on, it’s a matter of calling ScheduleReadEntitySet method any number of times.
The ODataStore library is used to interact with the SMP Server to submit HTTP requests to either GET data or perform CUD operations. An ODataStore instance is required to interact with an OData Service. The ODataStore hides a lot of complexities and makes interacting with OData source fairly easy for the developer. To create an instance of the ODataStore, the developer can use either one of the 2 constructors. The default value for the 2nd EntityFormat parameter is XML format. However, using JSON format considerably reduces the network traffic.
public ODataStore(string serviceUri, ODataStore.EntityFormat entityFormat = ODataStore.EntityFormat.XML);
public ODataStore(Uri serviceUri, ODataStore.EntityFormat entityFormat = ODataStore.EntityFormat.XML);
public enum EntityFormat
{
JSON = 0,
XML = 1,
}
// Sample code snippet for creating an ODataStore
var store = new ODataStore(uri);
Once an instance of ODataStore is created, the method OpenAsync is called. This method retrieves the service document and the metadata document. When making the OpenAsync call, it is also necessary to pass in the user credentials and the application connection id as header values.
var client = new SAP.Net.Http.HttpClient( new System.Net.Http.HttpClientHandler { Credentials = new NetworkCredential(“user", “password") }, true);
client.DefaultRequestHeaders.TryAddWithoutValidation("X-SMP-APPCID",appconnid);
await store.OpenAsync(client);
The ScheduleReadEntitySet method is used to schedule an HTTP GET request. This method takes the collection name as a parameter. The Response object is then called asynchronously to submit the request.
var execution = store.ScheduleReadEntitySet(collectionName);
var response = await execution.Response;
The response object is then cast as an ODataEntitySet and can be immediately bound to an UI control. The ODataEntitySet is an IObservableCollection which allows the UI controls to automatically update themselves when the collection is changed.
var response = await execution.Response;
this.EntitySet = (SAP.Data.OData.Online.ODataEntitySet)((IODataResponseSingle)response).Payload;
// Bind this.EntitySet directly to UI controls
Making changes to the backend
The ScheduleCreateEntity method is used to create an entity in the backend. This method takes an ODataEntity and the CollectionName as parameters. An entity is created locally and passed in as parameter to the ScheduleCreateEntity method.
var entity = new SAP.Data.OData.Online.ODataEntity(“TypeName");
entity.Properties["ID"].Value = XYZ;
entity.Properties["Name"].Value = “<XYZ>";
store.AllocateProperties(entity, SAP.Data.OData.Store.PropertyCreationMode.All);
var execution = store.ScheduleCreateEntity(entity, collectionName);
var response = await execution.Response;
Similarly, the ScheduleUpdateEntity is used to update an entity in the backend. This method takes an ODataEntity as a parameter. It is recommended to use the DeepCopy() method to make a real copy of an entity (not just a reference copy). Make the necessary updates on the temporary ODataEntity. This way, even if the update operation fails (network disconnects, server error or whatever), the original entity is still intact and the app would not be in an inconsistent state.
var copiedEntity = entity.DeepCopy();
copiedEntity.Properties[“Name"].Value = newName;
var execution = store.ScheduleUpdateEntity(copiedEntity);
var response = await execution.Response;
The ScheduleDeleteEntity method is used to delete an entity in the backend.
var execution = store.ScheduleDeleteEntity(entity);
var response = await execution.Response;
Update: The code for the sample application and the How To Guide is now published. The Windows Store Flight Sample Application Series illustrates the various techniques involved in creating an online Windows Store application using the Windows SMP 3.0 SP05 SDK. This sample application series uses the universal Windows app project templates to build apps that can run on Windows Phones, tablets, laptops and workstations.
In conclusion, in this blog I have highlighted some of the important methods involved in performing CRUD operations against an OData Source using the SAP Mobile Platform. This current version of SMP SDK only supports online functionality for Windows. However, future releases of the SMP SDK will support additional functionality. In upcoming blogs, I will talk more about the newer functionality and also provide more code samples to help build Windows applications using the new SAP Mobile Platform SDK. Also, if you have questions building Windows applications, please feel free to reach out to me.
Hi,
great blog, but I can't find the Windows Desktop SDK in SAP App Store?
br
Meex
SAP Mobile Platform SDK SP05 (referred to as "SMP SDK") contains the Windows SDK. If you install SMP SDK in the default location, you will find the Windows SDK in the following folder: C:\SAP\MobileSDK3\NativeSDK\ODataFramework\Windows
The size of the Windows SDK is only about 250 kb. They are packaged as NuGet packages. The .nupkg files contain libraries for both Windows Store and Windows Desktop applications.
ok thx, but where can I download can't find SP05?
You can download it from Service marketplace (http://service.sap.com/swdc).
perfect, thx for your help
Hi, I've some problems creating the Online ODataStore 🙁
May you can provice your complete code snippet?
regards
Meex
The sample application will be published in a couple of days. In the meantime, if you have any questions, contact me. [Removed by Moderator]
Hi Milton,
I have another question 🙂
As EntitySet is a dynamic data structure, is it possible to use LINQ to query against a returned entityset? We want to load the data once from backend to our app, and then the user should have the possibility to search the EntitySet?
regards
Meex
ok found it myself 🙂
var entities = from entity in EntitySet
where ((string)entity.Properties["Description"].Value).Contains("Test")
select entity;
Meex
// LINQ extension method using the lambda style
var filteredEntitySet = entitySet.Where(e => ((string)e.Properties["Address/State"].Value) == "WA");
// LINQ extension method using the SQL style
var filteredEntitySet = from e in entitySet
where ((string)e.Properties["Address/State"].Value) == "WA"
select e;
foreach (var e in filteredEntitySet)
{
Console.WriteLine(e.Properties["Name"].Value);
}
is there a way to transform ODataEntity to XML or JSON? I want to serialize the object so ein can store data in as BLOB in sqlite DB?
regards
Meex
var execution = Store.ScheduleReadEntitySet(collectionName);
IODataResponse response = await execution.Response;
string json = JsonConvert.SerializeObject(((IODataResponseSingle)response).Payload);
You can add the Newtonsoft.Json nuget package and use the code above to serialize the object as JSON.
Hi Milton,
thx for your answer! Serialize works, but I have a problem deserializing the json to a entity set? Is there hint?
regards
Meex
Was there an SDK change from SP5 to SP6 that would cause problems wtih the sample?
ODataContext.DownloadRelatedItems breaks when trying to use the navigationProperty.AssociationResourcePath. That value is a mangled URI that ScheduleRequest fails on.
We worked around that by extracting the CarrierCollection("airlinecode")/carrierFlights from the URI and passing it in as the resourcePath instead of the mangled URI.
Beyond that, we have problems booking flights and haven't figured out a work around yet.
It should work fine. What error are you getting when trying to use the navigationProperty.AssociationResourcePath ? Is it implemented in the backend OData source ?
Also, does your metadata document have a navigation property named carrierFlights ?
Your workaround should also work. Your approach requires prior knowledge of the relationship between the tables, whereas the approach above queries for the relationship and figures out the related table.
The value I get for navigationProperty.AssociationResourcePath is:
https://sapes1.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT/CarrierCollection('AA')/carrierFlights
I haven't try running this against SP5 of the SDK, but this is the value I get against SP6 of SMP 3.0 SDK.
Regarding the metadata document, where does this reside?
Hi, for CRUD operations you need to send a X-CSRF-TOKEN, I've tried this, but I still get a 403 satus. Maybe you can provide an example?
kind regards
Meex
ok, found it 🙂
There's a parameter you can set => client.ShouldHandleXcsrfToken = true
Hi Milton,
would it be possible to provide an example for a Deep Create / Deep Insert with the SDK?
best regards
Meex
Hi Milton,
could you please explain how to get a specific entity? For example I have a flight with an id == 3 and want only this on entity.
Regards,
Hendrik
public async Task ReadEntity(string resourcePath)
{
var execution = Store.ScheduleReadEntity(resourcePath);
IODataResponse response = await execution.Response;
this.Entity = (SAP.Data.OData.Online.ODataEntity)((IODataResponseSingle)response).Payload;
}
await ReadEntity("Suppliers(3)");
Hi Milton,
Currently I am building an online windows application that will be deployed on an Intermec device with OS version "Windows Embeded handhled 6.5 classic, CE OS 5.2.29040". can I use online oData SDK for communicating with SAP?
Regards,
Maged
Hi Milton,
How to create a Entity set with json string?
I tried in below way but its throwing a error message while adding the data as Object reference not found.
Dictionary<string, IODataNavigationProperty> navigationProperties = new Dictionary<string, IODataNavigationProperty>();
Dictionary<IODataAnnotationName, string> annotations = new Dictionary<IODataAnnotationName, string>();
ODataEntity odataEntity = new ODataEntity("EntityType", navigationProperties, annotations);
odataEntity.Properties[key].Value = "SAP";