Search code examples
c#genericsasp.net-core-mvcasp.net-mvc-viewmodel

Generic Method public T Method() where T : BaseViewModel always returns NULL


I am having a brain-fart at the moment. I am trying to have a BaseController for all my controllers. With that, I want to have a method to create the various ViewModels for the Views that all inherit from a BaseViewModel and set properties that are in the BaseViewModel. The properties in the BaseViewModel are set depending on which controller action is being used so I cannot just set them in the BaseViewModel constructor.

However, I keep getting a Null value returned when I call it.

Here is the method in the BaseController:

/// <summary>
/// Instantiate a ViewModel
/// </summary>
/// <typeparam name="T">ViewModel that inherits <see cref="BaseViewModel"/></typeparam>
/// <returns></returns>
public T SetupViewModel<T>(int? currentTrack = null) where T : BaseViewModel
{
     // Return a new instance of a ViewModel
    return new BaseViewModel(_Context)
    {
         // Set the current track
         CurrentTrack = currentTrack,
    } as T;
}

I call it like this in public class HomeController : BaseController:

/// <summary>
/// Main page
/// </summary>
/// <returns></returns>
public IActionResult Index()
{
    // Instantiate the view model
    var vm = SetupViewModel<HomeViewModel>();
 
    // Setup the repositories
    vm.SetupRepositories();

    // Load the tables base on the user
    vm.Load(GetLoggedInUserName());

    // Return the view with model
    return View(vm);
}

When I break at vm.SetupRepositories(), the variable vm is NULL.

EDIT (response to comments about new() I get this when I try the new()

Screenshot


Solution

  • So as I thought, it was something small. Thank you haim770 (comment for OP) for pointing the way.

    My BaseViewModel has two constructors (a default and one that accepts the parameter to set the context. So instead I just needed to set the context as a property and not through the parameter. Also, instantiate a new T instead of the BVM.

    /// <summary>
    /// Instantiate a ViewModel
    /// </summary>
    /// <typeparam name="T">ViewModel that inherits <see cref="BaseViewModel"/></typeparam>
    /// <returns></returns>
    public T SetupViewModel<T>(int? currentTrack = null) where T : BaseViewModel, new()
    {
         // Return a new instance of a ViewModel
        return new T()
        {
             // Set the Context
             Context = _Context,
    
             // Set the current track
             CurrentTrack = currentTrack,
        } as T;
    }