Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

We are beginning to implement Gateway at our company, which most of our development is done in a .NET environment. With some new changes in GW SP03, there are a few new things which you must do during the request to perform a modifying (create, update, delete) request around the CSRF tokens. I wanted to share a basic example of how I was able to utilize the native data service client functionality within .NET to perform a Create request to a Gateway service. This particular example is around creation of a material in ECC using BOR objects.

I'm not going to go into the creation of the Gateway service, as I will assume this is already done.

Create a new C# project in Visual Studio. Once the project is created, we need to add the Gateway service to the project.

In Solution Explorer, right click on References then click on Add Service Reference. Once the window opens, add the service by putting the URL to the service in the Address box and click GO. You should see the service name in the Services box along with the collections available for the service. Assign it to a meaningful Namespace and click OK.

You will now be able to use the native functionality for data services in .NET for your Gateway service.

For this example I created just a basic Windows forms application. I have a single form with a text box (to display error messages) and a button (to start the create process).

First off, create a few objects to be used in a couple different methods. These will be used to hold the data both received and sent to the Gateway service.

    public partial class Debug : Form
    {
        private string csrfToken = String.Empty;
        private string setCookie = String.Empty;
        private CookieContainer cookieJar;

Inside the button click method is where I have the following code to actually execute the create request.

Basically we check to see if we have the CSRF token stored already, if we don't we have to make a HTTP request to the Gateway server to get the token. Once we have the token and the corresponding cookies, we can proceed with the modifying request.

private void button2_Click(object sender, EventArgs e)
        {
            // Setup network credentials object to be used for requests to Gateway server
            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(Properties.Settings.Default.GW_Username, Properties.Settings.Default.GW_Password);
           
            // Create Gateway objects
            z_material material = new z_material();
            Z_MATERIALS materialClient = new Z_MATERIALS(new Uri(Properties.Settings.Default.GW_Uri));
            materialClient.Credentials = credentials;
            // Check to see if we already have the CSRF token...if not, request it from the server.
            if (this.csrfToken == String.Empty)
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(Properties.Settings.Default.GW_Uri);
                HttpWebResponse resp;
                // Add custom header request to fetch the CSRF token
                req.Credentials = credentials;
                req.Method = "GET";
                req.Headers.Add("X-CSRF-Token", "Fetch");
                               
                // Setup cookie jar to capture cookies coming back from Gateway server. These cookies are needed along with the CSRF token for modifying requests.
                cookieJar = new CookieContainer();
                req.CookieContainer = cookieJar;
                try
                {
                    resp = (HttpWebResponse)req.GetResponse();
                }
                catch (System.Net.WebException ex)
                {
                    // Add your error handling here
                    return;
                }
                catch (Exception ex)
                {
                    // Add your error handling here
                    return;
                }
                // Assign values from response to class variables.
                this.csrfToken = resp.Headers.Get("X-CSRF-Token");
                this.setCookie = resp.Headers.Get("Set-Cookie");
            }       
            // Assign values to objects being passed into Gateway request.
            material.material_id = "MIKETEST2";
// commented out rest of value assignment for brevity
            // Use native .NET data service client to build request to add item to collection (CREATE/POST)
            materialClient.AddToz_materialCollection(material);
            // Add event handler to add additional data to service request
            materialClient.SendingRequest += new EventHandler<System.Data.Services.Client.SendingRequestEventArgs>(materialClient_SendingRequest);
            // Post changes to GW server
            try
            {
                materialClient.SaveChanges();
            }
            catch (Exception ex)
            {
                //Add your error handling here
            } 
        }

As you can see we've added an event handler to the materialClient object to do some additional processing of the request before it's sent to the server.

Here we are going to add the CSRF token to the request headers, along with setting the content type to be what the Gateway server is expecting. Also, we must include the cookies from the response above, or else you will receive an error from the Gateway server with something along the lines of "CSRF token validation failed".

        void materialClient_SendingRequest(object sender, System.Data.Services.Client.SendingRequestEventArgs e)
        {
            // If we have a CSRF token, add it to the request headers. Make sure to set Content-Type in headers to correct value.
            if (this.csrfToken != String.Empty)              
                e.RequestHeaders.Add("x-csrf-token", this.csrfToken);
            e.Request.ContentType = "application/atom+xml";
            // Append cookies from response above to modifying request.
            CookieCollection cookies = cookieJar.GetCookies(new Uri(Properties.Settings.Default.GW_Uri));
            foreach (Cookie cookie in cookies)
            {
                e.RequestHeaders.Add("Cookie", cookie.ToString());
            }           
        }

And that's it! As long as your Gateway service is setup properly and you're passing in all the appropriate values, you will create your material in the ECC system. This is a very generic example, but hopefully it will help someone out there with the CSRF token validation.

Mike Bowen

5 Comments
Labels in this area