0

I need to pass objects between ActionMethods and Views in an ASP.net MVC 5 app.

I'm using it for a multi page signup - and for a multi page payment.

Is this bad practice? I haven't seen a good way to pass objects between different controllers.

Code:

public ActionResult Join1()
{
    //
    return View("Join2", MyObject);
}

[HttpPost]
public ActionResult Join2(MyObject MyObj)
{
    //manipulate object
    //return
}

It seems to be an effective way to do it - though I haven't seen many people do it this way. I haven't seen objects being passed between action methods much at all.

Is there a flaw in this approach, a better way of passing models between Views - or should each ActionMethod stick to passing simple data with, say, TempData instead of objects?

Why haven't I seen any sample projects doing things like this?

I've seen return RedirectToAction("act"); plenty - but that is Get and passing an object in a URI is limiting - and I don't want users to be able to manipulate or see the data being passed.

thx.

niico
  • 11,206
  • 23
  • 78
  • 161
  • 1
    I do this as needed. Use `RedirectToAction` where you think [PRG](http://stackoverflow.com/questions/11209191/how-do-i-include-a-model-with-a-redirecttoaction/11209320#11209320) is appropriate – Shyju Apr 29 '17 at 13:13

1 Answers1

1

Unless I have misunderstood the description, your code is not doing what you think it's doing. That first return View("Join2", MyObject); statement is not executing the second ActionMethod, it is only passing your data into the View that happens to have the same name as the second method. Therefore the code implied by //manipulate object will not run before that View is rendered and sent back to the user.

Assuming the View file Join2.cshtml exists, and it contains the default @using (Html.BeginForm()), then users submitting the form will cause the Join2 Action to be executed and the same view rendered with the manipulated data - unless, of course, you add another return View() statement that names a different View.

The reason you haven't seen this done much is that the MVC convention is to have a View named the same as the ActionMethod, this makes the code slightly simpler and also much easier for other ASP.NET developers to understand because it is what they are expecting to see.

If you want the form rendered by each View to then execute a different ActionMethod when it is posted back, the place to do that is in the View code, where Html.BeginForm() has several overloads that allow you to do just that, e.g. in Join.cshtml you could write:

@using (Html.BeginForm("Join2", "JoinController"))
{
    // form fields and stuff
}
// Produces the following form element
// <form action="/JoinController/Join2" action="post">

To address the final part of your question, "I don't want users to be able to manipulate or see the data being passed", sorry to say it but your proposed code doesn't prevent that: users can see the data in the web form, before it is ever posted back to the Join2 method; they can manipulate the data by sending an HTTP POST containing any data they want back to the Join2 method.

If you absolutely, positively need to actually execute Join2() from within Join(), before anything is passed back to the user, then you can call it just like any other C# method:

var myResult = Join2(MyObject);

Then you have an ActionResult object that you can manipulate or return straight to the browser. But why you would want to do this, is beyond me.

Daniel Hume
  • 437
  • 4
  • 9
  • Thanks. It's very flexible how I do this - I'm at the design stage - so I can change it as much as I want. How would you pass an object from one ActionMethod to another? – niico Apr 29 '17 at 15:22
  • Just added a final section showing how to invoke the method as any other in C#. However I would suggest that if you need to do this, your design is probably flawed: the whole purpose of an Action Method is to respond directly to a user's request. – Daniel Hume Apr 29 '17 at 15:26
  • Yes I agree - I'm asking for a more conventional way to do this - for some reason i can't really find much online. – niico Apr 29 '17 at 15:27
  • That would depend on what you're trying to achieve from a requirements point of view. If the goal is to walk users through a multi-page form, collecting more data as you go, then using `Html.BeginForm("NextActionName", "ControllerName")` is the way to do that. If you don't want to return the already-entered data back to the user between pages e.g. as hidden form fields, or if you want to add some persisted, 'secret' data that the users shouldn't see then ways to do that would be either store it in the `Session` object, or create a database record and give the ID to each subsequent page view. – Daniel Hume Apr 29 '17 at 15:35
  • So the way I was doing it is a good option if you're passing data between different ActionMethods - and not using a database? – niico Apr 29 '17 at 15:57
  • No, the way you were doing it is *failing* to pass data between ActionMethods, it still returns the data straight back to the browser (assuming the View is putting that data somewhere in the HTML) without executing the second method. If you want data from one request to be available when processing a second request, without putting that data into the view so it can be posted back by the second request, then you absolutely have to store it on the server *somewhere*, be that SQL, ASP.NET Session object, or writing it to a file on disk. – Daniel Hume Apr 29 '17 at 16:07