Thursday, March 5, 2015

Calling a WCF Web Service over HTTPS (SSL)

I was recently trying to access a web service that I wanted to secure over HTTPS. I got it working as an HTTP service, as you do, and made sure that I had a certificate on the server and enabled the https protocol.
I was using basic Http binding and here are the changes that need to be made

          <security mode="Transport">
            <transport clientCredentialType="None" />

That now worked in the browser if I prefixed the url with https://

Next step was that I needed to call the web service where I was not able to access a web.config or an app.config.  Without the service reference being available you have to do this in code. First thing is to make sure you have a copy of the interface class accessible in the client.  It doesn't need to be the same name but it does need to specify the operation contract exactly.

    [ServiceContract]
    public interface IFormDefinition
    {
        [OperationContract]
        [FaultContract(typeof(CRMSoapFault))]
        void PublishFormMetaData(string crmEndPoint, string formId, string webResource, string token);
    }
    [DataContract]
    public class CRMSoapFault
    {
        public CRMSoapFault(string errorMsg)
        {
            this.ErrorMsg = errorMsg;
        }
        ///
        /// This property is used to pass the custom error information
        /// from service to client.
        ///

        [DataMember]
        public string ErrorMsg { get; set; }
    }

To call the web service and set the binding information through code to match this you need to add:

 BasicHttpBinding myBinding = new BasicHttpBinding();
            myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
            myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            EndpointAddress myEndpoint = new EndpointAddress(endPointUrl);
            ChannelFactory myChannelFactory = new ChannelFactory(myBinding, myEndpoint);
            try
            {
                IFormDefinition wcfClient1 = myChannelFactory.CreateChannel();
                // call the web service method
                wcfClient1.PublishFormMetaData(crmEndPoint, formId, webResource, token);

            }
            catch(FaultException faultEx)
            {

             }

Monday, March 2, 2015

Accessing SharePoint Online with Web Client

Misleading title really because if you try and access SharePoint Online using the WebClient it will fail to authenticate.  What you need to do is use the CookieContainer and SharePointOnlineCredentials. 
I got the basics of this from this post. and also from this post which uses a class inherits from WebClient. It mentions that you need the SharePoint Client Components SDK which will install Microsoft.SharePoint.Client.DLL and Microsoft.SharePoint.Client.RunTime.DLL. Add references to both DLLs in your project and add these two using statements

using Microsoft.SharePoint.Client;
using System.Security;


 
Add this class to your project
 
public class ClaimsWebClient : WebClient
{ private CookieContainer cookieContainer;

public ClaimsWebClient(Uri host, string userName, string password)
 
{

cookieContainer = GetAuthCookies(host, userName, password);

}
 
protected override WebRequest GetWebRequest(Uri address)
{
    WebRequest request = base.GetWebRequest(address);
    if (request is HttpWebRequest)
 
    { 
        (request as HttpWebRequest).CookieContainer = cookieContainer;
   }
  
   return request;
 
}
 
private static CookieContainer GetAuthCookies(Uri webUri, string userName, string password)
{    var securePassword = new SecureString();
    foreach (var c in password) { securePassword.AppendChar(c); }
    var credentials = new SharePointOnlineCredentials(userName, securePassword);
    var authCookie = credentials.GetAuthenticationCookie(webUri);
    var cookieContainer = new CookieContainer();
    cookieContainer.SetCookies(webUri, authCookie);      return cookieContainer;
}

}
 


Then call the ClaimWebClient class in the same way as you would the WebClient.  Note that you do not need to set the credentials because it is done within the ClaimWebClient class.

ClaimsWebClient wc = new ClaimsWebClient(new Uri(sharePointSiteUrl), userName, password);

byte[] response = wc.DownloadData(sourceUrl);