Accessing ViewBag in Controller that's set in a view - asp.net-mvc

I understand I can do this using ModelBinding, but I'd like to know if I can use the ViewBag
I set the ViewBag property in the View
#{
ViewBag.WasPriorityCustomer = Model.PriorityCustomer == true;
}
A user who is not a priority customer can be changed to one, but i need to know if they were a priority customer to begin with.
In the controller
[HttpPost]
public ActionResult Save(MyModel model)
{
if (ViewBag.WasPriorityCustomer == false && model.PriorityCustomer == true)
{
//Thank you for becoming a priority customer
}
}
Unfortunately ViewBag.WasPriorityCustomer is always null

You just try to do things in the wrong way :
You can set a ViewBag's value in an action, and use it's value in the generated view.
But to get a value from a view in the POST action, you should use an hidden input.
something like that in the view (untested) :
# {bool wasPriorityCustomer = Model.PriorityCustomer;}
#Html.Hidden("wasPriorityCustomer", wasPriorityCustomer)
and Action becomes
[HttpPost]
public ActionResult Save(MyModel model, bool wasPriorityCustomer)
or you could change your ViewModel to include the "hidden" value.
and use #Html.HiddenFor(m => m.WasPriorityCustomer)

Try this code if you want to store some value in viewBag and want to use in this ViewBag value in View.
In Model Action
ViewBag.Test = ("NewTest");
in View you can write
#ViewBag.ProcedureTypeId
This way you can have ViewBag value in Viewpage

Related

MVC Controller returning different views; Model data not being saved in hidden input

I'm attempting a multiple page form where I use a single controller action and returning a view depending on a value on my model.
My model has a property that I put in an input field on my views, using Html.HiddenFor().
Here's my simplified model:
public class MyModel
{
public virtual int Step { get; set; }
}
And in my views, I have:
#model MyModel
...
#Html.HiddenFor(model => model.Step)
Then in my controller I have:
public ActionResult Create()
{
...
myModel.Step = 1;
return View("View1", myModel);
}
[HttpPost]
public ActionResult Create(MyModel myModel)
{
...
if (myModel.Step == 1)
{
myModel.Step = 2;
return View("View2", myModel);
}
else if (myModel.Step == 2)
{
...
}
...
}
My problem is, my controller always sees mymodel.Step as having the value of 1. Why is that?
What's weird is that I tried to display it on the form with these:
#Html.DisplayFor(model => model.Step)
#Html.EditorFor(model => model.Step)
The second time the page was displayed, the first line showed the text "2". The second showed an input field with "1". I'm confused.
ADDITIONAL INFO:
My model also has a Guid property which is passed onto the View in a hidden field. I tried to change it also on postback, and check its value the second time around. The new value did not register. The model returned the original value before the first post. So it is consistent with the other field.
I may have to use different controller actions if I couldn't find why it is behaving the way it does at the moment.
SOLUTION:
As Reda suggested below, I fixed it by doing this in my post action method:
Before displaying "View2" and to effect changes my controller makes to a value in my model, I run ModelState.Clear()
Here is a blog post which confirms the need to clear ModelState for this scenario.
Usually, when you return to view from your post action, it means that something failed during validation process and the form should be displayed again with the submitted values. That's why the ModelState remembers your inputs when you return to View, and your inputs will be filled from the ModelState, not your view model.
In my opinion you have two solutions :
ModelState.Clear, which will erase your old value, before setting new ones
redirecting to a GET action, with new values
Second solution is a better one, because you're not displaying the old form with validation errors, you're just showing a new view with different values.
Here's an example (of course you adapt it to your needs) :
public ActionResult Create(int? step)
{
...
myModel.Step = step.HasValue ? step.Value : 1; // or whatever logic you need to apply
return View("View1", myModel);
}
[HttpPost]
public ActionResult Create(MyModel myModel)
{
...
if (myModel.Step == 1)
{
return RedirectToAction("Create", new { step = 2 });
}
else if (myModel.Step == 2)
{
...
}
...
}

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";

Pass model to view then pass it again from view to controller

I'm fairly new to asp.net mvc and I have a question. Example model:
public class FooModel
{
public string StrA {get; set;}
public string StrB {get; set;}
}
How can I do something like this: pass model to view (model with StrA filled, StrB empty), update StrB of my model (StrA filled, StrB filled) and then submit it to my action with both StrA and StrB filled (by default I will pass new instance of model with only StrB filled and my previous value of StrA will vanish).
I know I can use HiddenFor, but is there any other way to do that?
I know I can use HiddenFor, but is there any other way to do that?
In your POST action you could fetch the value of the StrA property from the same place you fetched it in your GET action. This way you don't need to use a hidden field to persist it.
For example:
public ActionResult Index()
{
var model = new FooModel
{
StrA = PopulateStrAFromSomewhere()
};
return View(model);
}
[HttpPost]
public ActionResult Index(string strB)
{
var model = new FooModel
{
StrA = PopulateStrAFromSomewhere(),
StrB = strB
}
... do something with the model
}
Now in the view you could only have an input field for StrB inside the form which will allow the user to modify its value:
#model FooModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.StrB)
#Html.EditorFor(x => x.StrB)
<button type="submit">OK</button>
}
You can build your own POST using e.g. jQuery AJAX ( http://api.jquery.com/jQuery.post/ ) or construct a form manually and submit it ( http://api.jquery.com/submit/ ). This means you won't have to create a visible form on the page (if that is what you want to avoid).
However you will need to pass the data to the DOM and persist it in some way (e.g. with a hidden field). Since HTML is stateless you can't magically save the StrA somewhere if you actually want to get it back to the server somehow - unless it isn't meant to change between requests, which means you wont need to get it to the client and back any way (see Darin's response for an example of how to handle it in this case).

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);
}

model binding in 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.

Resources