mvc3 FormData to create page Session getting lost - asp.net-mvc-3

I have 1 form with a simple dropdownbox with values from a database on Post the value of that dropbox gets inserted in a session. I think use that session value on the create page to autofill some categories but somehow it seems like the session becomes NULL or Empty on the second page.
form 1 action
[HttpPost]
public ActionResult select(listings listing)
{
Session["address"] = ViewBag.CategoryID;
return View();
}
form 1 view
<form method="post" action="create">
#Html.DropDownList("CategoryID")
<input type="submit" value="step 2"/>
</form>
Form 2 action
public ActionResult Create()
{
// The "IF" works correctly but it seems like it is making the SESSION= NULL
if (Session["address"] == null)
{
return RedirectToAction("sesserror");
}
string tt = (string)Session["address"];
var getlisting = (from s in db.relistings where tt==s.address select s).FirstOrDefault();
return View();
}
The issue looks like maybe its in the IF statement if I go to FORM 1 pick a value and go to FORM 2 it does not redirect me so either the SESSION has a value and it is losing it or something else.
Form 2 View /create page
<b>Step: 2 out of 2</b>
#Session["address"]
I have more on Form 2 but i'm focusing on that part. Is there a better way to carry a value from 1 form to the other? by the way the Session does work initially because if I go straight to Form 2 I get redirected to Sesserror.

Related

ActionMethod param is 0 every time

I've got a form (here's some of its code):
#model Discussion
#{
ViewBag.Title = "Edit Discussion";
Layout = "~/Views/Shared/_App.cshtml";
}
#using (Html.BeginForm("Update", "Discussion", FormMethod.Post, new { id = Model.discussionId, #class = "update" }))
{
... rest of the view code
}
My related controller's update method has:
[HttpPost]
[ValidateInput(false)]
public ActionResult Update(FormCollection col, int id = 0)
{
... rest of code
}
when the form is submitted, I keep getting an id of 0 instead of the ID I'm seeing from the model that when I debug is clearly there inside being used during the form rendering. IT's just when I submit, it's not passing the id correctly.
Am I doing something wrong in terms of syntax here? the new{} in the Html.BeginForm I guess I don't understand how the new anonymous type is matching up to this id when the form is submitted when it's a collection of id and a class here as you can see.
When you do the new {id = Model.discussionId ...} you are setting the id attribute of the form element. To get the id to come across properly you would have to make it an input of the form. So inside the form you would put a hidden input element with something like this: #Html.Hidden("id", Model.discussionId)
So your current form is rendering something like this:
<form id="theDiscussionId" class="update" action="/Discussion/Update">
... rest of the view code
</form>
And you need it to be like this:
<form class="update" action="/Discussion/Update">
<input type="hidden" name="id" value="theDiscussionId" />
... rest of the view code
</form>

server side validation in the main view cause also validation in partial view, how to stop that?

