Asp.net-mvc – MVC ViewData Model null after Post-back to Controller Action

asp.net-mvcasp.net-mvc-4razorviewmodel

I have a simple MVC 4 (Beta) Application and just observed something that I assume may be handled differently. In this case, when the below Product Action is called a Model is created and assigned to ViewData for use in the View. This all works fine, the Model property is not-null, and the Views use of the Model property works.

[HttpGet]
public ActionResult Product()
{
    return ExecuteFormRequest(View(), true, delegate
    {
        var model = Request.ParseFromQueryString<Product>();

        if (model != null)
        {
            ViewData.Model = model;
        }

        return View();
    });
}

When the Product is updated and Post'ed back to the Controller all the data looks fine, but if the product fails validation and I return the View ActionResult (as shown below) the View encounters a null reference exception because the Views Model property is now null

[HttpPost]
public ActionResult Product(Product product)
{
    if (!ModelState.IsValid)
    {
        return View();
    }

    // Do other business stuff and target new or same View    

    return View();
}

This is the line in the View that leads to a null reference exception, because the Model Property is now null.

@if (!string.IsNullOrEmpty(Model.MyValue)) {}

The way I resolved this was to reset the Model Property (as shown below). This seems wrong to me and I'm wondering if I'm approaching this all wrong. Any ideas welcome?

[HttpPost]
public ActionResult Product(Product product)
{
    if (product!= null)
    {
        ViewData.Model = product;
    }

    if (!ModelState.IsValid)
    {
        return View();
    }

    // Do other business stuff and target new or same View    

    return View();
}

Best Answer

If you have a strongly typed viewmodel, why are you using viewdata? try this:

[HttpGet]
public ActionResult Product()
{
    return ExecuteFormRequest(View(), true, delegate
    {
        var model = Request.ParseFromQueryString<Product>();

        //if (model != null)
        //{
        //    ViewData.Model = model;
        //}

        //return View();
        return View(model);
    });
}

[HttpPost]
public ActionResult Product(Product product)
{
    if (!ModelState.IsValid)
    {
        //return View();
        return View(product);
    }

    // Do other business stuff and target new or same View    

    //return View();
    return View(product);
}

The reason you are seeing the behavior with your approach is because HTTP is stateless. Unlike webforms, MVC does not reconstitute all of your variables after a post. Each action method starts out with a new ViewData dictionary.

Related Topic