ViewModel property binding to null - asp.net-mvc

I have this ViewModel
public class MyViewModel
{
public Customer Customer{ get; set; }
public Account Account{ get; set; }
public DateTime MyDate{ get; set; }
}
This View
#using (Html.BeginForm("Final", "Home", FormMethod.Post, new { #class = "form" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Customer)....
#Html.DisplayFor(m => m.Customer.FirstName) //This displays the name ok
And this is my Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Final(MyViewModel viewModel)
{
viewModel.Customer.... //This is null
The problem is, I don´t have to edit the properties, only show them and then save to the database, that´s why I use HiddenFor, but the properties Customer and Account bind to null.
What is the problem? Maybe the HiddenFor?
PS: I have the GET method in which I perform the appropriate return View(viewModel)
This is where I pass the ViewModel
[HttpGet]
public ActionResult Final()
{
var viewModel = new MyViewModel
{
//set the properties, etc
};
return View(viewModel);
}

Customer is a complex object, so you will need each property of Customer as a hidden field.
#Html.HiddenFor(m => m.Customer.FirstName)
#Html.HiddenFor(m => m.Customer.LastName)
Alternatively, you can store the entire MyViewModel in TempData which uses Session State under the hood.

Related

How to pass #HiddenFor value on post method

This is my ViewModel:
public class TestViewModel
{
public Object p1{ get; set; }
public Type p2{ get; set; }
}
public class MainViewModel
{
public testViewModel test1;
}
This is my View:
#model mainViewModel
#using (Html.BeginForm("updateAction", "controller", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<fieldset>
#Html.EditorFor(x => x.test1, "editorView")
</fieldset>
}
EditorView.cshtml
#model testViewModel
//<input type="hidden" value="#Html.AttributeEncode(Model.p2)" id="p2" name="p2" />
#Html.HiddenFor(x => x.p2)
Controller method
[HTTPPost]
public ActionResult updateAction(mainViewModel md)
{
//ModelState.Clear();
return View("Index");
}
Now on post method I couldn't get the value of P2 variable. I tried most possible ways to get hidden value on post method but none of them work. I think something with Type property which I was not able to populate.
Please suggest me the way to get the hidden value on controller post method.

Html.DropDownListFor returns null

There are similar questions and I have tried most of them. Instead of continuing to destroy the remaining code while conjuring demons from the similar past questions, I have decided to ask for help.
When I arrive at the AddMembership action I get a null value instead of the selected item. Below are the details.
View;
#using (Html.BeginForm("AddMembership", "WorkSpace", FormMethod.Post, new { data_ajax = "true", id = "frmAddMembership" }))
{
<div id="newMembershipDiv">
#Html.DropDownListFor(m => m.selectedID, new SelectList(Model.allInfo, "Value","Text",1), "Select!")
<input type="submit" value="Add" name="Command" />
</div>
}
Controller (I just want to see the selectedID or anything appear here.);
public ActionResult AddMembership(SelectListItem selectedID)
{
return View();
}
Model;
public class SomeModel
{
public SelectList allInfo { get; set; }
public SelectListItem selectedID { get; set; }
}
The Monstrosity which initializes the allInfo SelectList
model.allInfo = new SelectList(synHelper.getall().ToArray<Person>().Select(r => new SelectListItem {Text=r.Name, Value=r.prID.ToString() }));
synHelper.getAll() returns a List of the below class;
public class Person
{
public Guid prID { get; set; }
public string Name { get; set; }
}
The only thing that is posted to your action is a selectedID, which is a simple string. If you wander, in the request it looks as simple as:
selectedID=1234
Therefore it should be awaited for as a simple string. Adjust your action parameter:
public ActionResult AddMembership(string selectedID)

Model with DropDownListFor SelectList not binding on the HttpPost

