Before I used Simple.OData.Client in our Xamarin project, I tried it with help of LINQPad. I was very impressed by the easiness to use it. When I built it into our Xamarin project I got exception by trying to get data from SharePoint's REST Api.
Simple.OData.Client.WebRequestException: Unexpected WebException encountered ---> System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decr...{Simple.OData.Client.WebRequestException: Unexpected WebException encountered ---> System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a
As I believe, this exception was caused by the fact that our SharePoint instance using self-signed certificate. I tried it to eliminate by returning always true to the ServerCertificateValidationCallback
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
Now I get all the time Unauthorized exception from the Simple.OData.Client
Simple.OData.Client.WebRequestException: Unauthorized
Initial call is from MainViewModel through the business layer
private async void InitializeAsync()
{
// TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:09:55]: Show loading indicator
TaskEntity getTaskForCurrentMonthAsyncTask = await _taksBusinessLayer.GetTaskForCurrentMonthAsync();
_timeToDisplay = getTaskForCurrentMonthAsyncTask.DueDate - DateTime.Now;
// TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:10:04]: Hide loading indicator
StartCountdownTimer();
}
The class which executing the call is the class SharePointTaskRepository
public class SharePointTaskRepository : ITaskRepository
{
private readonly string _collectionName;
private readonly ODataClient _oDataClient;
public SharePointTaskRepository(Uri sharepointUri, string collectionName, ICredentials credentials)
{
if (sharepointUri == null)
{
throw new ArgumentNullException("sharepointUri");
}
if (String.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException("Argument can't be null, empty or white space!", "collectionName");
}
if (credentials == null)
{
throw new ArgumentNullException("credentials");
}
_collectionName = collectionName;
var oDataClientSettings = new ODataClientSettings(sharepointUri, credentials);
_oDataClient = new ODataClient(oDataClientSettings);
}
public async Task<IEnumerable<TaskModel>> ReadAsync(Expression<Func<TaskModel, bool>> filter, Expression<Func<TaskModel, object>> orderBy, int numberOfResults)
{
return await _oDataClient
.For<TaskModel>(_collectionName)
.Filter(filter)
.OrderBy(orderBy)
.Top(numberOfResults)
.FindEntriesAsync();
}
}
I double checked the credentials, which are definitely correct. The code which utilize ServerCertificateValidationCallback is in the ApplicationRuntimeSettings. This class is platform specific, singleton and provided as all other objects by dependency injection.
[assembly: Dependency(typeof(ApplicationRuntimeSettings))]
namespace AZeitReminder.Droid.Infrastructure
{
public class ApplicationRuntimeSettings : ApplicationRuntimeSettingsBase
{
public ApplicationRuntimeSettings()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
}
public override SQLiteConnection CreateSqLiteConnection()
{
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = Path.Combine(documentsPath, DatabaseFileName);
var currentPlatform = new SQLitePlatformAndroid();
var connection = new SQLiteConnection(currentPlatform, path);
return connection;
}
public override CultureInfo GetCultureInfo()
{
var androidLocale = Java.Util.Locale.Default;
var netLanguage = androidLocale.ToString().Replace("_", "-"); // NOTE [Anton Kalcik - Dienstag, 05. Mai 2015 17:21:10]: turns pt_BR into pt-BR
return new CultureInfo(netLanguage);
}
}
}