I have layout with login partial view (username, password and submit button) and models ( some controls and submit button)with validation(server side and client side) displayed in normal views (#RenderBody() in layout).
My problem is when do server side validation in any of my views it also validate the login partial view because it execute the httppost function of the login. how can I stop that??
login view controller
[HttpGet]
public ActionResult LogOn()
{
return PartialView();
}
//
// POST: /Account/LogOn
[HttpPut]
public ActionResult LogOn(LogOnModel model)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
ViewBag.UserName = model.UserName;
}
else
{
ModelState.AddModelError("", Resources.Account.Account.LoginFailureText);
}
}
return PartialView(model);
}
and model controller
public ActionResult MyModel()
{
ViewBag.DisplayThxMsg = false;
return View();
}
[HttpPost]
public ActionResult MyModel(Models.FeedbacksModel feedback)
{
if (ModelState.IsValid)
{
//do something
}
else{
//do another thing
}
return View(feedback);
}
I find your question very difficult to understand. Im guessing your problem is you have a login partial control displayed as part of site layout and is shown on all pages. So while submitting any page, the username password validation kicks in, and you want to prevent that.
Understand that all validation # server - side happens while model binding, As properties are bound to the posted fields, the attributes on the fields are looked at and honored / catered to. So to prevent server side validation simply put the login partial view in it's own form so it is not sent while submitting other forms on the page.
In short have 2 forms - one form for login and one for feedback. Don't put all input fields in the same form.
If you still have validation errors after that, then it is because of other reasons like, type conversion problems. The default model binder will add some errors for basic type conversion issues (for example, passing a non-number for something which is an "int").The sample DataAnnotations model binder will fill model state with validation errors taken from the DataAnnotations attributes on your model.
EDIT
If you look at line number 125
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
You have the above code which will render the login form.
It will do so inside the other form at line 45
<form id="form1" runat="server" method="post">
This has no end tag therefore it will encompass the whole document till </html>
You should change the structure from
<form id="form1" runat="server" method="post">
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
</form
to
<form id="form1" runat="server" method="post">
</form>
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
This line #using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");} will render this form <form id="LoginView1" action="LogOn"> and all child elements of it.
LATEST EDIT
In your layout page use this :
#Html.Partial("~/Views/Shared/LogOnPartial.cshtml", new LogOnModel())
instead of this :
#Html.Action("LogOnPartial", "Account")
The reason why it all works is, the LogOnPartial method marked with [HttpPost] is called because the request was in a POST context. What you want is, You just need the view without the action executing even when POSTing. The above code does that. It renders the view without calling the action method. MVC3 is sort of a stupid servent : It only knows that it should call the Action method marked with [HttpPost] when the request is in a post context. It doesn't know that the request is in a post context for another action (index) and not this one (logonpartial). So now you can remove this method
public ActionResult LogOnPartial()
{
return PartialView();
}
which will no longer be used.
Note that you need to change the account controller's LogOnPartial Method to return
return RedirectToAction("Index","Home"); instead of return PartialView(model); on successful login. And on FAILURE you cannot render a partialview as you have coded. You must return an entirely new View. It must neither be index nor LogonPartails - just return return View("Login_Error_View"); which has its own layout. Otherwise it will be difficult to control the workflow.

Best method to pass value in MVC

