0

Situation

Inside my ASP.NET project, I have a view which allows the user to change his password. After submitting a form, the user will be redirected to the UserDetail using RedirectToAction. Here I want to notify the user if the password change was successful or not (planning to use Alertify JS). Yet, I can't seem to successfully pass the message from my controller to my view.

How does one properly pass data (simple string) from a controller to a view when using RedirectToAction without the use of ViewBag, ViewData, Tempdata, ...? Or, if there's a way to solve my current difficulties with these, happy to hear.

  1. ViewBag/ViewData: Can't be used since I return RedirectToAction where I can't pass it in the URL instead of a View. I've considered using Ajax to return JSON instead of using RedirectToAction which would enable me to use ViewBag but this brings in some difficulties and would change the overall structure of the project.

  2. TempData: I don't have a session configured in my Startup.cs and can't do so since I'm missing the Microsoft.AspNetCore.Session namespace. I also can't add the namespace since this adds some complications. See the following error: System.TypeLoadException: 'Method 'ConfigureAppConfiguration' in type 'Microsoft.AspNetCore.Hosting.WebHostBuilder' from assembly 'Microsoft.AspNetCore.Hosting, Version=1.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' does not have an implementation.'

I'd rather not work with cookies or some sort of cashing system.
EDIT: I'd also rather not use a querystring but seeing the comments/answers makes me realize that my options are limited. I forgot to add the querystring/route param to the list earlier.

The ManageController.cs

[HttpGet]
public IActionResult UserDetail(int id)
{
    // Code to GET the UserViewModel
    return View(model);
}

[HttpGet]
public IActionResult UserPassword(int id)
{
    // Code to GET the UserViewModel
    return View(model);
}

[HttpPost]
public IActionResult UserPassword(UserViewModel model)
{
    // Code to check and save the password.
    if (user.Password == model.Password) {
        //ViewData["Message"] = "Succeeded";
        //TempData["Message"] = "Succeeded";
    } else {
        //ViewData["Message"] = "Failed";
        //TempData["Message"] = "Failed";
    }
    // TODO: Alert the user
    return RedirectToAction("UserDetail", new { id = model.UserId });
}

UserDetail.cshtml

<!-- Some view code -->
<form>
    <button class="ui button button-back" type="button" onclick="window.location.href = '@Url.Action("UserPassword", "Manage", new { id = Model.UserId })';">Change Password</button>
</form>
<!-- Trying to use ViewData -->
@*<div id="id-message" data-value="@ViewData["Message"]"></div>*@

<script>
  $(document).ready(function () {
    console.log("Ready");

    // Alert the user of a password change
    //var message = $("#id-message").attr("data-value");
    //var message = "@(TempData["Message"] as string)";
    if (message !== null && message !== "") {
      alertify
        .alertmessage, function () {
          alertify.message('OK');
        };
    }
  });
  // Some script code
</script>
Wouter Vanherck
  • 2,070
  • 3
  • 27
  • 41
  • 4
    Add a `string Message` property to you view model –  Jun 13 '18 at 13:09
  • You can pass it as route parameter `new { id = model.UserId, message= "" }` and accept it in `UserDetail(int id, string message)` – Satpal Jun 13 '18 at 13:11
  • 1
    Possible duplicate of [how to add querystring values with RedirectToAction method?](https://stackoverflow.com/questions/1067200/how-to-add-querystring-values-with-redirecttoaction-method) – mjwills Jun 13 '18 at 13:12
  • Thank you all for your comments. I'd rather not use a querystring/route parameter but it seems like my options are limited. I've got one more question about the change to the model though @StephenMuecke, Even if I changed the model, I'm not actually passing it to the YserDetail, right? – Wouter Vanherck Jun 13 '18 at 13:27
  • But this is not about "from my controller to my view", you want to pass data from request123 to request231. Keeping and managing state is always a pain on the Web, pick your bitter medicine. On how many servers do you want to run the site? – bommelding Jun 13 '18 at 13:28
  • @WouterVanherck, If you have passed the message (or a `bool` indcating success or otherwise, you can just set the value of `Message` in `UserViewModel` before passing it to the view –  Jun 13 '18 at 13:30
  • `I'd rather not use a querystring/route parameter` Can you talk us through why not? I ask since this is is a pretty standard PRG pattern. – mjwills Jun 13 '18 at 13:31
  • @bommelding It's more of a web app then a site, which could be run on a lot of devices. I presume you ask that question so you could recommend the best option? – Wouter Vanherck Jun 13 '18 at 13:34
  • @mjwills I'm still learning ASP.NET and am trying to write uniform code. Since this is only a string, it's not a big deal to pass it through an URL but when passing objects that can't be put in the model comes into play, it's gotta be done in a different way, shouldn't it? – Wouter Vanherck Jun 13 '18 at 13:37
  • I'd use a `bool` rather than `string`, but that is a side issue. What kind of object are you envisaging that need to be passed through a querystring that can't be put in the model? – mjwills Jun 13 '18 at 13:40
  • @mjwills I might be missing the entire point but I'm not actually passing the model from UserPassword POST to the UserDetail GET, just the Id for navigation right? I'm a bit confused with the flow now – Wouter Vanherck Jun 13 '18 at 13:49
  • 1
    @WouterVanherck I would rather consider fixing the TempData issue than asking this question because if u would have TempData fixed u would have some many options to implement. I would find a good solution if TempData does function correctly. – Rey Jul 28 '18 at 20:29

3 Answers3

1

You can pass it as route parameter with RedirectToAction() method

return RedirectToAction("UserDetail", new { id = model.UserId, message= "" });

and accept it

[HttpGet]
public IActionResult UserDetail(int id, string message)
{
   // Code to GET the UserViewModel
   return View(model);
}
Satpal
  • 132,252
  • 13
  • 159
  • 168
0

About another options as your described, i would suggest SessionState:

string passwordChange = "Password has been changed";
Session["yourName"] = passwordChange  // inside your if else logic calling it from your UserDetail controller method. 

Or creating a JsonResult result to reference an Ajax call, for instance.

Sergio Rezende
  • 762
  • 8
  • 25
0

change:

[HttpGet]
public IActionResult UserDetail(int id)

to

[HttpPost]
public IActionResult UserDetail(UserViewModel model)

Add the Message property to your model.

should do it for you

Ibrahim Malluf
  • 657
  • 4
  • 6