Reputation: 95
I'm just picking up .net MVC and I've come across something that I can't work out. I'm obviously missing some basic principle but would love some help.
I have a ViewModel with two IEnumerables that I want to use to create dropdownlistfors. My GET works fine, the lists are populated as expected.
Now I'm posting the ViewModel back to a POST method, not to do anything useful but just to try and understand how mvc works. I expected that I would simply be able to re-populate the dropdownlistfors from the model that was posted back - but I get a null reference exception.
Other values, such as partyid, in the ViewModel survive the POST so i'm confused.
I can get it to work if I repopulate the lists but that seems wrong.
Can someone give me a pointer?
My ViewModel
public class DemoViewModel
{
//properties
public IEnumerable<tbl_server_lookup> servers { get; set; }
public int serverId { get; set; }
public IEnumerable<tbl_site_lookup> sites { get; set; }
public int siteId { get; set; }
public int partyid { get; set; }
public string message { get; set; }
public DemoViewModel()
{
}
}
My Controller
// GET: /Demos/Test/
[HttpGet]
public ActionResult Test()
{
DemoViewModel demo = new DemoViewModel();
using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var serverList = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = serverList.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}
demo.message = "Enter the user id you would like to look up in the box below.";
return View(demo);
}
//
//POST: /Demos/Test/
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(DemoViewModel demo)
{
//It works if I uncomment this block...
/*using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var myQuery = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = myQuery.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}*/
demo.message = "the user id you posted is: " + demo.partyid + ". The Server you selected is: ";// +demo.serverId;
return View(demo);
}
My View
@model ADAPI.ViewModels.DemoViewModel
<h2>Demos</h2>
<h3>@Model.message</h3>
@using (Html.BeginForm("Test","Demos"))
{
@Html.AntiForgeryToken()
<div class="">
<h4>Party ID</h4>
@Html.ValidationSummary(true)
<!-- input box for party id-->
@Html.TextBoxFor(model => model.partyid)
<!-- dropdown list of server types eg live vs test-->
@Html.DropDownListFor(model => model.serverId, new SelectList(Model.servers, "server_Id","server_name"))
@Html.DropDownListFor(model => model.siteId, new SelectList(Model.sites, "site_short_name","site_name"))
<input type="submit" value="Try" />
</div>
}
The Error
Upvotes: 1
Views: 211
Reputation: 5827
In MVC, model on the views are loaded in the controller action, they are not posted back along with the post action.
If you are used to ASPX
's viewstate, there is no such thing in MVC, you need to load what you need for every view in the current action.
Upvotes: 2
Reputation: 203
Dropdown lists are rendered into html as tag and returned to the server as plain single value.
You have to rebind/repopulate them on the server, wchich is annoying in scenarios like validation, where the same model should be returned to the client.
There is no support for that in the framework - you have to do it on your own.
One more thing - if you absolutely have to return the list items and want them back on the server, you can serialize tham and hide in some hidden field. But it's ugly and unsecure since anyone can change its value.
Upvotes: 0