I am still new to MVC, so sorry if this is an obvious question:
I have a page where the user can choose one of several items. When they select one, they are taken to another form to fill in their details.
What is the best way to transfer that value to the form page?
I don't want the ID of the item in the second (form) pages URL.
so it's /choose-your-item/ to /redemption/ where the user sees what was selected, and fills the form in. The item selected is displayed, and shown in a hidden form.
I guess one option is to store in a session before the redirect, but was wondering if there was another option.
I am using MVC3
Darin Dimitrov's answer would be best if you don't need to do any additional processing before displaying the /redemption/ page. If you do need to some additional processing, you're going to have to use the TempDataDictionary to pass data between actions. Values stored in the TempDataDictionary lasts for one request which allows for data to be passed between actions, as opposed to the values stored in the ViewDataDictionary which only can be passed from an action to a view. Here's an example below:
public ActionResult ChooseYourItem()
{
return View();
}
[HttpPost]
public ActionResult ChooseYourItem(string chosenItem)
{
TempData["ChosenItem"] = chosenItem;
// Do some other stuff if you need to
return RedirectToAction("Redemption");
}
public ActionResult Redemption()
{
var chosenItem = TempData["ChosenItem"];
return View(chosenItem);
}
If you don't want the selected value in the url you could use form POST. So instead of redirecting to the new page, you could POST to it:
#using (Html.BeginForm("SomeAction", "SomeController"))
{
#Html.DropDownListFor(...)
<input type="submit" value="Go to details form" />
}
To help others, this is how I resolved my issue of needing multiple buttons posting back, and wanting to pass a different Id each time.
I have a single form on the page, that posts back to my controller:
The Form:
#using (Html.BeginForm("ChooseYourItem", "Item", FormMethod.Post))
{
And the code
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChooseYourItem(string itemId)
{
TempData["ITEMID"] = itemId
return RedirectToAction("Create", "Redemption");
}
Then, inside the form, I create buttons whose name == "itemId", but has a different value each time.
For example
<strong>Item 1</strong>
<button value="123" name="itemid" id="btn1">Select</button>
<strong>Item 2</strong>
<button value="456" name="itemid" id="btn2">Select</button>

Redirection in controller in MVC 3 with Razor

I need a little help. I'm trying to make a little project in MVC 3 with Razor. A page with 2 buttons: Button 1 and Button 2. When I click on Button 1 I want to go at Page 1. The same with Button 2 ( to Page 2). It's not difficult, BUT I want the redirection to be made in Controller, not in View (cshtml). I know that I need to use ActionName and RedirectToAction, but I don't know how. Please help me!
What you'll need to do is check which button was pressed in the HttpPost part of the controllers action then redirect accordingly.
As a very basic example you could add two
<input type="submit" name="submit" value="<val>">
controls into your forms view each having the same name and a different value (instead of ) then add a string parameter called submit to the HttpPost action. Assuming the buttons have values "button1" and "button2" Then in your action's code you could use:
if(submit == "button1") {
RedirectToAction("Page1");
} else {
RedirectToAction("Page2");
}
to redirect based on which button was pressed
This is a simplified example, but I think you will get my meaning. You simply need to name your buttons and check the formcollection to see which exists in the collection thus indicating which what clicked. see code below:
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
<input type="submit" value="Go 1" name="go-1" />
<input type="submit" value="Go 2" name="go-2" />
}
and now the Action implementation.
[HttpPost]
public ActionResult Test(FormCollection collection)
{
if (collection.AllKeys.Contains("go-1")) return View("Page1");
if (collection.AllKeys.Contains("go-2")) return View("Page2");
return View("Index");
}
and thats it.
In your controller action for page 1, you can use RedirectToAction:
public ActionResult Process()
{
// do processing
// redirect to page 2
return this.RedirectToAction("Index", "Page2");
}
You can invoke the Process action from the Page 1 button using either a GET or POST request, depending on if the Process action is idempotent. E.g your page 1 view:
#Html.BeginForm("Process", "Page1", FormMethod.Post)
{
<input type="submit" name="button" value="Submit" />
}
Alternatively, you could use an ActionLink:
#Html.ActionLink("Redirect to Page 2", "Process", "Page1")

Calling another Controller post method

I am using ASP.NET MVC 3 for my website.
I have created a partial view that has "Previous, Next and Save" buttons. I am calling this partial view on my master page.
My requirement is that on what ever View I am I must be able to call different Save methods in different controllers by passing respective Model data to controller actions.
Example
I have 4 step data input, I have a different controller for each step.
If i am on step 1 and i click Save the form Values should go to Step1Controller's action method,
If I am on step 2 then post should call Step2Controller
Something like this this:
public ActionResult Save(GenericModel model)
{
//use reflection to find out model type
//call appropriate controller action with model
return RedirectToAction("Create", new { Controller = "Conference", Action = "Create" });
}
This save method will be called for Save button on the Master page. How can I achieve this?
Are the forms on separate actions on the controllers?
If so, just set the form action on each page to point to the relevant controller. So form 1 is
<form method="post" action="/step1controller/action">
Form 2 is:
<form method="post" action="/step2controller/action">
Does that solve your problem?
I would create a private method in the controller and call in every part of the first steps.
private bool Save(GenericModel model)
{
......
}
[HttpPost]
public bool SaveStep1(GenericModel model)
{
this.Save(model);
}
[HttpPost]
public bool SaveStep2(GenericModel model)
{
this.Save(model);
}

Resources