In one of my projects, I have developed a WCF service and hosted it on Azure. I was required to create the service RESTful and call it from inside a SharePoint online app; for which, I added the required service configuration in the web.config file.
For creating the RESTful service, we need to use WebHttpBinding for specifying service endpoint and define the endpoint behavior. Here’s the configuration that I have added:
Adding this allows accessing my service using RESTful API calls over HTTP access. But, when I tried calling my service from inside the SharePoint online app, it showed the below error:
“The app… was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint…. The request has been blocked; the content must be served over HTTPS."
And then I knew that the service should be secure to be accessible over HTTPS. To secure the custom domain name with HTTPS, it requires binding a custom SSL certificate to the custom domain in Azure.
This can also be done through simple configuration changes in the web.config file. To make the RESTful service accessible over HTTPS, I added the following configuration:
First, it is needed to add a WebHttpBinding configuration with security mode set to ‘Transport’ as below:
And then, it required assigning this WebHttpBinding configuration to Service Endpoint binding with httpsGetEnabled set to ‘true’
After adding these configuration settings, I was able to call my service from inside the SharePoint online app using HTTPS access.
With the above configuration, the service will be accessible over HTTP and HTTPS both. If you want to disable HTTP access, and allow the service accessible with HTTPS only, then you can set httpGetEnabled to ‘false’ in the ServicerBehavior settings.
Using Net.WebClient over HTTPS returns this error:
The underlying connection was closed: An unexpected error occurred on a send.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
You have to setup a ServerCertificateValidationCallback event and set the right SecurityProtocol:
Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates
Public Class HTTPS_Test
Private Function validateCertificate(sender As Object,
certificate As X509Certificate,
chain As X509Chain,
sslPolicyErrors As SslPolicyErrors
) As Boolean
'' If the certificate is a valid, signed certificate, return true.
'If sslPolicyErrors = Security.SslPolicyErrors.None Then
' Return True
'Else
' Console.WriteLine("X509Certificate [{0}] Policy Error: '{1}'",
' certificate.Subject,
' sslPolicyErrors.ToString)
' Return False
'End If
Return True
End Function
Public Sub DownloadFromHTTPS()
'-- IMPOSTAZIONI PER USARE HTTPS/CERTIFICATI - da impostare prima di usare il WebClient
ServicePointManager.ServerCertificateValidationCallback = AddressOf validateCertificate
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or
SecurityProtocolType.Tls Or
SecurityProtocolType.Tls11 Or
SecurityProtocolType.Tls12
Dim url As String = "https://..."
Using myWebClient As New WebClient()
Dim data As String = myWebClient.DownloadString(url)
End Using
End Sub
End Class
IIS on Windows Server 2012 R2 64bit throws this error:
Could not find a base address that matches scheme http for the endpoint with binding BasicHttpBinding. Registered base address schemes are [https].
Impossibile trovare un indirizzo di base corrispondente allo schema http per l'endpoint con binding WebHttpBinding. Gli schemi degli indirizzi di base registrati sono [].
When i ran this code i recieved the following exception: XmlException was unhandled: The "XmlWriterSettings.Encoding" property is read only and cannot be set. The documentation for the Settings property clearly says:
The XmlWriterSettings object returned by the Settings property cannot be modified. Any attempt to change individual settings results in an exception being thrown.
As you can see: is still not what i want. Apparently is the Encoding property ignored if the XmlWriter is not using a Stream. So here is my next attempt:
MemoryStream memoryStream = new MemoryStream();
// initialize xmlWriterSettings as above...
XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
// call the same operations on the xmlWriter as above...
string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray());
Ok, i'm getting close:
?
Luckily enough i knew that the ? (byte with value 239) at the beginning is the BOM (Byte Order Mark). In order to get rid of that byte i had to create my own instance of UTF8Encoding. Finally, i can present some working code: