Why is my app crashing in System.Windows.ni.dll on startup with no useful stack trace? (seemingly after adopting Caliburn.Micro) - windows-phone-8

Start with the default "empty" Windows Phone App project (Windows Phone 8). Let's call it BlackAdder for fun.
Add Caliburn.Micro from Nuget
Move MainPage.xaml to the Views subdirectory and create a matching ViewModel in ViewModels\MainPageViewModel.cs
Fix the namespace for MainPage to Blackadder.Views in both the .xaml and .xaml.cs files
Update App.xaml
<Application
x:Class="BlackAdder.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:local="clr-namespace:BlackAdder">
<Application.Resources>
<local:Bootstrapper x:Key="bootstrapper"/>
</Application.Resources>
</Application>
Update App.xaml.cs
public partial class App : Application
{
public static PhoneApplicationFrame RootFrame { get; private set; }
public App()
{
InitializeComponent();
// Show graphics profiling information while debugging.
if (Debugger.IsAttached)
{
...
}
}
}
Create Bootstrapper.cs
public class Bootstrapper : PhoneBootstrapper
{
private PhoneContainer container;
protected override void Configure()
{
container = new PhoneContainer();
container.RegisterPhoneServices(RootFrame);
container.PerRequest<MainPageViewModel>();
AddCustomConventions();
}
protected static void AddCustomConventions()
{
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
When we run the app, it crashes in a very weird place.
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll
Additional information: Exception has been thrown by the target of an invocation.
There is no inner exception, and the stack trace is (seemingly) useless.
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke()
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority)
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context)
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args)
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult)

It turns out this has nothing to do with caliburn.micro at all. The problem lies in Properties\WMAppManifest.xaml.
After moving MainPage.xaml to the Views subdirectory, the Navigation Page setting (found on the first tab, Application UI) needs to be updated to Views\MainPage.xaml

Related

Blazor Server - 'Code Behind' pattern: OnInitializedAsync(): no suitable method found to override

