13

straight forward question , can't seem to get my viewBag value to display in a view that the user is directed to after completing a form.

Please advise..thanks

My Index ActionResult simple returns model data..

public ActionResult Index()
{
    var source = _repository.GetByUserID(_applicationUser.ID);
    var model = new RefModel
    {
        test1 = source.test1,
    };
    return View(model);
}

My Get Edit" ActionResult , simply uses the same model data as Index.

My Post "Edit" ActionResult, assigns the new values if any to the model and redirects to the Index page, but Index page does not display ViewBag value ??

[HttpPost]
public ActionResult Edit(RefModell model)
{
    if (ModelState.IsValid)
    {
        var source = _repository.GetByUserID(_applicationUser.ID);
        if (source == null) return View(model);

        source.test1 = model.test1;
        _uow.SaveChanges();

        @ViewBag.Message = "Profile Updated Successfully";
        return RedirectToAction("Index");      
    }
    return View(model);
}

And in my Index view...

@if(@ViewBag.Message != null)
{
    <div>
        <button type="button">@ViewBag.Message</button>
    </div>
}
Xaruth
  • 4,034
  • 3
  • 19
  • 26
mkell
  • 711
  • 2
  • 13
  • 31

4 Answers4

39

ViewBag only lives for the current request. In your case you are redirecting, so everything you might have stored in the ViewBag will die along wit the current request. Use ViewBag, only if you render a view, not if you intend to redirect.

Use TempData instead:

TempData["Message"] = "Profile Updated Successfully";
return RedirectToAction("Index");

and then in your view:

@if (TempData["Message"] != null)
{
    <div>
        <button type="button">@TempData["Message"]</button>
    </div>
}

Behind the scenes, TempData will use Session but it will automatically evict the record once you read from it. So it's basically used for short-living, one-redirect persistence storage.

Alternatively you could pass it as query string parameter if you don't want to rely on sessions (which is probably what I would do).

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • when it return null from view? I have a function that everything is ok but it returns null from view in this link : localhost:44385/account/ActiveEmailAccount/ddd8915deba74659be3ca89fdc118f14. I mean ddd8915deba74659be3ca89fdc118f14 doesn't come at all! why? – hasti.au Sep 15 '22 at 09:11
2

RedirectToAction causes an HTTP 302 response, which makes the client make another call to the server and request a new page.

You should be returning a view instead of redirecting.

Natan
  • 4,686
  • 5
  • 30
  • 48
  • 1
    Well, actually, it's best practice to redirect after a successful POST - redirect-after-post pattern. Return view only if there are some errors that the user need to fix and resubmit. – Darin Dimitrov Oct 10 '13 at 11:54
  • The user asked as straight forward question, I gave a straight forward answer on why the value wasn't being displayed. – Natan Oct 10 '13 at 11:56
  • I dunno, the downside of storing it in the session is that it gives trouble if you want to scale out. I'd be in favor of directly returning a view rather then storing it in the sessions(which you should always be wary about) – Kristof Oct 10 '13 at 11:57
  • Darin is right about the solution, but the question was not if his architecture was right, it was why the value wasn't being displayed. – Natan Oct 10 '13 at 12:30
2

The RedirectToAction(msdn) instructs your browser to make a new request.
So your server will be called again but it will be a new request with a blank viewbag and all
You could do a sort of internal redirect by just calling the index method, this way the viewbag will still have its data.

Edit : you'll also have to modify your index method or your View(model) line will try to render the edit.
Full code below

public ActionResult Index()
{
    var source = _repository.GetByUserID(_applicationUser.ID);
    var model = new RefModel
    {
        test1 = source.test1,
    };
    return View("Index",model);
}


[HttpPost]
public ActionResult Edit(RefModell model)
{
    if (ModelState.IsValid)
    {
        var source = _repository.GetByUserID(_applicationUser.ID);
        if (source == null) return View(model);

        source.test1 = model.test1;
        _uow.SaveChanges();

        @ViewBag.Message = "Profile Updated Successfully";
        return Index();      
    }
    return View(model);
}
Kristof
  • 3,267
  • 1
  • 20
  • 30
  • Just to add a further twist onto this question ... what if the view I'm returning to is a tabbed view and my only way to redirect is via..return RedirectPermanent("~/RefTarget/Index/#users");.......#users being one of three tabs...how would carry out my viewBag message operation then ? – mkell Oct 10 '13 at 14:36
  • You're doing a redirect again. I'd set the selected tab on the viewmodel or in the viewbag and check this value in the view to select the correct tab while it's being rendered. – Kristof Oct 11 '13 at 06:27
  • Nice! for people who can not return their view because they have to create a model again this is a good solution! This way you don't have to create your model in two places so it reduces code duplication. Awesome! – Nash Carp Nov 30 '17 at 12:32
0

You can try this way also

Controller

public ActionResult Test()
    {
ViewBag.controllerValue= "testvalue";
 ..................
    }

View - define top of razor page @{string testvalue= (string)ViewBag.controllerValue;}

$(function () {
       var val= '@testvalue';
});