Skip to Content
Technical Articles
Author's profile photo Maria Trinidad MARTINEZ GEA

How to consume Service Layer oData services from .NET via WCF

In this blog I’ll like to show you how to consume SAP Business One Service Layer oData sevices from a .NET application via WCF.

SAP Business One Service Layer is a new generation of extension API for consuming SAP Business One data and services. It builds on core protocols such as HTTP and OData, and provides a uniform way to expose full-featured business objects on top of a highly scalable and high-availability Web server. Currently, Service Layer supports OData version3, version 4, and a few selected OData client libraries, for example, WCF for .Net developers; data.js for JavaScript developers.

After installing SAP Business One Service Layer in your server (installed as part of the SAP Business One server components in the HANA Linux server) all documentation is available at the following link:

https://your_hana_server:50000 (your_hana_server is the name or IP of your HANA server)

Please also check the different documents and samples available in the main SAP Business One, version for SAP HANA Extensibility topics (http://scn.sap.com/docs/DOC-60454).

Development Environment

  1. Odata protocol version 3 is the highest version supported by WCF.
  2. You can choose to work with VS 2010, 2012 or 2013 for your daily work.
  3. As precondition, you need to get “WCF Data Services 5.6.0 Tools” installed in advance. You can get the installer from:
    http://www.microsoft.com/en-us/download/confirmation.aspx?id=39373.
  4. Next section explains  how to consume Odata Services via WCF.
  5. You can use Json.Net [NewtonSoft.Json.Net.dll] library for object serialization.
  6. Service Layer server needs to be configured with the following properties in the file b1s.conf (located in the Service Layer installation folder ServiceLayer/conf):
    1. “MetadataWithoutSession”: true  (not required anymore, see following steps)
    2. “WCFCompatible”:true

After changing the configuration file you need to restart Service Layer by running the following command in /etc/init.d folder:
./b1s restart

How to consume Service Layer odata service via WCF

 Add the metadata as service or file directly by selecting “Add Service Reference” into your C#/.NET based Microsoft Visual Studio project, the metadata will be validated automatically.

Note: You have two options:

  1. Open a session with Service Layer before with the Login POST command, for example via PostMan or any other tool.Send a $metadata GET request with the B1S-WCFCompatible header property set to true.

Save the metadata response into an xml file.

Point to the metadata xml file from Microsoft Visual Studio Add Service Reference window:

2. Directly put the $metadata link into the Add Service Reference window (without opening a session before).

You will be prompted to enter a User name and a Password:

As there is no input for company name in WCF, the username and company must be combined as a User name.

User name: {“CompanyDB”: “SBODEMOUS”, “UserName”: “manager”}
Password: your user password

 

Microsoft Visua Studio IDE will use a tool named “SvcUtil.exe” to validate the metadata XML and generate proxy class for your usage automatically if validate passed. You can find all classes in “ObjectBrowser”.

 

SL_ObjectBrowser.png

 

With the automatically generated proxy classes, you can program the required business logic of your application.

 

Sample Code

You can download a .NET sample code connecting to SAP Business One version for SAP HANA Service Layer and doing some operations like:

– Login/Logout

– Retreive the list of Business Partners and Items

– Add a Sales Order Document

– Update a Sales Order Document

– Get a specific Sales Order Document

– Close a Sales Order Document

– Get information via query filters to reduce the amount of data to be retrieved (for example not all fields but only CardCode, CardName fields required but the UI) to improve performances

– Send several queries via Batch in only one request

– Use pagination to retrieve all Orders page by page (user will not be able to see all pages at once and performances will be better if you retrieve page by page).

With this sample you will see how easy is to consume Service Layer Entities (what we are using to call objects in COM interface) and Actions (somehow equivalent to the DI API Services) by getting directly your hands in real .NET C# code.

Please use our standard SDK forum for questions/remarks on the SAP Business One version for SAP HANA Service Layer.

DOWNLOAD IT FROM HERE

Enjoy it!

Assigned Tags

      53 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo David Metser
      David Metser

      We are aawre of the broken link and working on a solution

      Author's profile photo Rahul Jain
      Rahul Jain

      Hello Sir,

      I am getting the below error, when I am adding the service reference in my c# windows application. Please look @ this & let me know the appropriate solution.

       

      Author's profile photo Former Member
      Former Member

      I am having the same problem. How do i add a reference to an OData service. Here are the first few lines of $metadata. Is there a version problem that Visual Studio does not understand.

      Please help SAP!

       

      <edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
      <edmx:DataServices m:DataServiceVersion="2.0">
      <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="HCM_LEAVE_REQ_CREATE_SRV" xml:lang="en" sap:schema-version="1">
      <EntityType Name="AbsenceType" sap:content-version="1">
      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      You activated the WCFCompatible flag on your Service Layer as indicated in the blog and restarted Service Layer afterwards?

      Author's profile photo Rahul Jain
      Rahul Jain

      Yes, We have done it but still no access. Maria Trinidad MARTINEZ GEA can u pls help here on the.

      Author's profile photo Former Member
      Former Member

      Hi,

      Must be install WCF Data Services 5.6.0 RTM Tools Installer, copy link:

      https://www.microsoft.com/en-us/download/confirmation.aspx?id=39373

       

      Best Regards

      Author's profile photo Rahul Jain
      Rahul Jain

      Link not working.

      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      Hi Tanakorn,

      Your question is not directly related to that blog but in general to B1 behavior on DocEntry numbering.

      Can you please post this question on the community forum? I'll remove it from here in the coming days.

      Regards,
      Trinidad.

      Author's profile photo Tanakorn Sippatat
      Tanakorn Sippatat

       

      To Maria Trinidad MARTINEZ GEA

      Thank you.

       

      Best regards,

      Tanakorn

       

      Author's profile photo R. Pol
      R. Pol

      Hi Maria,

      I have downloaded your application and a system administrator has done the settings for point 6. under Development Environment.

      When i start the application, i can Login, Load Initial Data, Add New Order and Get Order. So i assume all my settings are correct!?

      However, when i do Get Order Pages, i get the following error (twice):
      A null value was found for the property named 'SystemSerialNumber', which has the expected type 'Edm.Int32[Nullable=False]'. The expected type 'Edm.Int32[Nullable=False]' does not allow null values.

      When i check REFDI.chm to see what field corresponds with 'SystemSerialNumber', it is 'SysSerial'. When i check the database which tables contain this field, i find 3 tables (‘SRI1_LINK’, ‘OSRI’ and ‘SRI1’). When i check these tables, there are no entries with 'SysSerial' is null!?

      I am using SAP B1 9.2 PL 8 and Visual Studio 2015.

      Question 1: Any idea what might be wrong?

      Also, i notice that you are using 2 methods to get data.

      1) An actual service call to login

      Uri login = new Uri("https://<server ip>:50000/b1s/v1/" + "Login");
      BodyOperationParameter[] body = new BodyOperationParameter[3];
      body[0] = new BodyOperationParameter("UserName", cred.UserName);
      body[1] = new BodyOperationParameter("Password", cred.Password);
      body[2] = new BodyOperationParameter("CompanyDB", cred.CompanyDB);
      session = (B1Session)currentServiceContainer.Execute<B1Session>(login, "POST", true, body).SingleOrDefault();

      2) Through the Service Layer object

      BusinessPartner bp = currentServiceContainer.BusinessPartners.Where(cursor => cursor.CardCode == cardCode).SingleOrDefault();

      Question 2 intro:
      I want to get Company Details.

      When i check the Service Layer Object (method 2), it does not contain a definition for AdminInfo. Therefor i need to use method 1.

      I want to get ADM1.Street and such, but from what i can tell i need to use /b1s/v1/CompanyService_GetAdminInfo and than extract the individual address field values from the 'Address' field...

      When i add the following code, i get an error:

      var admin = new Uri("https://<server ip>:50000/b1s/v1/" + "CompanyService_GetAdminInfo");
      var adminInfo = currentServiceContainer.Execute<AdminInfo>(admin, "POST", true).SingleOrDefault();

      InnerException: {"The response payload is a not a valid response payload. Please make sure that the top level element is a valid Atom or JSON element or belongs to 'http://schemas.microsoft.com/ado/2007/08/dataservices' namespace."}

      When i do the same call using Postman, i do get a valid response...

      Then i think to myself, ok, lets try with a BusinessPartner:

      var bp = new Uri("https://<server ip>:50000/b1s/v1/" + "BusinessPartners");
      var bpInfo = currentServiceContainer.Execute<BusinessPartner>(bp, "GET", false);

      This works fine (this makes me think that all my settings are indeed correct)...

      Question 2: How do i get AdminInfo?

      With kind regards,

      Ruben Pol

      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      Hi Ruben,

      Here you have a sample for getting the CompanyService_GetCompanyInfo.

      Can you please check if this code works for you and afterwards adapt it for AdminInfo instead of CompanyInfo?

      If not working please post a question outside this blog comments, it is not easy to get it managed here, just post the link here.

      public string CompanyService_GetCompanyInfo()
      {
      CompanyInfo cmpInfo = null; // ComplexType!
      try
      {
      //Format the URI
      string strFormat = "{0}/{1}";
      string strURL = strCurrentServerURL;
      if (strCurrentServerURL.EndsWith("/"))
      strURL = strURL.Remove(strURL.Length - 1); //remove last /, to avoid duplication

      string strRequstCmd = string.Empty;

      //HTTP Request Command Type
      string strCommandType = "POST";

      string strAction = "CompanyService_GetCompanyInfo";

      strRequstCmd = string.Format(strFormat, strURL, strAction);
      Uri cmdQuery = new Uri(strRequstCmd);

      //Enacpsulate the parameters if necessary
      BodyOperationParameter[] body = null;
      cmpInfo = (CompanyInfo)currentServiceContainer.Execute<CompanyInfo>(cmdQuery, strCommandType, true, body).SingleOrDefault();

      return cmpInfo.CompanyName;
      }
      catch (Exception ex)
      {
      throw ex;
      }
      }

      Hope it helps

      Trinidad.

      Author's profile photo R. Pol
      R. Pol

      Hi Trinidad,

      Unfortunately, that did not help...

      I posted a new question on https://answers.sap.com/questions/408805/how-to-consume-hana-service-layer-call-get-company.html with my Program.cs code for a simple Console Application... Hopefully with that code you can figure out what is going on (unless that code is working for you)...

      With kind regards,

      Ruben Pol

      Author's profile photo Former Member
      Former Member

      Hello ,

      thank you so much for the interesting tuto

      i want to know if I can use service layer inside my SAP B1 addon instead of DI API

      best regards

      Radhia HENOUZ

      Author's profile photo Miklós Németh
      Miklós Németh

      Yes, absolutely. You can even apply Single-Sign-On with the help of the new UI API function in the Company COM interface, GetServiceLayerConnectionContext. You will receive the cookie string for B1SESSION. The UI API performs the login for you this way.

       

      Author's profile photo Bilal Sultan
      Bilal Sultan

      Thank you Maria Trinidad MARTINEZ GEA for this blog i found it very useful,
      Still i have a couple of questions as where exactly you specified that the Document (order) is a sales order
      , and how can i specify lets say a delivery or AR\invoice

      Please Help

      Author's profile photo R. Pol
      R. Pol

      Hi Trinidad,

      When using your code I had an issue when i wanted to create an Invoice based on a Delivery. With the help from SAP support i found out that i had to change 1 of the functions from your sample program. As to keep your page readable, I made a blog post with the solution provided by SAP support (https://blogs.sap.com/?p=642503)...

      With kind regards,

      Ruben

      Author's profile photo Former Member
      Former Member

      Hi,

      I have facing problem.

      when updating Sales order using Service Layer.

      Error is -5002 :- Internal error (-5002) occurred.

      Code :-

      SalesOrder = currentServiceContainer.Orders.Where(cursor => cursor.DocEntry == model.DocEntry).SingleOrDefault();
      SalesOrder.Comments = "Change it yo";
      currentServiceContainer.UpdateObject(SalesOrder);
      currentServiceContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);

       

      Author's profile photo Hassan El Madany
      Hassan El Madany

      I appreciate your efforts but when I restarting service layer after configuration, the following error occured. i can not use http://server:50000/b1s/v1/login 

      Author's profile photo Raul Zapata Pasos
      Raul Zapata Pasos

      Hello Trinidad,

       

      I'm trying to Add the Service reference to my visual studio project, but then credentials are requested and I'm not sure which credentials I must use; It's important to mention previously I have logged in using postman

       

      Do you know how can I solve this issue?

      Thanks

      Author's profile photo Ümit Yavuz
      Ümit Yavuz

      Hi Raul Zapata Pasos,

       

      I have the same problem, did you solve the problem?

       

      Best Regards.

      Author's profile photo Jose Amaya
      Jose Amaya

      Hello guys

      I'm facing the same issue here when trying to add the web reference for service layer to the VS Project, tried it as a web reference and as a service reference and failed both because of this.

      @raul.zapatapasos @umity did you guys could resolve this problem? have any pointers?

      Dear @mariatrinidad.martinezgea could you point us somewhat in a better direction?

       

      Best regards

       

      Author's profile photo Ümit Yavuz
      Ümit Yavuz

      Hello Jose,

      I solved the problem. I added  MetadataWithoutSession : true   and WCFCompatible :true  b1s.conf file. it's okey.

       

      Best Regards.

      Author's profile photo Raul Zapata Pasos
      Raul Zapata Pasos

      Hello Ümit

       

      I will try your solution! Thanks

      Author's profile photo Luis Raposo
      Luis Raposo

      Hello Maria,

       

      I’m trying to modify your example to support this option:  B1S-ReplaceCollectionsOnPatch=true.

      But i’m not sure where can we put this parameter in the request.

       

      I want to manage the allocated batches in the order items, and when I save the document I add, remove or update batches in the items of the order, the Service Layer does not return any error, but also it did not changed nothing in the allocated batches.

      Can you help me with this?

       

      Thank you.

       

      Best regards,

      Luis Raposo

      Author's profile photo Sofia Zaec
      Sofia Zaec

      Maria Trinidad MARTINEZ GEA , thank you for this blog.

      I tried your samples but I've got error described here : https://answers.sap.com/questions/12684019/tax-data-is-missing-arrayoffset-12-srclinnum-1-src.html

      please, I really don't know what to do and it's really bad!

      Author's profile photo Nestor Duarte
      Nestor Duarte
      hello Maria Trinity
      
      Thanks for this blog, can you give an example of "Batch Operation" in service layer where you can get the order number and then add it to a service call ?, I do not know how to get the order number and then add it to a document of sap b1 in "Batch Operation", the idea is that it is a single transaction, as well as the transactions in the DI API.
      
      regards.
       
      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      Hi Nestor,

      What you are trying to do cannot be done via Batch Operation. You need to use Service Layer Script Engine capabilities instead, please chec this blog for more details https://blogs.sap.com/2017/09/01/implementing-service-layers-script-engine/

      Hope it helps,
      Trinidad.

      Author's profile photo Ameth Ordoñez
      Ameth Ordoñez

      hello maria trinidad,

      thanks for this blog, how can we use this method “DraftsService_SaveDraftToDocument” I am working with the draft documents and I need to convert them to real documents, I have a code but I am not sure, I appreciate your help:

      public bool DraftsService_SaveDraftToDocument(int pDocEntry)
              {
                  try
                  {
                      //Format the URI
                      string strFormat = "{0}/{1}";
                      //url del servicio
                      string strURL = strCurrentServerURL;
                      //cadena de la solicitud
                      string strRequstCmd = string.Empty;
                      //HTTP Request Command Type
                      string strCommandType = "POST";
                      //objeto de accion
                      string strAction = "DraftsService_SaveDraftToDocument";
      
                      //validar si tiene el simbolo "/"
                      if (strCurrentServerURL.EndsWith("/"))
                          strURL = strURL.Remove(strURL.Length - 1); //remove last /, to avoid duplication
      
                      strRequstCmd = string.Format(strFormat, strURL, strAction);
                      Uri cmdQuery = new Uri(strRequstCmd);
      
                      //Enacpsulate the parameters if necessary
                      BodyOperationParameter[] body = new BodyOperationParameter[1];
      		
      		//???
                      body[0] = new BodyOperationParameter("Document", "");
      
                      currentServiceContainer.Execute<string>(cmdQuery, strCommandType, true, body);
      
                      return true;
                  }
                  catch (Exception ex)
                  {
                      //insertar Log
                      return false;
      
                  }
              }

      regards

       

      Author's profile photo Pawel Generalczyk
      Pawel Generalczyk

      Hi.

      I have an issue while trying to Add Service Reference.

      After selecting metadata and pressing Ok button I receive an error:

      Regards,

      Pawel

      Author's profile photo Former Member
      Former Member

      Hi Pawel,

       

      I have same problem like you.

      My environment is VS Studio 2015 + SBO 10.0 PL02 on MSSQL 2017.

      Did you fix this issue?

      Regards

      Robin

      Author's profile photo Luis González Neira
      Luis González Neira

      No logro iniciar sesión, me vuelve a solicitar usuario y contraseña.

      Author's profile photo Luis González Neira
      Luis González Neira

      I cannot log in, I am asked again for a username and password.

       

      Author's profile photo Txema Pérez-Aradros
      Txema Pérez-Aradros

      Hello Luis.

      I have the same problem.  You have solved it?

       

      Thanks

      Author's profile photo Poul-Erik Jensen
      Poul-Erik Jensen

      I think You will need to use Postman to login and then afterwards get $metadata which You then save as an XML file, that You afterwards can "import" in Visual Studio

      Author's profile photo Carsten Giesen
      Carsten Giesen

      Hello,

      thanks for this blog entry.
      But regard, until VS2019 there are a other way to implement the service to the Project.

      First you have to install:
      https://marketplace.visualstudio.com/items?itemName=laylaliu.ODataConnectedService

      Here you can import the XML you explain.

      The way to add via URL didn#t work for me.
      I have to enter the credentials again and again and again ....

      cu

      Carsten

      Author's profile photo Patrik Becker
      Patrik Becker

      Hi Carsten,

      do you use the connected service agains a SAP 10.0 SQL Service Layer?

      I tried to Login and get the response "500 - InternalError"

      If T try to Login with the same code agains a Service Layer HANA, Version 9.3  it works fine.

      If I Login against my Service Layer (SAP10/SQL) with Visual Studio 2015 and a Service Reference , it works fine too.

      I really have no idea and looking for help.
      Do you have an idea?

       

       

      Author's profile photo Poul-Erik Jensen
      Poul-Erik Jensen

      Hi Patrik

      Did You solve this problem?

      (I have the same problem)

      response 500 and unfortunately no log information giving details about the error

      Best regards

      Poul-Erik

      Author's profile photo Poul-Erik Jensen
      Poul-Erik Jensen

      I now have the connection to servicelayer. Seems like the result is about "errors" in the XML-file (metadata) datetime entities. The latest version of SB1 has fixed most of it, but i still needed to replace datetimeoffset to date in the metadata-xml file to get a succes

      Author's profile photo Chendera Hari Mastopa
      Chendera Hari Mastopa

      Hello, @mariatrinidad.martinezgea. I have tried this sample and try following it thought I use my own XML.

      I can change Value in Comment and UDF in Documents , Also can Insert and Update Master BP.
      But problem is I can’t insert Document(Order,Quotation,Purchase Order,etc)

      Always got error:
      Internal error (-5002) occurred

      Am I missing something? or My code is wrong?

      Author's profile photo Pawel Generalczyk
      Pawel Generalczyk

      Hi Maria.

      Would please help me.

      I am trying to post a correction invoice using the service layer. After several successful attempts, the server suddenly started rejecting the request with the message:
      The remote server returned an error: (502) Bad Gateway.
      Even restarting the service tier service did not help.
      What could be the reason for this behaviour and how can we fix the problem?

      Kind regards.

      Pawel

      Author's profile photo Praveen kumar
      Praveen kumar

      Hello there, I have tried both the methods that you mentioned in the above blog , I tried the first method but i cannot get my saved xml document into the add service reference , then i tried second method by directly giving the URL , then the User name and password credentials came . but when i give my correct credentials , the pop up screen appears again and again asking for the user name and password repeatedly .

      Please help me thank you!

      PS. im using VS2019 and my server is MSsql 2014

       

      Author's profile photo Anish Maharjan
      Anish Maharjan

      I am also facing the exact same problem, I am using vs2019, .net framework 4.5.1 in the addon project for sap 10. If anybody knows how to solve this problem, please help.

      Author's profile photo Praveen kumar
      Praveen kumar

      try to download the reference as xml document and pass it into the solution

       

      Author's profile photo Praveen kumar
      Praveen kumar

      change your frame work version to 4.0 then try adding the service reference

      Author's profile photo Rahul Jain
      Rahul Jain

      Hey Praveen kumar

      Thanks for proving response on the queries but still i am not able to find the solution. Please suggest resolution here. Please find the steps & correct where I am going wrong -

      Check the B1s.Conf file for your reference - 

      Step 0 - Please find the screenshot of the .Net Framework Version 4.0

      Step 1 - Saved the $Metadata as xml file and pasted into my .net project

      Step 2 - Tried to refer the same but still I am getting same error.

      Error Details 

      image.png

      SAP Version 

      image.png

      Please provide resolution here.

      Author's profile photo Rahul Jain
      Rahul Jain

      Found the solution, Please find the link here - https://answers.sap.com/questions/13545446/service-layer-login-session-in-c-wcf.html?sort=oldest

      Author's profile photo Mauro Cattaneo
      Mauro Cattaneo

      Hi Maria,

      is there any way to filter only active BusinessPartners with the ServiceLayer?

      Thanks a lot

      Mauro

      Author's profile photo German Oggier
      German Oggier

      Hi maria, I am trying to update a business partner and when executing the update method it throws me the following error, could you help me understand why the saveChanges () does not work? . Below I attach photos.

       

       

      help me please!

      Author's profile photo Manish Kumar Singh
      Manish Kumar Singh

      Hi Maria,

      Please help !

      At the time of adding service reference, after putting credentials it's giving error as below attachment. I am using SAP 10 PL02 with SQL 2019.

      Author's profile photo Steven Delombaerde
      Steven Delombaerde

      Hello

       

      I am trying to get the sample code from the following link, but it does not work:

      https://assets.cdn.sap.com/tools/SAP-Business-One-Service-Layer-NET-WCF-sample.zip

      Can someone check this link and make it available again?

       

      Thanks

      Steven

      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      Hi Steven,

      The sample code is available for download here.

      Please pay attention to the fact that this sample was created in 2015 and therefore several libraries and metadata details might have been modified from the SAP Business One side as well as from Microsoft. This sample is provided as is without further support.

      Our recommendation is to move to cloud development and loosely coupled solutions as explained in most recent blogs https://blogs.sap.com/2018/06/05/loosely-coupled-solutions-for-smbs-topics/ .

      Hope it helps
      Trinidad.

      Author's profile photo João Claudino
      João Claudino
      link doesn't work
      Author's profile photo Maria Trinidad MARTINEZ GEA
      Maria Trinidad MARTINEZ GEA
      Blog Post Author

      Should be ok now, please check

      Please pay attention to the fact that this sample was created in 2015 and therefore several libraries and metadata details might have been modified from the SAP Business One side as well as from Microsoft. This sample is provided as is without further support.

      Our recommendation is to move to cloud development and loosely coupled solutions as explained in most recent blogs https://blogs.sap.com/2018/06/05/loosely-coupled-solutions-for-smbs-topics/ .

      Hope it helps
      Trinidad.