model binding in mvc - asp.net-mvc

i'm having a textbox inside a form.
[View]
<%=html.textbox("name") %>
[Controller]
Index(string name)
{
name = "something";
return View();
}
On Form Submit
In this case without sending any ViewData the textbox value is maintained.But the value "something" is not setting up.
But whn i change the Action to
[Controller]
Index()
{
string name="something";
return view();
}
the value is not maintained.
Really wat happening on that parameter.

If you want to set data for html.textbox("name") in the Controller use ViewData["name"] = "something"

Your question is not very clear and your code example is not actually adding anything to ViewData or the view Model - here's a shot at what i think your trying to do...
Assuming you want to re-populate the form and your View is Strongly Typed, You would do something like this:
public ActionResult Index(String name)
{
MyModel model = new MyModel;
model.Name = name;
ViewData.Model = model;
return View();
}
A textbox in your view with the same name would then have the value auto populated from the Model
<%= html.textbox("Name") %>
Posting the form would then post the model object to your controller like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(MyModel model)
{
// do something with the model
ViewData.Model = model;
return View();
}
and then re-populate the form with the model data.

string name in your Index action in the controller, is mapped to the FormValue, if you change this, MVC understands that it needs to add the value from the FormValueCollection to the textbox, and you have changed that in your Index action. If you declare a variable by yourself this doesn't work because there is no binding to the formvalues.

Related

Validation between controllers

I have a HomeController with an Index.cshtml Razor view that uses an InitialChoicesViewModel with validation attributes. The Index view contains the following form:
#using (Html.BeginForm("CreateCharacter", "DistributePoints", FormMethod.Get))
This goes to a different controller (which is what I want):
public class DistributePointsController : Controller
{
public ActionResult CreateCharacter(/* my form parameters */)
// ...
}
How do I perform server-side validation on the form (such as checking ModelState.IsValid), returning my original Index view with a correct ValidationSummary on error? (On success I want to return the CreateCharacter view of the other controller.)
Based on John H's answer, I resolved this as follows:
#using (Html.BeginForm("CreateCharacter", "Home"))
HomeController:
[HttpPost]
// Only some of the model fields are posted, along with an additional name field.
public ActionResult CreateCharacter(InitialChoicesViewModel model, string name)
{
if (ModelState.IsValid)
{
return RedirectToAction("CreateCharacter", "DistributePoints",
new {name, model.Level, model.UseAdvancedPointSystem});
}
// Unsure how to post a collection - easier to reload from repository.
model.ListOfStuff = _repository.GetAll().ToList();
return View("Index", model);
}
I had to add a parameterless constructor to my view model, too.
[HttpPost]
public ActionResult CreateCharacter(InitialChoicesViewModel model)
{
if (ModelState.IsValid)
return RedirectToAction("SomeSuccessfulaction");
return View("~/Views/Home/Index.cshtml", model);
}
The ~/ denotes the relative root of your site.
The code above complies with the Post-Redirect-Get pattern, in order to prevent some types of duplicate form submission problems. It does that by redirecting to a separate action when the form submission is successful, and by returning the current view, complete with ModelState information, on error.
By default, ASP.NET MVC checks first in \Views\[Controller_Dir]\, but after that, if it doesn't find the view, it checks in \Views\Shared.
If you do return View("~/Views/Wherever/SomeDir/MyView.aspx") You can return any View you'd like.
But for now in your case, try the following
public ActionResult CreateCharacter(SomeModel model)
{
if(!ModelState.IsValid){
return View("~/Views/Home/Index.cshtml", model )
}
return View();
}
To check your ModelState just use an if statement in Controller:
if(ModelState.IsValid)
{
...
}
If there is any error add you can add an error message to the ModelState Dictionary like this:
ModelState.AddModelError("Somethings failed", ErrorCodeToString(e.StatusCode));
After that return your same View and pass it to your model
return View(model);
If you add "#Html.ValidationSummary()" in your View, it will get the errors from the ModelState Dictionary and display them.But if you show values yourself maybe with different styles you can do it manually, take a look at this question
And if there is no error you can return your CreateCharacter View like this, just redirect user to the appropriate action:
return RedirectToAction("CreateCharacter","DistributePoints");

Changing a Model's value in httppost action

I'm looking to change the value of a string in a view model in the controller and pass it back to the view like so:
[HttpPost]
public ActionResult TestAction(TestViewModel model)
{
model.TestStringValue = "test val";
return View("Index", model);
}
The value is shown in a textbox but isn't showing the updated value. What do I need to do in the controller to update a view model's field?
Try
ModelState.Clear();
To Clear Model State Values
Try
ModelState.Remove("TestStringValue");
model.TestStringValue = "test val";

How to keep dropdownlist selected value after postback

