4

I'm building a web site, and I need to show a list of customers. When a customer is selected, to show his items, I send the id of the customer from the view with this:

 <th>
 @using (Html.BeginForm("SetID", "Client", FormMethod.Post, new 
{ id = item.id.ToString() }))
   {
    @Html.Hidden("id", item.id.ToString());
    <input type="submit" value="see items" />
   }
   </th>

I receive the id in the controller and save it to make the query and show the values this way.

private string customer_id
[HttpPost]
public ActionResult SetCustomer(string id) {
    Save(id);
    return RedirectToAction("Index");
}

private void Save(string id) {
    this.customer_id = id;
}

But when I get redirected to the Index view, the variable "customer_id", is null. Is there something I'm missing?

Bryan
  • 2,870
  • 24
  • 39
  • 44
jdaxpuac
  • 43
  • 6

2 Answers2

4

Because you're not persisting the value anywhere.

HTTP is stateless. What this means in ASP.NET is that each HTTP requests results in a new instance of the controller being requested. So the following sequence of events is happening here:

  1. User makes a request to SetCustomer, creating a new instance of the class
  2. Value is stored in a class-level variable
  3. Request is responded to and completed, the instance of the class is destroyed
  4. User makes a request to Index, creating a new instance of the class

Since it's a new instance, no value is set. There are a variety of places you can store data, it just has to be in a context that both requests can access. Examples, in no particular order, include:

  1. Database
  2. Session
  3. URL query string
  4. Cookie
  5. etc.

Basically, you have to write the value to some location which persists between requests. In-memory variables don't do that in web applications.


A simple example here could be to include the value on the query string in the redirect. In ASP.NET MVC, that might look something like this:

return RedirectToAction("Index", new { customer_id = id });

What this would do is include on a URL parameter a customer_id value when the user is redirected. So your Index action you could accept that parameter:

ActionResult Index(int? customer_id = null)
{
    // use the customer id if one is provided
}

In this case I assumed that the value should be nullable in case the Index is ever requested without a value. But what you prefer to do for that is up to you. Basically this action now has an optional parameter, which you would use however you're currently trying to use it.

The benefit of this is that it maintains the intended statelessness of web applications. You're storing the state (the customer_id value) in the request/response itself, as opposed to some other medium (session, database, etc.) where you become responsible to maintaining it.

David
  • 208,112
  • 36
  • 198
  • 279
  • thank man, i didn't see that way, i try to use Session["customer_id"] an solve the problem :D, thank you very much for help this noob haha. :) – jdaxpuac Apr 12 '17 at 18:36
  • @Jose_av28: Using session state *can* solve the problem, at least in this limited scope. But it introduces statefulness to the web application, which should be avoided unless absolutely necessary. An example of a pitfall there is if you host the application in an auto-scaling cloud solution where you don't control how web servers are arranged/configured. The web server which stores the session may not be the web server which attempts to retrieve it. Providing the value to the user attaches it to the request itself, so any server can process the request. – David Apr 12 '17 at 18:38
  • Well, I just needed to make some queries from the admin account, then just erase it, so i don't know how implement this topic :S. – jdaxpuac Apr 12 '17 at 23:49
0

ASP.NET MVC controllers are instantiated to serve every request. Your local variable this.customer_id is not supposed to survive a call to the server. If you want to save something, it should go in a database table, or a file or somewhere persistent.

You could also store it in memory like in a cache, but that would need to be in a reference to something that lives longer than the controller (which will be thrown away after the server responds back to the browser).

If you want something like I described to be long lived, you might need to use a service to inject into your controllers. Many people would use a DI or IOC framework and life cycle configurations to accomplish this.

keithwill
  • 1,964
  • 1
  • 17
  • 26