Show TOC

SAP.Net.Http.HttpClient Features and UsageLocate this document in the navigation structure

Use SAP.Net.Http.HttpClient features in .NET and Windows Store applications.

Also see Upgrade Guide for Windows Applications That use the SAP.Net.Http Assembly for information on features that require code migration. For example, uploading logs/BTX documents and error handling.

Enabling TLS Version 1.2
  • .NET: By default, the library automatically enables TLS version 1.2.
  • Windows Runtime: The library can use TLS 1.2 automatically, but you must verify that TLS 1.2 is enabled at the operating system level:
    1. Press Win+R, type inetcpl.cpl, then press Enter.
    2. Select the Advanced tab and scroll down to the Security section.
    3. If it is not already, select Use TLS 1.2.

Specifying the Client Certificate Used When Sending Requests
  • .NET: Create a System.Net.Http.WebRequestHandler instance. Add a reference to the System.Net.Http.WebRequest assembly, otherwise the class will not be available:
    Sample Code
    var handler = new System.Net.Http.WebRequestHandler() {
    	ClientCertificateOptions = ClientCertificateOption.Manual,
    	// set up the rest of the properties you need here…
    };
    // add the certificate instance to the ClientCertificates collection:
    handler.ClientCertificates.Add(clientCertificate);
    
    // create a client with the handler above
    var client = new SAP.Net.Http.HttpClient(handler, true);
    
    Note You can also chain your custom handlers together using the handler created in the sample code above.
  • Windows Runtime: Create a Windows.Web.Http.Filters.HttpBaseProtocolFilter instance, then set its ClientCertificate property to your certificate instance:
    Sample Code
    var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter() {
    	ClientCertificate = clientCertificate,
    	// set up the rest of the properties you need here…
    };
    
    // create a client with the handler above
    var client = new SAP.Net.Http.HttpClient(filter);
    Note You can also chain your custom filters together using the filter created in the sample code above.
Enabling SAML Authentication
(.NET and Windows Runtime) The networking library supports SAML authentication that uses a POST binding and Web profile. In SP09, redirect binding is unsupported and only SAP IdPs can be used with POST binding and web profile:
Sample Code
var client = new HttpClient(…) { // replace "…" with your handler or filter variable, if any
	ShouldHandleSamlRequests = true,
	// configure the rest of the properties of the HttpClient you need here…
};
…
client.SamlAuthenticationProperties.SamlFinishEndpoint = new UriBuilder("https://YOUR_URL_HERE/SAMLAuthLauncher").Uri;
client.SamlAuthenticationProperties.SamlFinishEndpointParameter = "finishEndpointParam";
Note Kapsel developers: When using the LogonCore library, switch off SAML authentication handling and perform SAML authentication in JavaScript. Otherwise the HTML5/Cordova application might fail when the native library detects that SAML authentication is taking place and attempts to show a native UI.
Use this code to switch off handling of SAML authentication on a LogonCore instance:
logonCore.ShouldHandleSamlRequests = false; // logonCore is an instance of SAP.Logon.Core.LogonCore;
Tracking HTTP Request Progress
  • .NET:
    Sample Code
    using (var client = new SAP.Net.Http.HttpClient()) {
    	await client.SendAsync(() => new HttpRequestMessage(
    		HttpMethod.Get, new Uri("YOUR_URI_HERE")),
    		HttpCompletionOption.ResponseContentRead,
    		cancellationTokenSource.Token,
    		(s, progress) => {
    		// this implementation is just a sample, you can even update UI here (just dispatch the UI code to the UI thread)>>
    			Console.SetCursorPosition(0, 0);
    			Console.WriteLine("{0} KB out of {1} KB", progress.BytesTransferred / 1024, progress.TotalBytesToTransfer / 1024);
    		});
    	…
    }
    
  • Windows Runtime:
    Sample Code
    using (var client = new SAP.Net.Http.HttpClient()) {
    	await client.SendAsync(() => new HttpRequestMessage(HttpMethod.Get, new Uri("YOUR_URI_HERE")),
    					HttpCompletionOption.ResponseContentRead,
    					cancellationTokenSource.Token,
    					async (s, progress) => {
    						await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
    							this.StatusText = String.Format("{0} KB out of {1} KB", progress.BytesTransferred / 1024, progress.TotalBytesToTransfer / 1024);
    					});
    	});
    }
    
