Connect to Firebird on Mono - c#

Im trying to connect to a Firebird server using Mono on Mac but it is throwing an exception that I have no idea whats is happening.
I installed the package https://www.nuget.org/packages/FirebirdSql.Data.FirebirdClient
and here is the code I am using:
var connectionString = new FbConnectionStringBuilder();
connectionString.DataSource = "xxxx";
connectionString.UserID = "xxxxx";
connectionString.Password = "xxxxxx";
connectionString.Database = "/xxxxx.gdb";
connectionString.Charset = "NONE";
FbConnection connection = new FbConnection(connectionString.ToString());
try
{
connection.Open();
connection.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
And the exception:
String reference not set to an instance of a String.
Parameter name: s
at System.Text.Encoding.GetBytes (System.String s) [0x00006] in /private/tmp/source-mono-4.8.0/bockbuild-mono-4.8.0-branch/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/text/encoding.cs:1083
at FirebirdSql.Data.Client.Managed.GdsConnection.UserIdentificationData () [0x00141] in <1c49352b896a4a9dba73865ddab7b59e>:0
at FirebirdSql.Data.Client.Managed.GdsConnection.Identify (System.String database) [0x00044] in <1c49352b896a4a9dba73865ddab7b59e>:0
at FirebirdSql.Data.FirebirdClient.ClientFactory.CreateManagedDatabase (FirebirdSql.Data.FirebirdClient.FbConnectionString options) [0x00042] in <1c49352b896a4a9dba73865ddab7b59e>:0
at FirebirdSql.Data.FirebirdClient.ClientFactory.CreateDatabase (FirebirdSql.Data.FirebirdClient.FbConnectionString options) [0x00010] in <1c49352b896a4a9dba73865ddab7b59e>:0
at FirebirdSql.Data.FirebirdClient.FbConnectionInternal.Connect () [0x0001e] in <1c49352b896a4a9dba73865ddab7b59e>:0
at FirebirdSql.Data.FirebirdClient.FbConnection.Open () [0x000b7] in <1c49352b896a4a9dba73865ddab7b59e>:0
Do you have any idea to solve this problem?

Related

System.AggregateException: One or more errors ocurred. (A task was canceled.)

I'm trying to call LoadPickerData method to load the result in a Picker using async/await from the a ViewModel. I get the following error:
Error
System.AggregateException
Message=One or more errors occurred. (A task was canceled.)
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs:2027
at System.Threading.Tasks.Task`1[TResult].GetResultCore (System.Boolean waitCompletionNotification) [0x0002b] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs:496
at System.Threading.Tasks.Task`1[TResult].get_Result () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs:466
at EmployeeApp.Helpers.ConnectivityHelper.CheckConnectivity () [0x00049] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\Helpers\ConnectivityHelper.cs:34
at EmployeeApp.Helpers.ConnectivityHelper.get_IsConnected () [0x00000] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\Helpers\ConnectivityHelper.cs:21
at EmployeeApp.ViewModels.BaseViewModel.get_ServiceAreaStore () [0x00000] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\ViewModels\BaseViewModel.cs:27
at EmployeeApp.ViewModels.MailboxViewModel.GetPickerServiceArea () [0x0000f] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\ViewModels\MailboxViewModel.cs:60
at EmployeeApp.MailboxPage.LoadPickerData () [0x0002b] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\Views\MailBoxPage.xaml.cs:70
at EmployeeApp.MailboxPage.OnAppearing () [0x0002c] in F:\Workspace\BajaDev\MPA\_Project\EmployeeApp\Views\MailBoxPage.xaml.cs:31
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021
at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <06692e0cad5848598a0f46942a89e99f>:0
at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <06692e0cad5848598a0f46942a89e99f>:0
at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00009] in <06692e0cad5848598a0f46942a89e99f>:0
at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.44(intptr,intptr)
I'm trying to load the result of a GET request in a picker, but when I start the app the first time, it does not and I get the previous exception and the second time I run it I no longer get that error.
I looked for why and I was making the call of an asynchronous method in a constructor and that is bad code, I changed it to an OnAppearing () method but still that exception keeps coming out and I don't have idea the why yet
MailboxPage.xaml.cs
public MailboxPage()
{
InitializeComponent();
BindingContext = viewModel = new MailboxViewModel();
}
protected override async void OnAppearing()
{
base.OnAppearing();
await LoadPickerData();
}
private async Task<IEnumerable<ServiceArea>> LoadPickerData()
{
var vm = new MailboxViewModel();
var servicesareas = await vm.GetPickerServiceArea();
try
{
ServiceAreaPicker.ItemsSource = servicesareas.ToList();
ServiceAreaPicker.ItemDisplayBinding = new Binding("Name");
}
catch(AggregateException ae)
{
foreach (var e in ae.Flatten().InnerExceptions)
{
Debug.WriteLine($"{e.GetType().FullName} { e.Message}");
}
}
return servicesareas;
}
MailboxViewModel.cs
public async Task<IEnumerable<ServiceArea>> GetPickerServiceArea()
{
try
{
PickerItems = await ServiceAreaStore.GetPickerItemsAsync(true);
foreach (var item in PickerItems)
Items.Add(item);
}
catch (AggregateException ae)
{
foreach (var e in ae.Flatten().InnerExceptions)
{
Debug.WriteLine($"{e.GetType().FullName} { e.Message}");
}
}
return PickerItems;
}
ServiceAreaStoreAPI.cs
public async Task<IEnumerable<ServiceArea>> GetPickerItemsAsync(bool forceRefresh = false)
{
if (forceRefresh)
{
var json = await Client.GetStringAsync($"api/servicearea");
Servicesareas = await Task.Run(() => JsonConvert.DeserializeObject<IEnumerable<ServiceArea>>(json));
try
{
var success = LocalDatabase.AddItemsAsync(Servicesareas);
if (!success.Result)
{
//Log de fallo en la insercion de datos.
}
}
catch(AggregateException ae)
{
foreach (var e in ae.Flatten().InnerExceptions)
{
Debug.WriteLine($"{e.GetType().FullName} { e.Message}");
}
}
}
return Servicesareas;
}
In your ServiceAreaStoreAPI, you don't await a task which might be causing your issue since it'll continue on and return a canceled result.
var success = LocalDatabase.AddItemsAsync(Servicesareas);
If you have used the Task.Wait() method in the method body, then adding the async keyword to the method will fix this issue. Ex:
public async Task<ActionResult> Delete(int id) { }