I have a Blazor (Server) application which runs perfectly fine, and which adheres to all rules set by Microsoft.CodeAnalysis.FxCopAnalyzers and StyleCop.Analyzers.
A heavily cut-down razor page is as follows:
#inherits OwningComponentBase<MyService>
#inject IModalService ModalService
#inject IJSRuntime JSRuntime
// UI code
#code
{
private readonly CancellationTokenSource TokenSource = new CancellationTokenSource();
ElementReference myElementReferenceName;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await this.myElementReferenceName.FocusAsync(this.JSRuntime);
}
protected override async Task OnInitializedAsync()
{
....
}
public void Dispose()
{
this.TokenSource.Cancel();
}
protected void ShowModalEdit(object someObject)
{
.....
Modal.Show<MyPage>("Edit", parameters);
}
}
Note#1: I used #inherits OwningComponentBase<MyService> based on Daniel Roth's suggestion
Note#2: I am using the Chris Sainty's Modal component component
However, when I try to move all the code from the #code {...} section to a"Code Behind" partial class ("MyPage.razor.cs"), then I run into the following errors....
'MyPage' does not contain a definition for 'Service' and no accessible
extension method 'Service' accepting .....
'MyPage.OnAfterRenderAsync(bool)': no suitable method found to override
'MyPage.OnInitializedAsync()': no suitable method found to override
The type 'MyPage' cannot be used as type parameter 'T' in the generic
type or method 'IModalService.Show(string, ModalParameters,
ModalOptions)'. There is no implicit reference conversion from
'MyPage' to 'Microsoft.AspNetCore.Components.ComponentBase'.
Suggestions?
Your MyPage.razor.cs should inherit from ComponentBase class and your Mypage.razor should inherit from MyPage.razor.cs.
In your "code-behind" class you should use [Inject] attribute for every service you are injecting and make them at least protected properties to be able to use them in your razor components.
Below is an example from one of my testing apps, please note this uses .net-core 3.0, in 3.1 you can use partial classes.
Index.razor
#page "/"
#inherits IndexViewModel
<div class="row">
<div class="col-md">
#if (users == null)
{
<p><em>Hang on while we are getting data...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th class="text-danger">Id</th>
<th class="text-danger">Username</th>
<th class="text-danger">Email</th>
<th class="text-danger">FirstName</th>
<th class="text-danger">LastName</th>
</tr>
</thead>
<tbody>
#foreach (var user in users)
{
<tr>
<td>#user.Id</td>
<td>#user.Username</td>
<td>#user.Email</td>
<td>#user.FirstName</td>
<td>#user.LastName</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
IndexViewModel.cs
public class IndexViewModel : ComponentBase, IDisposable
{
#region Private Members
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private bool disposedValue = false; // To detect redundant calls
[Inject]
private IToastService ToastService { get; set; }
#endregion
#region Protected Members
protected List<User> users;
[Inject] IUsersService UsersService { get; set; }
protected string ErrorMessage { get; set; }
#endregion
#region Constructor
public IndexViewModel()
{
users = new List<User>();
}
#endregion
#region Public Methods
#endregion
#region Private Methods
protected override async Task OnInitializedAsync()
{
await GetUsers().ConfigureAwait(false);
}
private async Task GetUsers()
{
try
{
await foreach (var user in UsersService.GetAllUsers(cts.Token))
{
users.Add(user);
StateHasChanged();
}
}
catch (OperationCanceledException)
{
ShowErrorMessage($"{ nameof(GetUsers) } was canceled at user's request.", "Canceled");
}
catch (Exception ex)
{
// TODO: Log the exception and filter the exception messages which are displayed to users.
ShowErrorMessage(ex.Message);
}
}
private void ShowErrorMessage(string message, string heading ="")
{
//ErrorMessage = message;
//StateHasChanged();
ToastService.ShowError(message, heading);
}
private void ShowSuccessMessage(string message, string heading = "")
{
ToastService.ShowSuccess(message, heading);
}
protected void Cancel()
{
cts.Cancel();
}
#endregion
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
cts.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
TLDR
Make sure the namespace in your razor.cs file is correct
Longer explanation
In my case, I got this error when I put the class in the wrong namespace. The page.razor.cs file was in the same directory as the page.razor file and it contained a partial class as accepted by the October 2019 update.
However, even though the files were located in path/to/dir, page.razor.cs had a namespace of path.to.another.dir, which led to this error being thrown. Simply changing the namespace to path.to.dir fixed this error for me!
Came across this error when I used partial class approach and I was trying to scaffold Identity. I changed to base class aprroach it was resolved.
partial class I was using
after adding a component say MyComponent, add a class MyComponent.razor.cs
for injecting services
use
[Inject]
public BuildingServices Services { get; set; }
for base class approach
after adding a component say MyComponent, add a class MyComponent.razor.cs
change the class name and make it inherit from componentBase
MyComponentBase : ComponentBase
and place this at the top of MyComponent.razor
#inherits MyComponentBase
Use protected keyword to make your methods accessible
All the above points are very true. FWIW, and just to add a weird thing that I was finding with this issue; I could not get that error to go away. Everything was declared as it should be. Once you have ruled out all potential coding issues, I have found exiting VS, coming back in, and rebuilding clears it up. It is almost like VS just will not let go of that error.
It took two days of cleaning, rebuilding, ... and it turned out to be a cut and paste error. I copied the razor file from another, similar class, and left this at the top by mistake:
#inject Microsoft.Extensions.Localization.IStringLocalizer<Person> localizer
'Person' was the wrong class, it wasn't defined by any of the include statements. For some strange reason the only error was "OnInitialized() No method found to override."
I found this when upgrading to 6.0. I had to switch from using base classes to using partial classes!

Trying to integrate facebook with libgdx, where to implement this code because there is no "module:app" is present?

According to facebook:-
"Add the following to the dependencies {} section of your build.gradle (module: app) file to compile the latest version of the Facebook SDK:
implementation 'com.facebook.android:facebook-android-sdk:[4,5)'"
I don't see any module named app in the android studio project.where to add above line?
module:app in this case just means the main android app. So you should add the dependency to the android module.
Then I bet your next question how to use this library from the core since the Android module depends on the core module and not vice versa so you do not have access to the library in the core project. One way is to pass a contract to the platform launchers where each implements it differently.
//Simple contract
public interface IPlatformContract {
void runThis();
}
// Core project (MyGame)
private IPlatformContract platformContract;
public MyGame(IPlatformContract platformContract) {
this.platformContract = platformContract;
}
//DesktopLauncher
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
// Launch desktop with it's own implementation of the contract.
new LwjglApplication(new MyGame(new IPlatformContract() {
#Override
public void runThis() {
System.out.println(" I run on desktop!");
}
}), config);
}
//AndroidLauncher, different way. Here the class itself implements the contract.
public class AndroidLauncher extends AndroidApplication implements IPlatformContract{
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new LibgdxTestEnvironment(this), config);
}
#Override
public void runThis() {
System.out.println("I run on android!");
}
}
You can pass along the contract to other classes like screens in your core project so you have access to it. You can even make a Singleton.

