Search code examples
c#asp.net-core-mvcmodel-binding

How to pass Model parameter value from an action to a view and back to another controller action?


How do I keep a Model alive across multiple actions and views? So that no parameter value is lost in between. I suspect I am doing some basic error in Model binding.

For example,

  1. I have a Model
public class Car : IDisposable
    {
// Some code
        public string Brand { get; set; }
        public string Color { get; set; }
        public int Capacity { get; set; }
}
  1. Create an instance of this class in an Action
[HttpPost]
        public IActionResult Test_car_1st(int x)
        {
            var mycar = new Car();
            mycar.Brand = "Honda";
            // Some Code
            return View("TestView",mycar);
        }
  1. In the "TestView", the user can choose the color of the same Model.
@model Car;
//Some Code

<form method="post" enctype="multipart/form-data" asp-controller="Home" asp-action="Test_car_2nd" asp-route-Model="@Model" >
//User chooses the color from a dropdown
<select asp-for="@Model.Color">
   <option value="">
   // Some code

</select>
<input type="submit" value="Submit" class="btn btn-primary" asp-controller="Home" asp-action="Test_car_2nd"/>
</form>
  1. In the 2nd Action Method, I try to access the same model (now with both the parameters set). One was set in 1st Action and another was set in the TestView.
public IActionResult Test_car_2nd(Car Model)
        {
            // Some code
            return View("TestView_2",Model);
        }

I expect in the Test_car_2nd Action, both the parameters are set. But I find only Color is set. The other parameter (Brand) is null.

I want a model created in one action, and I would pass this model through various actions and views to edit the parameter values.

What I have right now is this :

  1. When I modify parameters in an action and call a View, the Model values are preserved.

  2. When I edit values in the View and call an action, only those parameters are preserved whose value was changed / created in the View. The other parameters which were previously set are not preserved (showing null).


Editing after accepting a solution :


Session Object is the best solution so far.

For anyone who may face the same issue, here is a summary of the pros and cons of various approach and some of the mistakes I made.

  1. First of all, HTTP is stateless as people have rightly pointed out. The confusion that I was having was due to the fact that in the debug mode using breakpoint, I could see the Model parameters inside the View. However, what I missed was that it was before the view was fully rendered. Once it is rendered, the Model parameters are no longer available to the View. This is a simple thing but I missed it at first !

  2. So what are the options through which we can 'carry on' the values ? Option 1 : As many people have suggested here - "Hidden input type". It works well for most cases but if your model has a list, then it's not straightforward but definitely possible. In fact, before posting this question, I was using that method.

Option 2 : Session object (as the accepted answer shows). According to me, this is a better option if your model properties are complex. Code maintainability is better.

  1. One of the main concern I had was on memory utilization. So far, I have not seen much difference on the 2 options. For disposing the memory allocated to the session object, I am using HttpContext.Session.Remove("ObjectName") Is this the "most efficient" way? Can I do better? Looking for any suggestion on this point.

Solution

  • I want a model created in one action, and I would pass this model through various actions and views to edit the parameter values.

    In order to meet your scenario and description you could use asp.net core session to bind your Car class.

    Because, tempdata and hidded html item cannot persist your previous state as it can only keep the value within one single request cycle.

    In your scenario, you might be wanted to manipulate your previous action's data and then want to pass to your next action or even you may want extract previous object in current action. Thus, using asp.net core session would the good option according to your needs.

    Let's have a look in practice how we can do that.

    Demo Model:

    public class Car 
    {
       
        public string Brand { get; set; }
        public string Color { get; set; }
        public int Capacity { get; set; }
    }
    

    Bind model in session:

    public static class SessionExtension
    {
        //setting session
        public static void SetComplexObjectSession(this ISession session, string key, object value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }
    
        //getting session
        public static T? GetComplexObjectSession<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }
    

    Note: We are going to use this session static class binding our model into session and retrieve from the session as well.

    Modidy value in controller action:

    [HttpPost]
    public IActionResult Test_car_1st(Car Model)
    {
       
        var mycar = new Car();
        mycar.Brand = "Honda";
        mycar.Capacity = 10;
        mycar.Color = "Metalic Grey";
        HttpContext.Session.SetComplexObjectSession("CarObject", mycar);
        return RedirectToAction("Test_car_2nd");
    }
    

    Note: What ever, we are posting from the view then we are modifying the sumitted value and binding into the session by using SetComplexObjectSession so later on we can get the updated value in anywhere.

    Get updated value in another action:

    public IActionResult Test_car_2nd()
     {
         var carObject = HttpContext.Session.GetComplexObjectSession<Car>("CarObject");
         return View(carObject);
     }
    

    Output:

    enter image description here

    Note: If you still want to study more about session manamement, you could refer to this official document.