Visual Studio App Center: System.NullReferenceException. How can I find the issue?

I don't know what is wrong with my code because everything seems to be correct. Therefore I want to use App Center to find the issue. I have an iOS application and a similar Android application. I uploaded the applications to the Apple App Store and Google Play Store. The applications are in alpha/test mode in both stores. After that, I installed the applications on my iOS and Android device and App Center logged the stack traces after the exception happened but I still cannot find the issue because the stack traces are not detailed enough.
On Android, PlayFab receipt validation always fails and I get this exception
System.NullReferenceException(Object reference not set to an instance of an object.).
On iOS, I think PlayFab receipt validation never fails but I sometimes get the same exception
System.NullReferenceException(Object reference not set to an instance of an object.).
The variables PurchaseditemCurrencyCode, PurchaseditemPurchasePrice, SignedData and Signature are not null and I think that they have the correct values because I can see in my Google Play account that the in-app product purchase is successful, but in the PlayFab Game Manager receipt validation fails.
PlayFab iOS and Android receipt validation
My values on Android:
PurchaseditemCurrencyCode = "EUR",
PurchaseditemPurchasePrice = 229,
SignedData = "{\"orderId\":..." and Signature = "eMU3xCYDD4L..."
My Android stack trace:
{
"length": 0,
"offset": 0,
"id": "63783019-f17b-47e1-8865-4e6290f43fbd",
"exception": {
"type": "System.NullReferenceException",
"message": "Object reference not set to an instance of an object",
"stackTrace": " at ggdgdgd.Android.Game1.ValidateAndroidReceiptAsync (System.String purchaseditemcurrencycode, System.Int32 purchaseditempurchaseprice, System.String signeddata, System.String signature) [0x000c3] in <11446e8c56cb4e78a270889c3b890601>:0 \n at ggdgdgd.Android.Game1.DoValidateAndroidReceiptAsync (System.String purchaseditemcurrencycode, System.Int32 purchaseditempurchaseprice, System.String signeddata, System.String signature) [0x0007a] in <11446e8c56cb4e78a270889c3b890601>:0 \n at ggdgdgd.Android.Game1.CheckPurchase (System.String productId) [0x0030a] in <11446e8c56cb4e78a270889c3b890601>:0 ",
"wrapperSdkName": "appcenter.xamarin"
},
My values on iOS:
PurchaseditemCurrencyCode = "EUR",
PurchaseditemPurchasePrice = 229,
SignedData = "MllVSAYJK..."
My iOS stack trace:
{
"length": 0,
"offset": 0,
"id": "71aef385-bb48-44d7-b59d-a53368c72c66",
"exception": {
"type": "System.NullReferenceException",
"message": "Object reference not set to an instance of an object",
"stackTrace": " at InapppurchaseTest.iOS.Game1.ValidateIOSReceiptAsync (System.String purchaseditemcurrencycode, System.Int32 purchaseditempurchaseprice, System.String signeddata, System.String signature) <0x1047fa730 + 0x002dc> in <f7cd0204315c470baa0e7963fe272e8d#b28b8328fb987f6bc8a6ed35dda86f7b>:0 \n at InapppurchaseTest.iOS.Game1.DoValidateIOSReceiptAsync (System.String purchaseditemcurrencycode, System.Int32 purchaseditempurchaseprice, System.String signeddata, System.String signature) <0x1047fa4e0 + 0x00183> in <f7cd0204315c470baa0e7963fe272e8d#b28b8328fb987f6bc8a6ed35dda86f7b>:0 \n at InapppurchaseTest.iOS.Game1.CheckPurchase (System.String productId) <0x1047f7a00 + 0x0041f> in <f7cd0204315c470baa0e7963fe272e8d#b28b8328fb987f6bc8a6ed35dda86f7b>:0 ",
"wrapperSdkName": "appcenter.xamarin"
},
It's impossible for me to find the issue with the current stack traces. Is it possible to get a more detailed stack trace in Visual Studio App Center?
I think that there is something wrong with PlayFabClientAPI.ValidateIOSReceiptAsync and PlayFabClientAPI.ValidateGooglePlayPurchaseAsync but I don't know what.
My Android and iOS code:
string SignedData = "", Signature = "", PurchaseditemCurrencyCode = "", PurchaseMessage = "";
int PurchaseditemPurchasePrice;
async void CheckPurchase(string productId)
{
bool purchaseIsSuccessful = await PurchaseItem(productId, "");
if (purchaseIsSuccessful == true)
{
try
{
if (Device.RuntimePlatform == Device.iOS)
{
if (productId == "Consumable11")
await DoValidateIOSReceiptAsync(PurchaseditemCurrencyCode, PurchaseditemPurchasePrice, SignedData);
}
else
{
if (Device.RuntimePlatform == Device.Android)
{
if (productId == "Consumable11")
await DoValidateAndroidReceiptAsync(PurchaseditemCurrencyCode, PurchaseditemPurchasePrice, SignedData, Signature);
}
}
}
catch (NullReferenceException ex)
{
Crashes.TrackError(ex);
}
}
else
{
PurchaseMessage = "Product could not be purchased";
}
}
public async Task DoValidateAndroidReceiptAsync(string purchaseditemcurrencycode, int purchaseditempurchaseprice, string signeddata, string signature)
{
await ValidateAndroidReceiptAsync(purchaseditemcurrencycode, purchaseditempurchaseprice, signeddata, signature);
}
private async Task ValidateAndroidReceiptAsync(string purchaseditemcurrencycode, int purchaseditempurchaseprice, string signeddata, string signature)
{
var result = await PlayFabClientAPI.ValidateGooglePlayPurchaseAsync(new ValidateGooglePlayPurchaseRequest()
{
CurrencyCode = purchaseditemcurrencycode,
PurchasePrice = (uint)purchaseditempurchaseprice,
ReceiptJson = signeddata,
Signature = signature
});
if (result.Error != null)
PlayFabMessage = "not successful");
else
PlayFabMessage = "successful");
}
public async Task DoValidateIOSReceiptAsync(string purchaseditemcurrencycode, int purchaseditempurchaseprice, string signeddata)
{
await ValidateIOSReceiptAsync(purchaseditemcurrencycode, purchaseditempurchaseprice, signeddata);
}
private async Task ValidateIOSReceiptAsync(string purchaseditemcurrencycode, int purchaseditempurchaseprice, string signeddata)
{
var result = await PlayFabClientAPI.ValidateIOSReceiptAsync(new ValidateIOSReceiptRequest()
{
CurrencyCode = purchaseditemcurrencycode,
PurchasePrice = purchaseditempurchaseprice,
ReceiptData = signeddata
});
if (result.Error != null)
PlayFabMessage = "not successful");
else
PlayFabMessage = "successful");
}
It seems that your result can be null and you are not checking that. That's the only point of failure that I can see.