Android WebView: Exceptions are not caught

I followed the approach of defining a Thread.setDefaultUncaughtExceptionHandler in the onCreate Method of my application. This application is also defined as such in the manifest. The handler is also created but its handler is never called although I do see a JavaScript error in the LogCat.
12-19 03:02:58.630: I/chromium(1569): [INFO:CONSOLE(45)] "Uncaught ReferenceError: $contactArea is not defined", source: file:///android_asset/DefaultPage.html (45)
The handler is defined in my app:
public class HPAWebView extends Application {
private static Context context;
#Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, final Throwable ex) {
// Custom code here to handle the error.
Toast.makeText(HPAWebView.getAppContext(), "Oh no! " + ex.getMessage(), Toast.LENGTH_SHORT).show();
}
});
HPAWebView.context = getApplicationContext();
}
public static Context getAppContext() {
return HPAWebView.context;
}
}
...and this application is stated in the manifest:
<application
android:name="sap.com.prototype.webview.HPAWebView"
Your custom exception handler is not able to catch JavaScript exceptions. You could register a JavaScript interface in your WebView and then call it in response to the JavaScript error event. Let me know if this makes sense or I can clarify more.

registering open generic decorators for typed implementations in castle windsor

While trying to coerce Windsor into wrapping an implementation with a random number of decorators, i've stumbled upon the following:
i have 3 decorators and an implementation all using the same interface.
if you run this code, windsor resolves icommandhandler<stringcommand> as implementation, which, as far as i can tell, is expected behaviour, because the typed implementation can not be registered with the open typed decorators.
However, if you uncomment the line container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());, all three decorators will be used to resolve implementation, which is the desired result (sort of : ).
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));
//uncomment the line below and watch the magic happen
//container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());
var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
var command = new stringCommand();
stringCommandHandler.Handle(command);
Console.WriteLine(command.s);
Console.ReadKey();
}
}
public interface ICommandHandler<T>
{
void Handle(T t);
}
public class stringCommand
{
public string s { get; set; }
}
public abstract class Decorator<T> : ICommandHandler<T>
{
public abstract void Handle(T t);
};
public class Decorator1<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator1(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator1;";
_handler.Handle(t);
}
}
public class Decorator2<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator2(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator2;";
_handler.Handle(t);
}
}
public class Decorator3<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator3(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator3;";
_handler.Handle(t);
}
}
public class implementation : ICommandHandler<stringCommand>
{
public void Handle(stringCommand t)
{
t.s += "implementation;";
}
}
Why exactly is this happening, is this a feature of windsor that i am not aware of? Is there perhaps a different way to achieve the same effect? (without resorting to reflection)
When windsor tries to resolve a component it will first try to resolve the more specific interface. So when you register Component.For it will prefer to resolve this over an open generic type.
If the same interface is registered multiple times, it will use the first one specified.
So if you don't uncommment the line your application will resolve implementation since this is the most specific component.
If you do uncomment the line decorator1 will be resolved and indeed the magic starts. The decorator will now start looking for the first registered component that satisfies it's constructor, in this case that would be decorator1 again (you did notice that your output show decorator1 2 times ?). Which will the resolve the next registered component and so on till it comes to the actual implementation.
So the only thing I can think about is not registering decorator1 as an open generic but as a specific type.
Kind regards,
Marwijn.

