Monday, February 21, 2011

redirectToAction results in null model

I have 2 actions on a controller:

public class CalculatorsController : Controller
{
    //
    // GET: /Calculators/

    public ActionResult Index()
    {
        return RedirectToAction("Accounting");
    }


    public ActionResult Accounting()
    {
        var combatants = Models.Persistence.InMemoryCombatantPersistence.GetCombatants();
        Debug.Assert(combatants != null);
        var bvm = new BalanceViewModel(combatants);
        Debug.Assert(bvm!=null);
        Debug.Assert(bvm.Combatants != null);
        return View(bvm);
    }

}

When the Index method is called, I get a null model coming out. When the Accounting method is called directly via it's url, I get a hydrated model.

From stackoverflow
  • This is less an answer than a workaround. I am not sure why you are getting a null model as it looks like it should work. In fact, I can confirm the behavior you are seeing when I try it out myself. [EDIT: I discovered a flaw in my initial test code that was causing my own null model. Now that that is corrected, my test works fine using RedirectToAction.] If there is a reason for it, I don't know it off the top of my head.

    Now for the workaround...I assume that you are doing it this way since the default route sends all traffic to http://www.domain.com/Calculators to "Index". So why not create a new route like this:

    routes.MapRoute(
      "Accounting",
      "Calculators/{action}/",
      new { controller = "Calculators", action = "Accounting" }
    );
    

    This route specifies the default action to the Calculators controller will be "Accounting" instead of Index.

    Maslow : well the idea is that this is a temporary workaround until I have more calculators rather than just the one. adding a route is less maintainable to me than doing it in the controller and later changing the index controller when I have something better for it to do.
    Bradley Mountford : I can understand that. Plus, I have been able to get this to work in one of my own projects without any special configuration so this should be working for you as well. Is the Accounting view strongly typed (i.e. does it have something like Inherits="System.Web.Mvc.ViewPage" at the top)?
  • Hi,

    Your view for the Action Accounting expects a model. (the BalanceViewModel). The index action method does not have a instance of the BalanceViewModel.

    There are a number of ways you can solve this. In your View (aspx page) you can check for nulls...

    Or in the index action method, you create a new instance of a BalanceViewModel and store it in TempData, and then retrieve this in your view when your model is null.

    Or in your action method, you could also call return View("Accounting", new BalanceViewModel()) instead of using redirect to action.

    EDIT: Example Code - If you want to share this functinality, create a private method like this:

    public class CalculatorsController : Controller {
        // GET: /Calculators/
        public ActionResult Index() {
            return View(GetBalanceViewModel());
        }
    
        public ActionResult Accounting() {
            return View(GetBalanceViewModel());
        }
    
        private BalanceViewModel GetBalanceViewModel() {
            var combatants = Models.Persistence.InMemoryCombatantPersistence.GetCombatants();
            Debug.Assert(combatants != null);
            var bvm = new BalanceViewModel(combatants);
            Debug.Assert(bvm != null);
            Debug.Assert(bvm.Combatants != null);
            return bvm;
        }
    }
    

    Have you seen this Question?

    Maslow : why do I need to provide the model in the index action if all I want the index action to do is is hand off to another action?
    Dai Bok : if that is the case, have you tried just returning the result from accounting? something like: return Accounting(); in the index action method. (Just a guess, have not tried it my self yet)

0 comments:

Post a Comment