Search code examples
c#asp.net-coremodel-view-controllerasp.net-core-mvcviewbag

Cannot show the value from ViewBag


I am trying to show the value of ViewBag on my .cshtml page, but the value is always empty. Below is my code:

public async Task<IActionResult> DateCalc( int? department)
{

    ViewBag.DestroyCount = 4; // docDestroyed;
    return RedirectToAction(nameof(Index));
}

This is what I have in my Index.cshtml :

<div class="card">
    <form asp-action="DateCalc" enctype="multipart/form-data">
  <h5 class="card-header">Documents destroyed by section</h5>
  <div class="card-body">
       <div class="left">
        <label>Select Department(s)</label>
           @Html.DropDownList("department", (IEnumerable
        <SelectListItem>)ViewBag.department, new{@class="form-control"})
       </div>
       <div></div>

   <br /><br />
    <input type="submit" value="submit" class="btn btn-primary" />
    <p class="card-text">Documents Destroyed by Section: </p>@Html.Label((string)ViewBag.DestroyCount) 
  </div>
  </form>
</div>

When I click on submit button, I want "Documents Destroyed by Section:" to display 4, but it does not display anything.

This is the line where I am trying to display DestroyCount after clicking on submit button:

@Html.Label((string)ViewBag.DestroyCount) 

Any help will be appreciated.


Solution

  • The data for ViewBag.DestroyCount was lost as you perform the redirection as:

    public async Task<IActionResult> DateCalc(int? department)
    {
        ...
        return RedirectToAction(nameof(Index));
    }
    

    The data for ViewBag and ViewData is only lasted within the same request.

    According to this table,

    ViewBag ViewData TempData
    Its value becomes null if redirection has occurred. Same as ViewData TempData is used to pass data between two consecutive requests.
    It lies only during the current request. Same as ViewData TempData only works during the current and subsequent request

    Solution 1: Use of TempData

    You need a TempData to pass the data between the requests.

    Controller

    public async Task<IActionResult> DateCalc(int? department)
    {
        TempData["DestroyCount"] = 4; // docDestroyed;
        return RedirectToAction(nameof(Index));
    }
    

    View

    @Html.Label(TempData["DestroyCount"]?.ToString())
    

    Demo

    enter image description here


    Solution 2: Return View but not RedirectToAction

    Another approach is return View() instead of RedirectToAction(). The data of ViewBag is available as it is within the same request and with no redirection.

    However, make sure that you need to initialize for ViewBag.department before returning to Index view which I write the implementation in the InitIndex method, and this method is shared for both Index and DateCalc action methods.

    Controller

    public IActionResult Index()
    {
        InitIndex();
    
        return View();
    }
    
    public async Task<IActionResult> DateCalc(int? department)
    {
        ViewBag.DestroyCount = 4; // docDestroyed;
        InitIndex();
    
        return View(nameof(Index));
    }
    

    View

    @Html.Label(((int?)ViewBag.DestroyCount)?.ToString())
    

    And notice to the browser URL, will change to "/{controller}/DateCalc".

    Demo

    enter image description here