Using MvvmCross from content providers and activities

I am trying to use MvvmCross v3 in one of my applications which consists of activities, content providers and broadcast receivers. However, I am not quite succeeding.
The application consists of a Core PCL which contains logic, models and viewmodels and a Droid application which contains all MonoDroid-specific stuff.
In Core I have an App:MvxApplication class and in Droid I have a Setup:MvxSetup class which creates an App-instance and initialises stuff.
I can use the IOC parts with content providers, broadcast receivers and non-Mvx-activities without problems. When I now want to add an MvxActivity it falls apart.
When the Mvx Activity launches I get an exception "Cirrious.CrossCore.Exceptions.MvxException: MvxTrace already initialized".
Obviously I am initialising things in the wrong order / wrong place. But, I need a pointer in the right direction.
My App Class
public class App
: MvxApplication
{
public override void Initialize()
{
base.Initialize();
InitialisePlugins();
InitaliseServices();
InitialiseStartNavigation();
}
private void InitaliseServices()
{
CreatableTypes().EndingWith("Service").AsInterfaces().RegisterAsLazySingleton();
}
private void InitialiseStartNavigation()
{
}
private void InitialisePlugins()
{
// initialise any plugins where are required at app startup
// e.g. Cirrious.MvvmCross.Plugins.Visibility.PluginLoader.Instance.EnsureLoaded();
}
}
And my setup class
public class Setup
: MvxAndroidSetup
{
public Setup(Context applicationContext)
: base(applicationContext)
{
}
protected override IMvxApplication CreateApp()
{
return new App();
}
protected override IMvxNavigationSerializer CreateNavigationSerializer()
{
return new MvxJsonNavigationSerializer();
}
public override void LoadPlugins(Cirrious.CrossCore.Plugins.IMvxPluginManager pluginManager)
{
pluginManager.EnsurePluginLoaded<Cirrious.MvvmCross.Plugins.Json.PluginLoader>();
base.LoadPlugins(pluginManager);
}
public void RegisterServices()
{
// I register a bunch of singletons here
}
// The following is called from my content provider's OnCreate()
// Which is the first code that is run
public static void DoSetup(Context applicationContext)
{
var setup = new Setup(applicationContext);
setup.Initialize();
setup.RegisterServices();
}
My Content provider's OnCreate():
public override bool OnCreate()
{
Log.Debug(Tag, "OnCreate");
_context = Context;
Setup.DoSetup(_context);
return true;
}
My MvxActivity:
[Activity(Label = "#string/ApplicationName", MainLauncher = true)]
[IntentFilter(new[] { "Settings" })]
public class SettingsView
: MvxActivity
{
public new SettingsViewModel ViewModel
{
get { return (SettingsViewModel) base.ViewModel; }
set { base.ViewModel = value; }
}
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.Page_SettingsView);
}
}
Short answer (I'm in an airport on mobile)
all the mvx android views will check the setup singleton has been created - https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Droid/Platform/MvxAndroidSetupSingleton.cs (vnext tree - but similar on v3)
so if you are creating a setup, but not setting this singleton, then you will get a second setup created when you first show a view
i suspect you can just get your setup created via the singleton class, but if this isn't flexible enough for your needs, then please log an issue on github
would also love to see some blogging about this - I've not used custom content providers much (at all!)