When I have the following code and I submit the form my post action shows the Contact object as null. If I remove the DropDownListFor from the view the Contact object contains the expected information (FirstName). Why? How do I get the SelectList value to work?
My classes:
public class ContactManager
{
public Contact Contact { get; set; }
public SelectList SalutationList { get; set; }
}
public class Contact
{
public int Id{get;set;}
public string FirstName{get; set;}
public SalutationType SalutationType{get; set;}
}
public class SalutationType
{
public int Id { get; set; }
public string Name { get; set; }
}
My view:
#model ViewModels.ContactManager
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contact.Id)
#Html.DropDownListFor(model => model.Contact.SalutationType.Id, Model.SalutationList, "----", new { #class = "form-control" })
#Html.EditorFor(model => model.Contact.FirstName)
<input type="submit" value="Save" />
}
My Controller:
public ActionResult Edit(int? id)
{
Contact contact = db.Contacts.FirstOrDefault(x => x.Id == id);
ContactManager cm = new ContactManager();
cm.Contact = contact;
cm.SalutationList = new SelectList(db.SalutationTypes.Where(a => a.Active == true).ToList(), "Id", "Name");
return View(cm);
}
[HttpPost]
public ActionResult Edit(ContactManger cm)
{
//cm at this point is null
var test = cm.Contact.FirstName;
return View();
}
You will pass the DropdownList using ViewBag:
ViewBag.SalutationList = new SelectList(db.SalutationTypes.Where(a => a.Active == true).ToList(), "Id", "Name");
than u have to call this list inside your edit view:
#Html.DropDownList("SalutationList",String.Empty)
The problem is that the DefaultModelBinder won't be able to map nested models properly if you use a different parameter name. You must use the same parameter name as the model name.
public ActionResult Edit(ContactManager contactManager)
As a general practice, always use the name of the model as the parameter name to avoid mapping problems.
Further Suggestion:
You can just use Contact as the parameter model, no need to use ContactManager if you only need the contact model.
[HttpPost]
public ActionResult Edit(Contact contact)
{
var test = contact.FirstName;
return View();
}

How do I get a strongly typed DropDownList to bind to a control Action

I've just started a new MVC project and I'm having trouble getting the post result from a form.
This is my Model Class :
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class TestModel
{
public List<User> users { get; set; }
public User user { get; set; }
public SelectList listSelection { get; set; }
public TestModel()
{
users = new List<User>()
{
new User() {id = 0, name = "Steven"},
new User() {id = 1, name = "Ian"},
new User() {id = 2, name = "Rich"}
};
listSelection = new SelectList(users, "name", "name");
}
}
This is my view class
#model MvcTestApplicaiton.Models.TestModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
#if (#Model.user != null)
{
<p>#Model.user.name</p>
}
And this is my controller :
public class TestModelController : Controller
{
public TestModel model;
//
// GET: /TestModel/
public ActionResult Index()
{
if(model ==null)
model = new TestModel();
return View(model);
}
[HttpPost]
public ActionResult Test(TestModel test)
{
model.user = test.user;
return RedirectToAction("index", "TestModel");
}
}
The drop down list appears just fine but I can't see to get the ActionResult Test function to run. I thought it would just bind itself with reflection but whatever is wrong, I can't see it.
You have two main errors in your code.
As Brett said you're posting to the Index method, but you don't have Index method that supports POST verb. The easiest way to fix is to change Html.BeginForm() with Html.BeginForm("Test", "TestModel")
You're using Html.DropDownListFor in a wrong way. You could pass only a value types there, because don't forget that the View will generate an HTML page. So instead of User in your Model you should have an UserID and in your View you should have #Html.DropDownListFor(x => x.UserID, #Model.listSelection). And finally in your Action you should query your data source to get the details for the user with this ID.
Hope this helps.
Looks like you're posting back to index. Either use a GET Test() action method, or specify the ACTION parameter in BeginForm().
For example,
#using (Html.BeginForm("Test", "TestModel"))
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
Or use a view named Test (rename index.cshtml to test.cshtml):
public ActionResult Test()
{
if(model ==null)
model = new TestModel();
return View(model);
}

How to access ViewModel properties within an ASP.NET MVC View?

I am using the following ViewModel to create an Employee
public class EmployeeViewModel
{
Employee employee{ get; set; }
Budget budget { get; set; }
}
How can I access the properties of Employee object inside my view? I would like to do something like
#Html.EditorFor(model => model.Employee.EmployeeID)
You start by having a controller action that will pass this model to the view:
public ActionResult Index()
{
EmployeeViewModel model = ...
return View(model);
}
then you have a corresponding view which is strongly typed to this model and in which you will be able to access the properties of this view model:
#model EmployeeViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.employee.EmployeeID)
<button type="submit">OK</button>
}

Resources