Login-screen crashes with SQLite

I am trying to create a simple login window in MonoDevelop but it crashes as soon as I click the button.
Using the following command: SqliteConnection.CreateFile("*.sqlite"); I can identify that it runs until line 26 but not 28.
Here is my code:
using System;
using Gtk;
using Mono.Data.Sqlite;
using System.Data;
namespace BB
{
public partial class BBLogin : Gtk.Window
{
public BBLogin () :
base (Gtk.WindowType.Toplevel)
{
this.Build ();
}
private void btnLoginOnClick (object sender, EventArgs e)
{
SqliteConnection conn = new SqliteConnection();
conn.ConnectionString = "Data Source=BBUser.sqlite;Version=3;";
SqliteCommand command = new SqliteCommand();
command.CommandText = ("SELECT UserName FROM T_test WHERE UserName=#UserName AND Password=#Password");
command.Parameters.AddWithValue ("#UserName", txtUserName.Text);
command.Parameters.AddWithValue ("#Password", txtPassword.Text);
conn.Open ();
/*line 26*/ SqliteConnection.CreateFile("failsafe0.sqlite");
object result = command.ExecuteScalar();
SqliteConnection.CreateFile("failsafe1.sqlite");
conn.Close ();
SqliteConnection.CreateFile("failsafe2.sqlite");
string userNameLogin = Convert.ToString(result);
SqliteConnection.CreateFile("failsafe3.sqlite");
if (userNameLogin != "")
{
SqliteConnection.CreateFile("success.sqlite");
/*MessageDialog md = new MessageDialog ("Username was correct!");
md.Run ();
md.Destroy();*/
}
else
{
SqliteConnection.CreateFile("failed.sqlite");
/*MessageDialog md = new MessageDialog ("Username or password is incorrect!");
md.Run ();
md.Destroy();*/
}
}
}
}
And here is the full exception detail:
Exception in Gtk# callback delegate
Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: No connection associated with this command
at Mono.Data.Sqlite.SqliteCommand.InitializeForReader () [0x00000] in :0
at Mono.Data.Sqlite.SqliteCommand.ExecuteReader (CommandBehavior behavior) [0x00000] in :0
at Mono.Data.Sqlite.SqliteCommand.ExecuteScalar () [0x00000] in :0
at BB.BBLogin.btnLoginOnClick (System.Object sender, System.EventArgs e) [0x0006c] in /home/christian/BB/BB/BBLogin.cs:27
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in :0
--- End of inner exception stack trace ---
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in :0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in :0
at System.Delegate.DynamicInvokeImpl (System.Object[] args) [0x00000] in :0
at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) [0x00000] in :0
at System.Delegate.DynamicInvoke (System.Object[] args) [0x00000] in :0
at GLib.Signal.ClosureInvokedCB (System.Object o, GLib.ClosureInvokedArgs args) [0x00000] in :0
at GLib.SignalClosure.Invoke (GLib.ClosureInvokedArgs args) [0x00000] in :0
at GLib.SignalClosure.MarshalCallback (IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data) [0x00000] in :0
at GLib.ExceptionManager.RaiseUnhandledException(System.Exception e, Boolean is_terminal)
at GLib.SignalClosure.MarshalCallback(IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
at Gtk.Application.gtk_main()
at Gtk.Application.Run()
at BB.MainClass.Main(System.String[] args) in /home/christian/BB/BB /Program.cs:line 15
Best regards,
Chris
A command to be executed needs a command text and a connection to use. You provide the command text but not the binding to the connection
Just add this line before executing the command
command.Connection = conn;
Also I suggest you to use this code when dealing with disposable objects
string userNameLogin = string.Empty;
using(SqliteConnection conn = new SqliteConnection("Data Source=BBUser.sqlite;Version=3;"))
using(SqliteCommand command = new SqliteCommand(#"SELECT UserName
FROM T_test WHERE UserName=#UserName AND Password=#Password", conn))
{
command.Parameters.AddWithValue ("#UserName", txtUserName.Text);
command.Parameters.AddWithValue ("#Password", txtPassword.Text);
conn.Open ();
result = command.ExecuteScalar();
}
if(string.IsNullOrEmpty(result))
{
// Failure
}
else
{
// Success
}
This approach is better because you are guaranteed that the connection will be closed and disposed when the code exits from the using block also in case of exceptions. Note also that using the SqliteCommand overload that takes two parameters (the command text and the connection) you don't have to remember to set them afterwards.

Owin Self Host Will Not Start

using VS2015 with admin permissions my host starts and I can receive requests using Nancyfx.
IDisposable host = null;
IDisposable HostStart()
{
try
{
return WebApp.Start<Startup1>("http://*:7002");
}
catch (HttpListenerException ex)
{
throw new Exception(ex.Message);
}
}
When I make a setup project with the Visual Studio Extension and build and install and then run with admin privalages I don't get any exceptions but the server can not be found.I have turned off the firewall.I have now run out of ideas?
UPDATE: I am getting an exception
An exception has been thrown by the taget of invocation.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: Object reference not set to an instance of an object.
at CabbyTechOffice.Startup1.Configuration(IAppBuilder app)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Owin.Loader.DefaultLoader.<>c__DisplayClass12. <MakeDelegate>b__b(IAppBuilder builder)
at Owin.Loader.DefaultLoader.<>c__DisplayClass1. <LoadImplementation>b__0(IAppBuilder builder)
at Microsoft.Owin.Hosting.Engine.HostingEngine.ResolveApp(StartContext context)
at Microsoft.Owin.Hosting.Engine.HostingEngine.Start(StartContext context)
at Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.Starter.HostingStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.WebApp.StartImplementation(IServiceProvider services, StartOptions options)
at Microsoft.Owin.Hosting.WebApp.Start(StartOptions options)
at Microsoft.Owin.Hosting.WebApp.Start[TStartup](StartOptions options)
at Microsoft.Owin.Hosting.WebApp.Start[TStartup](String url)
at CabbyTechOffice.MAIN.HostStart()
It seems the null ref is in the startup:
public class MyBoot : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
CabbyTechOfficeConfig fig = ConfigUI.GetCabbyTechConfig();
if (fig == null)
{
throw new Exception("NO CONFIG");
}
ICabbytechOfficeDataAccess DB = null;
try
{
DB = ConnDBCreater.CreateDB(fig.DatabaseComputerName + "\\" + fig.DatabaseInstanceName, "taxidb", fig.DbPassword, 8);
IPEndPoint smsEP = null;
SmsCommsMob sms = null;
var comms = new ControlConnectAndSend(new IPEndPoint(IPAddress.Any, fig.DispatchFromPDAServerPort));
try
{
smsEP = new IPEndPoint(IPAddress.Parse(fig.SmsIp), fig.SmsPort);
sms = new SmsCommsMob(smsEP);
}
catch (Exception)
{
}
StateInjector stateInjector = new StateInjector(DB, comms, sms);
UdpBroadcasterJson.Send(new UDPCmd() { code = UDPCmd.commandsEnum.broadcastForDispatch }, stateInjector.UDPDispatchPort);
try
{
var comp = DB.CompaniesGet();
stateInjector.CompanyName = comp.company;
}
catch (Exception)
{
}
try
{
stateInjector.zones = DB.ZonesGet();
}
catch (Exception)
{
}
try
{
var locLog = new PdaLocLog();
var locLogger = new PdaLocLogger(DB, locLog);
stateInjector.locLogger = locLogger;
}
catch (Exception)
{
}
container.Register<IStateInjector, StateInjector>(stateInjector);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}
You have chains of try/catches with empty catch blocks.
try
{
var comp = DB.CompaniesGet();
stateInjector.CompanyName = comp.company;
}
catch (Exception)
{
}
try
{
stateInjector.zones = DB.ZonesGet();
}
catch (Exception)
{
}
try
{
var locLog = new PdaLocLog();
var locLogger = new PdaLocLogger(DB, locLog);
stateInjector.locLogger = locLogger;
}
catch (Exception)
{
}
this could leave stateInjector null which you then try to use.
You need to handle the catches in such a way that you can log any problems in those try/catches. Presumably there's a problem in the environment where it's failing, but you don't know that because of the empty catches.
There was problem in TinyIoc container in the NancyFx bootstrapper due to bad design in the exception handlers and a dependency was being injected null.

NullReferenceException in System.Threading.Tasks.Task.Schedule when using System.Net.WebClient

I posted another post with the same issue. There is a simple Xamarin solution on github that you can download and run here. Please do.
It seems that calling System.Net.WebClient.DownloadDataTaskAsync in DEBUG mode on my Xperia Z3 (it works just fine with an emulator) the first time throws a NullReferenceException in System.Threading.Tasks.Task.Schedule:
public async Task<String> DownloadString(String url)
{
if (UseAuth)
webclient.Headers.Set("Authorization", TokenType + " " + AccessToken);
else if (!UseAuth && webclient.Headers["Authorization"] != null)
webclient.Headers.Remove("Authorization");
String response = "";
try
{
byte[] data = await webclient.DownloadDataTaskAsync(url);
response = Encoding.UTF8.GetString(data);
}
catch (WebException e)
{
response = new StreamReader (e.Response.GetResponseStream ()).ReadToEnd ();
ErrorResponse = JsonConvert.DeserializeObject<ErrorResponse> (response, settings);
if (ErrorResponse.Error.Status == 401 && ErrorResponse.Error.Message == "The access token expired") {
Console.WriteLine ("Error: " + ErrorResponse.Error.Status + " - " + ErrorResponse.Error.Message);
}
}
return response;
}
This code solves the problem, but I think it's a dirty fix and it doesn't really address the underlying problem.
public async Task<String> DownloadString(String url)
{
if (UseAuth)
webclient.Headers.Set("Authorization", TokenType + " " + AccessToken);
else if (!UseAuth && webclient.Headers["Authorization"] != null)
webclient.Headers.Remove("Authorization");
String response = "";
var failCount = 2;
for (int i = 0; i <= failCount; i++)
{
try
{
byte[] data = await webclient.DownloadDataTaskAsync(url);
response = Encoding.UTF8.GetString(data);
}
catch (WebException e)
{
if (i == failCount)
{
response = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
ErrorResponse = JsonConvert.DeserializeObject<ErrorResponse>(response, settings);
if (ErrorResponse.Error.Status == 401 && ErrorResponse.Error.Message == "The access token expired")
{
Console.WriteLine ("Error: " + ErrorResponse.Error.Status + " - " + ErrorResponse.Error.Message);
}
// Break out of the loop
break;
}
}
}
return response;
}
System.NullReferenceException: Object reference not set to an instance
of an object System.Threading.Tasks.Task.Schedule (Boolean
throwException) [0x00000] in :0 at System.Threading.Tasks.Task.Start
(System.Threading.Tasks.TaskScheduler scheduler) [0x00000] in :0 at
System.Threading.Tasks.TaskFactory.StartNew[WebRequest] (System.Func1
function, CancellationToken cancellationToken, TaskCreationOptions
creationOptions, System.Threading.Tasks.TaskScheduler scheduler)
[0x00000] in :0 at
System.Threading.Tasks.TaskFactory.StartNew[WebRequest] (System.Func1
function) [0x00000] in :0 at System.Net.WebClient.SetupRequestAsync
(System.Uri address) [0x00000] in :0 at
System.Net.WebClient+c__async0.MoveNext () [0x00000] in :0 --- End of
inner exception stack trace --- at
System.Net.WebClient+c__async0.MoveNext () [0x00000] in :0 --- End of
stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw ()
[0x00000] in :0 at
System.Runtime.CompilerServices.TaskAwaiter`1[System.Byte[]].GetResult
() [0x00000] in :0 at
SpotifyWebAPI.SpotifyWebAPIClass+c__async1A.MoveNext () [0x00133]
System.Net.WebException
Here is a screenshot from Xamarin Studio
The problem only happens with my device and DEBUG build mode. In RELEASE it works perfectly and on the emulator it works on both DEBUG and RELEASE.
As stated in the original post, calling System.WebClient.DownloadDataTaskAsync a second, third or Nth time all result in normal behaviour. It also only occur when I use a Spotify Android SDK Java binding project and call OpenLoginWindow() (which opens another activity, logs in and returns successfully) prior to calling DownloadDataTaskAsync.

Categories

Resources