Persist model field from GET to POST - c#

In the controller's GET method, I pick up a parameter (id) from the query string and assign it to a property in the model, which then gets sent to the view.
The view contains a form in which the user will supply the rest of the values for this model. When the model then gets sent back to the POST method, I need that original parameter (id) back again. But I'm not sure how to persist it. In the POST method, the id field is coming back blank. Is there a better way to do this?
// GET: CreateInsured
[Route("Home/CreateInsured/{id}")]
public ActionResult CreateInsured(int id)
{
Insured insured = new Insured();
insured.PolicyId = id;
return View(insured);
}
// POST: CreateInsured
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateInsured(Insured insured)
{
//insured.PolicyId is empty
}

You should put this Id into a Hidden field, like this:
#Html.HiddenFor(m => m.PolicyId)
And this field should be into your form.

Related

Persisting model property when submitting form

I am trying to figure out why property values are not persisting when I return the View with the model.
Index.cshtml
View:
#Html.HiddenFor(model => model.IsWtv)
Controller:
[HttpPost]
public ActionResult Index([Bind(Exclude = "Id,ShippingCost")] TestModels model)
{
//assume the initial value is false. I only want it to switch to true once
if (!model.IsWtv)
model.IsWtv = true;
return View(model);
}
Model:
public Boolean IsWtv
{
get;
set;
}
The value for IsWtv is always false when I resubmit the form. I don't understand why?
First, you should really be following the PRG pattern (POST, Redirect, GET) when dealing with controller action methods (unless this is some type of AJAX request).
With that said, HtmlHelpers get the model values from the model state and not the model when you update and return the model. In order to update and return the model, add this line of code in your post method prior to any property modifications:
ModelState.Clear();
or you could set the value of IsWtv in the ModelState itself:
//no point in doing any check on the actual variable
//we are always returning true
ModelState["IsWtv"].Value = true;

MVC Send back model properties after POST

I have a Model that I send to the view in a GET method and is bounded successfully to TextFor and ListFor's
e.g.
#Html.ListBoxFor(x => x.MultiChoice, new MultiSelectList(Model.property, "Id", "Name"), new { multiple = "multiple", #class = "multiselect" })
When the user submits the form, the Model is successfully passed back to the POST action method with its properties.
[HttpPost]
public ActionResult POST(Model quiz)
{
string Q1 = quiz.Q1 // = will equal what the user has put in. good
return View("Quiz", quiz);
}
However, when the Model (quiz) is returned to the view, the properties inside the quiz model are NULL, how do I retain the properties that come through to the POST method?
** Edit **
The GET Method
[HttpGet]
public ActionResult Quiz()
{
try
{
Quiz quiz = new Quiz();
// Of course, I could do this in the constructor of the model..
InitialiseQuiz(Quiz);
return View("Quiz", quiz");
}
catch (Exception ex)
{
}
}
Thanks
If I understood well, when you do this:
#Html.ListBoxFor(x => x.MultiChoice, new MultiSelectList(Model.property, "Id", "Name"))
the Razor will create a <select> tag with x.MultiChoice values as selected options. BUT, nowhere will be persisted the Model.property values (as it may be a collection, right?).
So, when you do the POST, you will only send the x.MultiChoice value back to the server, and the Model.property collection will be missed.
Knowing that, you just need to fill this property with the collection again during the POST action, like:
[HttpPost]
public ActionResult POST(Model quiz)
{
// some code here
quiz.property = new CollectionOfSomething();
return View("Quiz", quiz);
}
Is that what you are looking for?
The modelbinder news up an instance of that class with whatever POST data it has. Anything that's null has no posted data. The easiest way to make it not be null, then, is to create an HTML input for that property so that something is posted for it.
However, in situations where you're dealing with existing data, it's preferable to only post what you need to post, and then lookup the original object again in order to map the original property values back onto the version that was passed into your action:
[HttpPost]
public ActionResult Quiz(int id, Quiz model)
{
var quiz = db.Quizzes.Find(id);
// assuming `Foo` was a property that was not posted
model.Foo = quiz.Foo
...
}

Submit entity collection with other route parameters

I have a strongly typed view
#model IEnumerable<MagazineIndex>
that represents user input array of objects.Also I have a dropdown:
#Html.DropDownList("DropDownName",
(List<SelectListItem>)ViewData["magazines"],
new { id = "DropDownName" })
When I submit form I get this error:
There is no ViewData item of type 'IEnumerable' that has the key 'DropDownName'.
My controller is like this:
public ActionResult CreateContent(IList<MagazineIndex> indexes,
string DropDownName)
How must I correct bind values?
Make sure that in your HttpPost action you are populating the ViewData["magazines"] the same way you did in your Get action:
[HttpPost]
public ActionResult CreateContent(IList<MagazineIndex> indexes, string DropDownName)
{
...
ViewData["magazines"] = ... same stuff as in your GET action
return View(indexes);
}
This is only necessary to be done if you intend to redisplay the same view in your POST action. If you redirect, you don't need it. The reason you need it is more than obvious. Your view needs to render a DropDown control which depends on its value.

Pass UserId to the Model

So I have a simple web app where I can create a user (UserModel) and it returns that user ID. The user then has the ability to enter multiple instances or records of a specific item type, in this case a geographic location (LocationModel). The LocationModel has a UserId property that I need to set when the location is created.
The ActionLink for creating a user is User/Create/id=[userid]
The code in the controller is currently.
[HttpGet]
public ActionResult Create(string id)
{
return View();
}
[HttpPost]
public ActionResult Create(LocationModel model)
{
//CODE TO SAVE MODEL
}
My questions is how to pass the user id so that I can get it into the model in order to relate the two. I was going to try to pass it in the ViewBag and render it in a Hidden field but was thinking that someone has to have a more elegant solution than this. Thanks in advance.
Put the UserId on the model, and pass the model to the view:
[HttpGet]
public ActionResult Create(string id)
{
return View(new LocationModel{UserId = id});
}
Then render the UserId property as a hidden field in the View, so it will get included on your model parameter when the form is POSTed.
#model LocationModel
#using (Html.BeginForm(...)) {
#Html.HiddenFor(m => m.UserId)
...
}

Default values for model fields in ASP.Net MVC3

I have a simple Action in my Controller:
public ActionResult Edit(int itemId)
{
return View(new EditModel() { ItemId = itemId + 1 });
}
public class EditModel
{
public int ItemId { get; set; }
public string Title { get; set; }
}
The problem comes in the View, when I try to display everything.
Model.ItemId: #Model.ItemId
#Html.EditorForModel()
Since action parameter and property on EditModel have the same name (itemId) I get the following:
Is this a correct behaviour? How can I change default value displayed inside a form in that case?
This may be somehow confusing for the first look, but yes, this is default(correct) behavior. Controller.ModelState is the privileged supplier for the values when you use EditorFor or similar editor helpers, over the model itself. But there's trickier point in your situation.
ModelState is populated with action parameters and values that take part in model binding. When you call that action, ModelState is populated with "ItemId" = action parameter(itemId) value. Later, EditorFor sees that is should draw editor for ItemId. As ModelState has already got ItemId, it does not look at model value, but extracts it from ModelState["ItemId"]. Tricky source of your error is that action parameter name matches the model property name and modelState prefers that over model value. The best solution (clean one) would be to just rename action parameter, so that it does not match the model property name.
public ActionResult Edit(int initialItemId)
{
return View(new EditModel() { itemId = initialItemId + 1 });
}
This will do the trick.
You can write
Model.ItemId: #Model.ItemId
#Html.EditorFor(x => x.Title)
Or hide ItemId for edit with metadata

Categories

Resources