Enabling HTTP Request Tracing
The networking library in version 3.0 SP09 and later supports HTTP request tracing on all Windows platforms. By default, for performance and security reasons tracing is disabled. However, you can enable tracing any time, even if requests have already been sent to the server. To enable tracing, use:
tracedClient.TracingControl.IsEnabled = true;
To control into which tracing step the traces are added, use the TraceStep property. If no step is defined, traces are added to the active step:
tracedClient.TracingControl.TraceStep = step;  
<step> is an IE2ETraceStep variable.
Note Without an active "transaction," traces are not collected even if tracing is enabled.
The following data is collected when tracing requests:
  • Request line: includes the HTTP method, URL and the HTTP protocol version.
  • The request headers, although:
    • The default request headers set for the HttpClient are not collected, and
    • Authentication information is removed from the trace.
  • The number of bytes sent.
  • The response headers.
  • The number of bytes received.
  • The amount of time, in milliseconds, required to send the request and receive the complete response.
  • The HTTP status code, if available.
Enabling Logging for the Networking Library
The networking library in version 3.0 SP09 and later supports logging on all Windows platforms. By default, for performance and security reasons logging is disabled. However, you can enable logging any time, even if requests have already been sent to the server. To enable logging, use:
tracedClient.LoggingControl.IsEnabled = true;
Canceling an Ongoing Request
The following code sample is one possible implementation for sending requests that can be cancelled, and then cancelling them. Developers can implement their own logic that includes, for example:
  • Canceling a request using a keyboard shortcut.
  • Using a UI element other than the button control to signal the cancellation token.
  • Creating a field in your class that holds a cancellation token source instance instead of the method shown below. If you do this, you do not then need the "using" part as shown in the code snippet, however, you must dispose of the cancellation token source and re-create it each time after the response is received; you must also implement the IDisposable interface.
Request sending code:
Sample Code
try {
	using (var cts = new CancellationTokenSource()) {
		cancellationTokenSource = cts;
		using (var client = new SAP.Net.Http.HttpClient()) {
			var responseMessage = await client.SendAsync(
				() => new HttpRequestMessage(HttpMethod.Get, new Uri("YOUR_URI_HERE")),
				HttpCompletionOption.ResponseContentRead, cts.Token
			);
			message = await responseMessage.Content.ReadAsStringAsync();
		}
	}
} catch (Exception ex) {
	// handle the exception
}

cancellationTokenSource = null;
Using a button control to signal the token that cancellation has been requested:
Sample Code
private void Button_CancelClick(object sender, RoutedEventArgs e) {
	if (cancellationTokenSource == null) return;
	((CancellationTokenSource)cancellationTokenSource).Cancel();
	cancellationTokenSource = null;
}
Adding a Custom Handler or Filter
Example handler and filter code that counts the number of sent requests by an HttpClient instance:
  • .NET:
    Sample Code
    private class DummyHandler : System.Net.Http.DelegatingHandler {
    	int dummyField = 0;
    	public DummyHandler(System.Net.Http.HttpMessageHandler innerHandler) : base(innerHandler) { }
    
    	protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
    		Interlocked.Increment(ref dummyField);
    		System.Diagnostics.Debug.WriteLine("DummyHandler::SendAsync: " + dummyField);
    		return base.SendAsync(request, cancellationToken);
    	}
    }
  • This code performs the same function with regard to implementing the IHttpFilter interface:
    Sample Code
       int dummyField = 0;
    	private Windows.Web.Http.Filters.IHttpFilter innerFilter = null;
    	public DummyFilter(Windows.Web.Http.Filters.IHttpFilter filter) {
    		if (filter == null) throw new ArgumentNullException("filter");
    		this.innerFilter = filter;
    	}
    
    	public IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> SendRequestAsync(HttpRequestMessage request) {
    		CheckIfDisposed();
    		Interlocked.Increment(ref dummyField);
    		System.Diagnostics.Debug.WriteLine("DummyHandler::SendAsync: " + dummyField);
    		return this.innerFilter.SendRequestAsync(request);
    	}
    
    	private bool disposed = false;
    	private void CheckIfDisposed() {
    		if (disposed) throw new ObjectDisposedException("DummyFilter");
    	}
    
    	public void Dispose() {
    		Dispose(true);
    		GC.SuppressFinalize(this);
    	}
    	protected virtual void Dispose(bool disposing) {
    		if (disposed) return;
    		if (disposing) {
    			if (this.innerFilter != null) {
    				this.innerFilter.Dispose();
    				this.innerFilter = null;
    			}
    		}
    		disposed = true;
    	}
    }
