Featured post

ABAP help is only an email away!

Do you need ABAP help ASAP?  Are you working on a computer problem you can’t solve?  Let me know what your ABAP problem is and I will let you know if I can help. Fill out the form to the right and I will get back to you as soon as I can. I will put your question on the website and if we solve the problem, I will put the answer here as well to help others.

Consuming an SAP Odata Service with C#

Consuming an SAP Odata service with C# is is fairly simple to do. There are several different ways to do that. In this example, I will use base C# classes to retrieve the data and then use a C# library named JSON.Net to parse the data. I’ve written a short example here of how to return back the data.  For my SAP system, I am using an SAP instance I have installed locally which supports the NetWeaver Gateway.

The instance of SAP ships with some sample applications including the old favorite Flight application.  The NetWeaver Gateway will supply us back application data through our web browser. We can browse the types of data that can be returned for this example using this url substituting in your server name and appropriate port below:

http://<server name here>:8042/sap/opu/sdata/iwfnd/RMTSAMPLEFLIGHT/

That will yield the following result:

As you can see there are several object collections available related to the sample flight data. Here is the url we will be working with for this example:

http://nplhost:8042/sap/opu/odata/IWBEP/RMTSAMPLEFLIGHT_2/CarrierCollection?$format=json&$top=5

On my system this returns the following information in JSON format and with the parameter 5 in the url above, this returns a list of 5 carriers.

Next we have to take these results and put them into a format that we can use in C#.  We could use the Microsoft JSON related libraries to parse the data but I chose to use JSON.Net which is a popular .NET library for working with JSON data. You can find JSON.net  here http://www.newtonsoft.com/json.

JSON.Net lets you deserialize JSON data. When you deserialize it using JSON.Net, the library maps the field values it finds by name into object classes that you create in C#. For this example above we have an airline carrier so I needed to create an airline carrier class.

Here is the class that will map out the carrier details. If you look at the details of this class, it matches the format of the JSON data that is displayed above.  The key class here is the CarrierCollectionD class. You can see it contains a List of CarrierCollectionResults. That is our collection of return values that we would need to iterate through.

Now, onto proceeding to getting this data. For that we will use a basic WebClient from C#. There are several ways you can request the data. WebClient is fairly simple because it provides the DownloadString method which downloads all of the JSON data into a single string you can store in a variable.

I then take that data and then create a simple C# DataTable instance to store the data. I just did this so I could show some code on how to map out the results to the class I created earlier.

When I run this program then, I get the following result when I inspect the DataTable that has been created.

consuming-odata-service-carriers

Going forward I am going to explore other methods of retrieving this data. SAP offers UI5 to also allow you to retrieve the OData data but sometimes you like to use other tools to get the data, hence this article. Happy coding!

I would like to give this author credit – http://scn.sap.com/community/mobile/blog/2013/04/15/parsing-json-from-netweaver-gateway-on-windows-mobile-c because without his post, I would not have been able to do this work that I have here.

Creating an OData Service with SAP

Creating an OData service with SAP is not complicated. The first step is to determine what data you want to work with. That is based on your application. For our purposes, we will use the sample data that is included with SAP.  This is the airport related data. If you do not have this data in your system, then please follow the tutorial located at http://help.sap.com/saphelp_erp60_sp/helpdata/en/db/7c623cf568896be10000000a11405a/content.htm.  The main way to get this data into your system is to run t-code SAPBC_DATA_GENERATOR.  It may be useful to you as well to review the Flight data model while you are designing your application. You can find the data model at https://help.sap.com/saphelp_nw70/helpdata/en/cf/21f304446011d189700000e8322d00/content.htm.

In short, here are a list of the main tables in the Flight data model:

T000 – Client table
SCURX –  Currencies (key: currency key)
SBUSPART – Business partner (key: client, partner number)
STRAVELAG – Travel agencies (key: client, travel agency number)
SCUSTOM – Customers (key: client, customer number)
SCARR – Carriers (key: client, carrier ID)
SCOUNTER – Sales counters (key: client, carrier ID, sales counter number)
SPFLI – Flight schedule (key: client, carrier ID, connection number)
SFLIGHT – Flights (key: client, carrier ID, connection number, date of flight)
SBOOK – Flight bookings (key: client, carrier ID, connection number, date of flight, booking number, customer number)

