asp.net-coremodel-view-controllerhttphandlerviewbagtempdata

Pass value from one controller to another in ASP.NET Core MVC


How can I pass a dropdown selected value from my view to a controller then to different controller? I have a home page and an about page. On the home page the user selects an item from the dropdown, then they click on a button that navigates them to another page that has the same dropdown. My goal is to have the dropdown prepopulated on the about page based on what they selected on the home page.

My problem is that I am doing the navigation in my home page controller, so I am not getting the value of the selected value because it is not a post just a get. My variable "string countryDDL" in my home controller is null.

I am currently using TempData to pass the value, however, I am open to other options (viewbag, session state, etc). Thank you for your time.

Home page view:

<form method="post" asp-controller="Home" asp-action="Index" role="form">

    <div class="form-group">
        <label>Country Dropdown:</label>
        <select name="countryDDL" asp-items="@(new SelectList(ViewBag.message, "ID", "CountryName"))"></select>
    </div>
</form>
<a asp-action="AboutPage" asp-controller="Home">About Page</a>

Home Controller:

        public void CountryDDL()
        {
            List<CountryModel> countryName = new List<CountryModel>();
            countryName = (from b in _context.CountryModel select b).ToList();
            countryName.Insert(0, new CountryModel { ID = 0, CountryName = "" });
            ViewBag.message = countryName;
        }

        [HttpGet("[action]")]
        public IActionResult AboutPage()
        {
            string countryDDL = HttpContext.Request.Form["countryDDL"];
            int intCountry = Convert.ToInt32(countryDDL);
            CountryModel data = new CountryModel()
            {
                ID = intCountry,
                CountryName = "",
            };
            TempData["myData"] = data;
            return RedirectToAction("Index", "AboutPage");
        }

My Book Page Controller:

        [HttpGet("[action]")]
        [Route("/Index")]
        public async Task<IActionResult> Index()
        {
            //get values from Home controller
            CountryModel data = TempData["myData"] as CountryModel;

            return View();
        }

Solution

  • Firstly,your code makes a mistake that you could not pass TempData["myData"] redirect to another controller action with the following error message.That is because TempData uses Session, which itself uses IDistributedCache. IDistributedCache doesn't have the capability to accept objects or to serialize objects:

    InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type
    

    Here is the whole working demo:

    Home/Index.cshtml:

    <form method="post" asp-controller="Home" asp-action="Index" role="form">
    
        <div class="form-group">
            <label>Country Dropdown:</label>
            <select id="sel" name="countryDDL" asp-items="@(new SelectList(ViewBag.message, "ID", "CountryName"))"></select>
        </div>
    </form>
    <a asp-action="AboutPage" asp-controller="Home" >About Page</a>
    
    @section Scripts{ 
    <script>   
        $("a").click(function () {
            var selectItem = $('#sel').find(":selected").val();
            var href = $(this).attr('href');
            if (href) {
                href +="?countryDDL="+selectItem;
                $(this).attr('href', href);
                console.log(href);
            }
        });
    
    </script>
    }
    

    HomeController:

    public class HomeController : Controller
    {
        private readonly MvcProj3_1Context _context;
        public HomeController(MvcProj3_1Context context)
        {
            _context = context;
        }
        public IActionResult Index()
        {
            CountryDDL();
            return View();
        }
        public void CountryDDL()
        {
            List<CountryModel> countryName = new List<CountryModel>();
            countryName = (from b in _context.CountryModel select b).ToList();
            countryName.Insert(0, new CountryModel { ID = 0, CountryName = "" });
            ViewBag.message = countryName;
        }
        [HttpGet]
        public IActionResult AboutPage(string countryDDL)
        {
            int intCountry = Convert.ToInt32(countryDDL);
            List<CountryModel> data = new List<CountryModel>()
           {
                new CountryModel()
                {
                    ID = intCountry,
                    CountryName = "asd",
                }
           };
            TempData["myData"] = JsonSerializer.Serialize(data);
            return RedirectToAction("Index", "AboutPage");
        }
    }
    

    AboutPage/Index.cshtml:

    <form>
        <div class="form-group">
            <label>Country Dropdown:</label>
            <select id="sel" name="countryDDL" asp-items="@(new SelectList(ViewBag.message, "ID", "CountryName"))"></select>
        </div>
    </form>
    

    AboutPageController:

    public class AboutPageController : Controller
    {
        [HttpGet]
        public async Task<IActionResult> Index()
        {
            //get values from Home controller
            ViewBag.message = JsonSerializer.Deserialize<List<CountryModel>>(TempData["myData"] as string);
            return View();
        }
    }
    

    Result: enter image description here

    Update

    You could get the data like below:

    [HttpGet]
    public IActionResult AboutPage(string countryDDL)
    {
        int intCountry = Convert.ToInt32(countryDDL);
          
        //change this line...
        var data = _context.CountryModel.Where(c => c.ID == intCountry).ToList();
        TempData["myData"] = JsonSerializer.Serialize(data);
    
        return RedirectToAction("Index", "AboutPage");
    }