1

I'm following along with the tutorial on YouTube for N=2: Kittens and Lists

The KittenView is blowing up when it hits OnCreate()

Cirrious.CrossCore.Exceptions.MvxException: Failed to load ViewModel for type MyApp.Core.ViewModels.KittenViewModel from locator MvxDefaultViewModelLocator

It seems that it is not able to resolve the service (IKittenGenesisService), because when I add an empty constructor, the app runs with no errors. But obviously the view won't work properly without it's dependencies.

The same solution also has an earlier tutorial, which includes the FirstViewModel, which uses an ICalculationService. This service resolves fine and runs, so I know the MVVM IoC is working. But I can't find any differences between the two. It doesn't help that I cannot debug into a PCL project, but that is a different issue.

public class App: MvxApplication
{
    public override void Initialize()
    {
        CreatableTypes()
            .EndingWith("Service")
            .AsInterfaces()
            .RegisterAsLazySingleton();
        RegisterAppStart<KittenViewModel>();
    }
}

[Activity(Label = "View for KittenViewModel")]
public class KittenView : MvxActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.KittenView);
    }
}

public class KittenViewModel: MvxViewModel
{
    public KittenViewModel(IKittenGenesisService service)
    {
        var kittenList = new List<Kitten>();
        for (var i = 0; i < 100; i++)
        {
            var newKitten = service.CreateNewKitten(i.ToString());
            kittenList.Add(newKitten);
        }
        Kittens = kittenList;
    }

    private List<Kitten> _kittens;
    public List<Kitten> Kittens
    {
        get { return _kittens; }
        set
        {
            _kittens = value;
            RaisePropertyChanged(() => Kittens);
        }
    }
}

public class KittenGenesisService: IKittenGenesisService
{
    private readonly List<string> _names;
    private readonly Random _random;

    public KittenGenesisService()
    {
        _random = new Random();
        _names = new List<string>()
        {
            "Tiddles",
            "Amazon",
            "Pepsi",
            "Solomon",
            "Butler",
            "Snoopy",
            "Harry",
            "Holly",
            "Paws"
        }; 
    }

    public Kitten CreateNewKitten(string extra = "")
    {
        return new Kitten()
            {
                Name = _names[Random(_names.Count)] + extra,
                ImageUrl = string.Format("http://placekitten.com/{0}/{0}"),
                Price = RandomPrice()
            };
    }

    public int Random(int count)
    {
        return _random.Next(count);
    }

    public int RandomPrice()
    {
        return Random(23) + 3;
    }
}

Yet these work fine:

[Activity(Label = "View for FirstViewModel")]
public class FirstView : MvxActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.FirstView);
    }
}

public class FirstViewModel: MvxViewModel
{
    private readonly ICalculationService _calculationService;

    public FirstViewModel(ICalculationService calculationService)
    {
        _calculationService = calculationService;
        _generosity = 20;
        _subTotal = 100;
        Recalc();
    }
    // more code
}

Here is a unit test I added, it immediately blows up with a null reference exception when it tries to new up a KittenViewModel, the KittenGenesisService constructor is called fine.

[TestFixture]
public class KittenViewModelTests
{
    private KittenViewModel _sut;

    [SetUp]
    public void given_a_kittenviewmodel()
    {
        _sut = new KittenViewModel(new KittenGenesisService());
    }

    [Test]
    public void the_view_model_contains_kittens()
    {
        _sut.Kittens.Should().NotBeEmpty();
    }
}
theB
  • 6,450
  • 1
  • 28
  • 38
Ryan Langton
  • 6,294
  • 15
  • 53
  • 103

1 Answers1

3

I think it might be worth checking some if the basics like:

  • is there a public class which implements the genesis service?
  • does it have a public parameterless constructor? (Or a constructor which could itself be constructed)

If those things look ok, then it's probably worth trying some debugging techniques:

  • enabling trace so that you can see the inner details of the problems - see MvvmCross Mvx.Trace usage
  • experimenting with some test code in your app.cs - after the services have been registered, does Mvx.CanResolve<IKittenGenesisService>() return true?
  • trying to call your view model code from a unit test - does that work ok?
Community
  • 1
  • 1
Stuart
  • 66,722
  • 7
  • 114
  • 165
  • Thanks for the tips. I've added my KittenGenesisService code as well as a unit test. It blows up when trying to call the KittenViewModel constructor. – Ryan Langton Jun 26 '13 at 13:28
  • 1
    If it really "blows up" then please post a video - as I'd like to watch. If instead it just throws an exception, then check the exception error message and the line it's throw from - as that may tell you what is actually going wrong.... my guess would be that it will be a `FormatException` caused by `string.Format("http://placekitten.com/{0}/{0}")` – Stuart Jun 26 '13 at 13:32
  • Don't think that points to the problem though, I have a similar unit test for FirstViewModel and it throws an exception in the same place. Something under the covers with mvvm not letting me new up a viewmodel for unit testing. – Ryan Langton Jun 26 '13 at 13:37
  • Ok you found the problem, it was a formatexception. I'd like to know how people deal with this though. It seems unnecessarily difficult to track down simple bugs. Debugging doesn't work with PCL. Is there a way to do the unit tests? As I mentioned my unit tests wouldn't work at all and they're not doing anything other than trying to construct a view model. – Ryan Langton Jun 26 '13 at 13:39