Robert Ross Robert Ross - 23 days ago 8
C# Question

Saving data from a html form to List

I have two

Create
methods one decorated with
HttpGet
, and the other with
HttpPost
. I have a create view for the first one looking like this :

@{
ViewBag.Title = "Create";
}

<h2>Create</h2>

<form action="/" method="post">
<input type="text" name="txt" value="" />
<input type="submit" />
</form>


The methods :

List<string> myList = new List<string> { "element1", "element2", "element3" };
public ActionResult Create()
{
return View();
}

[HttpPost]
public ActionResult Create(string txt)
{
//myList.Add(Request.Form["txt"]);
myList.Add(txt);
return View();
}


I am simly trying to pass the data from my form on button to my second
Create()
and save it to
myList
.

I need some advice on how to make this work.

Answer

Once you've fixed your form (in that you're posting back to your application's default route (by default HomeController.Index() method) by sending the request to /, instead of your Create method), you are actually correctly adding the value to your list. The problem is, that value only stays for the current request.

To make things persistent, you need to consider a persistence layer in memory, in database, or in session. I've provided a full sample below that uses the session, which will give you a per-user list instance. Without this layer, your Controller is being routinely disposed of once the action has completed processing, and so the amends to your list are not persisted. This is the normal request lifecycle in ASP.NET and makes sense when you consider that your app is basically only ever dealing with 1 request at a time. It's important to note that making something static isn't a form of persistence per-se, in that its lifetime and reliability is indeterminable. It will appear to work, but once your application pool recycles (ie. the app is destroyed and reloaded in memory) you will have again lost all amends to your list.

I would suggest you read up on Session State to understand exactly what is going on below. In a nutshell, each application user / unique visitor to your site will be given a unique 'session ID', you can then use this session ID to store data that you wish to use on the server side. This is why, if you were to visit your Create method from separate browsers (or try Private mode) you will be maintaining two separate lists of data.

View (which also outputs the list to the user):

@model List<string>
@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<ul>
    @foreach(var str in Model)
    {
        <li>@str</li>
    }
</ul>

@using (Html.BeginForm())
{
    <input type="text" name="txt" />
    <input type="submit" />
}

Controller contents:

public List<string> MyList
{
    get
    {
        return (List<string>)(
            // Return list if it already exists in the session
            Session[nameof(MyList)] ??
            // Or create it with the default values
            (Session[nameof(MyList)] = new List<string> { "element1", "element2", "element3" }));
    }
    set
    {
        Session[nameof(MyList)] = value;
    }
}

public ActionResult Create()
{
    return View(MyList);
}

[HttpPost]
public ActionResult Create(string txt)
{
    MyList.Add(txt);
    return View(MyList);
}