The following code snippets show how to use this dummy handler/filter when sending requests:
  • .NET:
    using (var client = new SAP.Net.Http.HttpClient(
    		new DummyHandler(new HttpClientHandler() { AllowAutoRedirect = true }),
    		true
    	)) {
    		… // send a request here…
    }
    
  • Filter:
    using (var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter() { AllowAutoRedirect = true, AllowUI = false }) {
    	filter.CacheControl.ReadBehavior = Windows.Web.Http.Filters.HttpCacheReadBehavior.MostRecent;
    	filter.CacheControl.WriteBehavior = Windows.Web.Http.Filters.HttpCacheWriteBehavior.NoCache;
    	using (var client = new SAP.Net.Http.HttpClient(new DummyFilter(filter))) {
    		… // send a request here…
    	}
    }
    
Known Issues and Limitations
Due to Microsoft API limitations and confirmed bugs some changes in authentication handling were made that effects platforms that use the Windows Runtime API.
  • X509 authentication in tablet Windows Store apps
    The Microsoft networking library used internally either handles all the authentication challenges by showing a credential UI or showing nothing at all on the tablet platform. To ensure X509 certificates can be used for client authentication, credential handling is performed by the system and the system provided credential UIs. By doing this all authentication challenges known to Windows is handled by the Operating System. This could lead to these issues:
    • The user is prompted to enter the correct credentials each time the app restarts if the credentials entered on the logon/registration page (native or Kapsel) are wrong. The app has no access to the credentials entered in a system dialog, and therefore cannot persist the valid credentials to be used later. This does not limit the application in any way, but is an inconvenience to the user.
    • The change backend password functionality does not work, since the system handles all authentication challenges and caches the credentials during a user session per URL. This means the system ignores the credentials entered on the change backend password screen and accepts anything, since the system uses the credentials from its credential cache instead.
    • The system falls back to Basic authentication when X509 authentication fails (based on server configuration), but this should not occur (based on MobilePlace service configuration). For example:
      1. The user retrieves the logon/registration configuration from the MobilePlace service and an X509 certificate must be used to authenticate the user.
      2. The server is configured so that it falls back to basic authentication if certificate authentication fails.
      3. The user selects Cancel on the certificate picker UI provided by the system. After pressing Cancel the system displays the Enter basic authentication credentials dialog, which should not be the case according to the configuration retrieved from the MobilePlace service.
    • Registration deletion in most cases (~90%) only deletes locally (on the device) but not on the server. This is due to the lack of access to the credentials needed to be able to successfully send the "DELETE" HTTP request to the server without showing the credentials UI.
  • X509 authentication in Windows Phone 8.1 Store Apps

    There is an issue with the Microsoft implementation of the HttpBaseProtocolFilter class on Windows Phone. The AllowUI property is set to false by default which contradicts the documentation. Manually setting AllowUI to true causes an exception. This also means that to use X509 certificates on the phone you must either implement the certificate provider interface provided in the SAP Mobile Platform SDK, or install the client certificate using this provider into the application's local certificate store. Note however, that due to another issue, the WebView on the phone is unable to use client certificates (affects SAML scenarios).

  • User names with no passwords

    The Windows.Security.Credentials.PasswordCredential class does not accept null or empty strings ("") as passwords and throws an exception. This means that the LogonCore and the networking component cannot set the user name without a password in the system provided PasswordCredential instance. Therefore the system provided credential dialog requests the user name and password if necessary. Entering the user name in the dialog and pressing Enter works. The AllowUI property is false on the Phone (as described above) and therefore there are no system provided credential dialogs available on the phone. As a result, the SAP Mobile Platform SDK LogonCore and networking components handles basic authentication challenges particular well on the phone. Therefore if the user enters the username without passwords it is used and sent to the server when necessary and the phone platform is not affected.