In asp.net mvc3 how to keep dropdown list selected item after postback.
Do something Like this :
[HttpPost]
public ActionResult Create(FormCollection collection)
{ if (TryUpdateModel(yourmodel))
{ //your logic
return RedirectToAction("Index");
}
int selectedvalue = Convert.ToInt32(collection["selectedValue"]);
ViewData["dropdownlist"] = new SelectList(getAllEvents.ToList(), "EventID", "Name", selectedvalue);// your dropdownlist
return View();
}
And in the View:
<%: Html.DropDownListFor(model => model.ProductID, (SelectList)ViewData["dropdownlist"])%>
Even easier, you can include the name(s) of your dropdowns in your ActionResult input parameters. Your dropdowns should be in form tags. When the ActionResult is posted to, ASP.Net will iterate through querystrings, form values and cookies. As long as you include your dropdown names, the selected values will be preserved.
Here I have a form with 3 dropdowns that posts to an ActionResult. The dropdown names are (non-case sensitive): ReportName, Year, and Month.
//MAKE SURE TO ACCEPT THE VALUES FOR REPORTNAME, YEAR, AND MONTH SO THAT THEY PERSIST IN THE DROPDOWNS EVEN AFTER POST!!!!
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ReportSelection(string reportName, string year, string month)
{
PopulateFilterDrowdowns();
return View("NameOfMyView");
}
MVC does not use ViewState, which means you will need to manage the value persistence yourself. Typically this is done through your model. So, given that you have a view model, e.g.:
public class MyViewModel { }
And your controller:
public class MyController : Controller
{
public ActionResult Something()
{
return View(new MyViewModel());
}
public ActionResult Something(MyViewModel model)
{
if (!ModelState.IsValid)
return View(model);
return RedirectToAction("Index");
}
}
Now, when you pass the model back to the view with data (probably incorrect - failed validation), when you use your DropDownListFor method, just pass in the value:
#Model.DropDownListFor(m => m.Whatever, new SelectList(...))
... etc.
MVC's model binding will take care of the reading of the data into your model, you just need to ensure you pass that back to the view to show the same value again.
Assuming the selected item is part of the post, the controller now knows what it is. Simply have an entry in the ViewData dictionary indicating which item should be selected (null on get or if nothing was selected). In the view, check the value and if it's not null, select the appropriate option.
Use HttpRequestBase object.
In the view, this should work:
#Html.DropDownList("mydropdown", ViewBag.Itens as IEnumerable<SelectListItem>, new { value = Request["mydropdown"] })
If you are building the drop down list data source in the controller Action Method you can send the selected value to it
Controller:
public ActionResult Index( int serviceid=0)
{
// build the drop down list data source
List<Service> services = db.Service.ToList();
services.Insert(0, new Service() { ServiceID = 0, ServiceName = "All" });
// serviceid is the selected value you want to maintain
ViewBag.ServicesList = new SelectList(services, "ServiceID", "ServiceName",serviceid);
if (serviceid == 0)
{
//do something
}
else
{
// do another thing
}
return View();
}
View:
//ServiceList is coming from ViewBag
#Html.DropDownList("ServicesList", null, htmlAttributes: new { #class = "form-control" })

aspnetmvc model is updated but doesn't update control

hejdig.
In Aspnetmvc2 I have a model object that I send to a View. A control in the view isn't updated with the value. Why? What obvious trap have I fallen in?
The View:
<%:Html.TextBox(
"MyNumber",
null == Model ? "1111" : Model.MyNumber ) %>
<%:Model.MyNumber%>
is first fetched trough a Get. The "1111" value in the textbox is manually updated to "2222". We post the form to the controller which appends "2222" to the Model object and sends it to the view again.
The Controller:
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index( MyModel myModel)
{
myModel.MyNumber += " 2222";
return View(myModel);
}
Alltogether we get an output like:
<input id="MyNumber" type="text" value="1111">
1111 2222
As you can see the control doesn't use the Model's attribute but instead falls back to thew viewstate that doesn't exist in Aspnetmvc.
(The same happens with Razor.)
That's normal and it is how HTML helpers work : they look first in the model state and then in the model when binding a value. So if you intend to modify some property in the POST action you need to remove it from the model state first or you will always get the old value:
[HttpPost]
public ActionResult Index(MyModel myModel)
{
ModelState.Remove("MyNumber");
myModel.MyNumber += " 2222";
return View(myModel);
}

asp.net-mvc / linq to sql - do i always need an HTML.TextBox to do a Edit Save?

I have a UserController and an Edit.aspx. There is one field that is my primary key so i dont want to allow users to edit this field.
The issue is that if i remove the
<%= Html.TextBox("Email", Model.Email) %>
then when the asp.net-mvc magic calls my Controller code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, tblMailingList user_)
{
try
{
repo.UpdateUser(user_);
return RedirectToAction("Index");
}
catch
{
return View();
the email field of the tblMailingList is null. The issue is that i need this as the lookup in the table to retrieve the current record and obviously if its null i get an exception.
When i put the textbox back for this field, it works fine. It seems crazy that i would have to have a textbox and allow editing to pass this field over to the controller. i tried putting it in a label and it still shows up as null in the controller.
any suggestions?
My first question would be why are you doing the lookup on the Email field and not the Id field?
You can pass parameters in your Form declaration to be passed through to your Controller.
<% using (Html.BeginForm(
"MethodName", "Controller", FormMethod.Post,
new { id = Model.Id, email = Model.Email)) { %>
I'm not sure if I got the method declaration correct so please check.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, string email, tblMailingList user_)
{
try
{
repo.UpdateUser(user_);
return RedirectToAction("Index");
}
catch
{
return View();
I would recommend updating slightly differently as your tblMailingList user will not be valid to be updated in your Repository.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection form)
{
tblMailingList user = repo.GetUser(id); // get the user using the id
// so we can update in the same
// context
UpdateModel(user); // this will automatically update
// your user model with values
// from the form
try
{
repo.UpdateUser(user);
return RedirectToAction("Index");
}
catch
{
return View();
If you just want a field that could passed to controller which needs to be invisible in the form, Html.HiddenField could work for your case.
Do I get wrong?

Resources