Xamarin Forms: White screen between page push and pop solved

If you are experiencing white screen when pushing to Navigation or Modal stack on Android, read on.

I’m not sure is this a bug in Xamarin Forms or not, but I guess this is, because it comes only in certain scenarios, and not always.

What is happening, how do you notice this error?

You have got a NavigationPage. You are pushing a new page to the navigationstack, and the page is not getting rendered, only a blank white screen displays.

If you are rotating the device, the page is getting rendered well.

My environment was:
Xamarin.Forms: 4.8 up to 5.0
Device: Samsung Galaxy A12
Visual Studio 2019 Professional with Xamarin.Android SDK 11.4.0.5

Solution

Always invoke the INavigation’s methods on the applications Main Thread. UI changes must go always on the UI thread of the application.

Create a class which wraps the INavigation presented by your Views. It’s handy to store a reference in this class to the Applications Current MainPage’s INavigation instance, so try to build your code to supply the actual INavigation Instance every time to this class when the application’s mainpage is set.

	public class NavigationDispatcher : INavigation
	{
		private INavigation _navigation;

		public IReadOnlyList<Page> ModalStack => _navigation?.ModalStack;

		public IReadOnlyList<Page> NavigationStack => _navigation?.NavigationStack;

		private void SetNavigation(INavigation navigation)
		{
			_navigation = navigation;
		}

		public void InsertPageBefore(Page page, Page before)
		{
			_ = Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(() =>
			  {
				  _navigation.InsertPageBefore(page, before);
			  });
		}

		public Task<Page> PopAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopAsync();
			});
		}

		public Task<Page> PopAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopAsync(animated);
			});
		}

		public Task<Page> PopModalAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopModalAsync();
			});
		}

		public Task<Page> PopModalAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				return await _navigation.PopModalAsync(animated);
			});
		}

		public Task PopToRootAsync()
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PopToRootAsync();
			});
		}

		public Task PopToRootAsync(bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PopToRootAsync(animated);
			});
		}

		public Task PushAsync(Page page)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushAsync(page);
			});
		}

		public Task PushAsync(Page page, bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushAsync(page, animated);
			});
		}

		public Task PushModalAsync(Page page)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushModalAsync(page);
			});
		}

		public Task PushModalAsync(Page page, bool animated)
		{
			return Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
			{
				await _navigation.PushModalAsync(page, animated);
			});
		}

		public void RemovePage(Page page)
		{
			_ = Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(() =>
			  {
				  _navigation.RemovePage(page);
			  });
		}
	}

Remarks

Consider a check for the current thread in the methods body.
If they are being executed in the main thread, you won’t need to switch to the main again
.

Bug is reported on Github: https://github.com/xamarin/Xamarin.Forms/issues/11993

D365 BC OData: Filtering for boolean fields in the correct way

Somehow, Microsoft’s documentation for using OData service in Business Central does not give enough information for the proper usage of the OData’s filter for boolean fields. That’s when Postman becomes your best friend, and you are starting arguing about how to compare equality to a boolean field using filters. Oh, have you looked up stackoverflow already? Some say, that you will need to make a new column in the page, and put the boolean value as a string, to be able to use it in filter with string compare!! 😀 Others say, you will need to send the equality compare statement with binary marks, 1 for true and 0 for false.
None of the solutions mentioned will work. I mean the string compare method should work, but I recommend to use it for no one.

My test results

// Request 1
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq 'Yes'

"code": "BadRequest",
        "message": "A binary operator with incompatible types was detected. Found operand types 'Edm.Boolean' and 'Edm.String' for operator kind 'Equal'.  CorrelationId:  c409ac25-b53a-4fcd-ac7d-c87fe6999666."

// Request 2
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq Yes

 "code": "BadRequest",
        "message": "Could not find a property named 'Yes' on type 'NAV.<<TABLENAME>>'.  CorrelationId:  beb9f4bb-cec5-4d40-84b9-9802d45a5fa9."

// Request 3
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq yes

        "code": "BadRequest",
        "message": "Could not find a property named 'yes' on type 'NAV.<<TABLENAME>>'.  CorrelationId:  3f96be5e-f489-43fe-a24c-ea8255cc1cc1."

// Request 4
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq 1

 "code": "BadRequest",
        "message": "A binary operator with incompatible types was detected. Found operand types 'Edm.Boolean' and 'Edm.Int32' for operator kind 'Equal'.  CorrelationId:  d9f9a696-0f6d-48c4-89f5-60d784126810."

// Request 5
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq True

    "error": {
        "code": "BadRequest",
        "message": "Could not find a property named 'True' on type 'NAV.<<TABLENAME>>'.  CorrelationId:  b567a22c-6fa8-4333-801d-1b3deb42a7fb."

// Request 6
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq 'True'

        "code": "BadRequest",
        "message": "A binary operator with incompatible types was detected. Found operand types 'Edm.Boolean' and 'Edm.String' for operator kind 'Equal'.  CorrelationId:  94ae066f-8a9f-4c39-8c4e-667c8d15579f."

// Request 7
https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq 'true'

        "code": "BadRequest",
        "message": "A binary operator with incompatible types was detected. Found operand types 'Edm.Boolean' and 'Edm.String' for operator kind 'Equal'.  CorrelationId:  f08024a2-00f1-474c-957d-8ce1c15bf452."

The solution

The boolean operators in OData filters are CASE SENSITIVE, and marked with true and false. You won’t need to put in single quotation marks, or use binary marks like 1 or 0. The solution is simple:

// Request 8: 

https://<<HOST>>/ODataV4/Company('CRONUS International Ltd.')/<<TABLENAME>>?$select=Entry_No,Item_No,Lot_No,Positive,Qty_to_Handle_Base,Quantity_Base,Serial_No,Source_ID,Source_Ref_No&$filter=Entry_No eq 10 and Positive eq true

// Response 8:

    "value": [
        {
            "Entry_No": 10,
            "Positive": true,
            "Serial_No": "555",
            "Lot_No": "555",
            "Quantity_Base": 1,
            "Qty_to_Handle_Base": 1,
            "Item_No": "1",
            "Source_Ref_No": 10000,
            "Source_ID": "1001"
        }

.NET Core: UseUrls seems getting ignored error

If you are facing the issue, that the Host.CreateDefaultBuilder’s ConfigureWebHostDefaults’s UseUrls method is getting ignored, and all the environment variables and launchsettings.json completly getting ignored by the .NET core application, its always using the default port of http : 5000 and the https 5001, follow the instructions

Are you using configuration builder before calling the configurewebhostdefaults?

				ConfigurationBuilder cfgBuilder = new ConfigurationBuilder();
				cfgBuilder.AddEnvironmentVariables("CONFIGPREFIX_");
				IConfigurationRoot configuration = cfgBuilder.Build();

And are you passing the built configuration to ConfigureAppConfiguration ? Like that:

					.ConfigureAppConfiguration(builder =>
					{
						builder.Sources.Clear();
						builder.AddConfiguration(configuration);
					})

Then remove the ConfigureAppConfiguration call, and it will work..

No idea how to work around

Docker error: CTC1015 Docker command failed with exit code 125.

If the Visual Studio’s output of the build on windows says the following:

docker: Error response from daemon: failed to create endpoint <ProjectName> on network nat: failed during hnsCallRawResponse: hnsCall failed in Win32: The process cannot access the file because it is being used by another process. (0x20).
If the error persists, try restarting Docker Desktop.

Solution

Go to your Services administration panel (by running services.msc)

Stop the following services:
– HNS (Host Network Service)
– docker (Docker Engine)

Then restart them in the order of stopping.