Let’s consider the customers table (SCUSTOM).

customers-screenshot

In this table we have basic data such as customer id, name, title and address information. This is a simple and straightforward set of data.

We then need to model this data. This is done through using t-code – SEGW. If you run it for the first time, it will take a moment to compile. You are then presented with the SAP NetWeaver Gateway Service Builder.

netweaver-service-gateway-builder

Click the new button to create a new project. Before creating this I created a package called ‘ZODATA’ that I could use to assign this project to. You can create a new package using SE80. Then you should see a screen like this when you are done creating your package.

gateway-service-overview

Here is where we will model our data using different modeling types. Next, click on Data Model > Import from DDIC structure.  Once you go through the setup, you will see this screen. That was super easy, wasn’t it.

odata-scustom-data-model

Next, then you have to create an entity set representing your customers object. You do this under the EntitySet area below. Your screen should look like this:

odata-customers-entity-set

Next, we are going to generate runtime objcts for our application. This action creates the code that runs behind the scenes. Right click on the project at the top and choose “Generate Runtime”.

generate-entity-set

After generating the runtime you will see this screen:

odata-generate-runtime

Hopefully this is all starting to make sense at this point. The system is modeling the data and then also generating the classes to handle the mapping of the data and updating as well. This is similar to what .Net does through some of its wizards. If all goes well after you pick your package, you will see the following:

odata-runtime-success

That will provide the basic architecture for the underlying service. However, in order to tie it all together, we need to update the generated classes that were created. We need to modify the ZCL_ZODATADEMO_DCP_EXT class. Using the runtime generator saves a lot of coding time but it doesn’t completely eliminate it in all circumstances. Just take a look at all of the methods that were generated in this class:

odata-generated-class

There were a ton more that I did not list. It makes it a bit easier if we just look at the methods on the object through this navigation:

odata-entity-methods

So now looking into these methods, if we pick the first one, CUSTOMERSET_CREATE_ENTITY, we can see it doesn’t have an implementation yet.

 

odata-customer-entity-not-implemented

We now have to implement the code to handle this. We do that with the following code:

Then let’s change the get entity method:

We won’t be able to see this service until we register the service. We do this with the t-code /IWFND/MAINT_SERVICE. When you run this, choose the system alias of ‘LOCAL’. I had to do that to get my service to show. Once you do, you will see this screen:

odata-service-register-screen

Next, click on the service and then you will see the following screen:

odata-service-register-screen

You will see the following screen:

odata-add-service-confirmation

Then we are pretty much done. Then if we go back to /IWFND/MAINT_SERVICE we can see our service listed at the bottom:

odata-service-success

And now we are ready to test the service. We can do that by going to this url: http://<server>:<port>/sap/opu/odata/sap/ZODATADEMO_SRV/?sap-client=001&$format=json.

Appending tables with ABAP

Today’s tip is how to append tables with ABAP. This is simple to do and all it takes is just a simple modification to the INSERTING INTO TABLE syntax.

And that’s all you do to append records into an existing table when you do a select. Just remember, “APPENDING” is the key word but if you do this step, you should look for duplicates as well.

Convert Internal Table to HTML

I had one request where I had to convert an internal table into HTML so that I could stream it to the client’s computer as an Excel download. There are various ways of doing this such as converting the file into a CSV file but the user wanted to have HTML.

So, the way to accomplish this is to use the following code:

 

ABAP Prompt User with Yes or No Dialog

There are several choices to do dialogs in ABAP. Here, I will be doing a simple Yes or No Dialog Box using the function POPUP_TO_CONFIRM. Confirmation dialog boxes are frequently needed in programs. You can control program flow with dialog boxes and it’s also a very nice way to communicate with your user what your program is doing.

There are other options you can add to the dialog prompt as well. I did not include all of the options below. However, if you go into T-code SE37, you can review some of the options the function can take. Here is the sample program that I wrote.

Then if you run the program, you will see the following user prompt dialog:

ABAP User Prompt Yes or No

And that’s how easy it is to create a user prompt. When you have the result of the user’s input, it is stored as an integer in their Yes or No response. In this example, “1” corresponds to a “Yes” and “2” corresponds to a “No”.  This can be a simple driver to your program. Please note the sy-subrc check which is performed after the function check to display the user response.