ASP.NET MVC - redirect after form submit - asp.net-mvc

I have a ASP.NET MVC website and a "Configuration" view with a form.
When I submit the form, I would like to do some stuff and then Redirect to my "Initialization" ViewResult... How to do it ?
My form :
#using (Html.BeginForm("Save", "Home", FormMethod.Post, new { id = "Config" }))
{
// Some fields
<input type="submit" value="Save" />
}
then, the "Save" action :
[HttpPost]
[ValidateAntiForgeryToken()]
public async Task<RedirectToRouteResult> Save(Config websiteConfiguration)
{
// Do some stuff
bool ok = await myMethod();
if(ok)
{
return RedirectToAction("Initialization");
}
}
I tried other possibilities but I don't manage to get it work...
Up, I still have the problem...

Not sure if this issue was with an earlier version of MVC, but I have often forgotten that the [HttpPost] label may be placed above an ActionResult in the controller and not just above a JsonResult.
So the simplest MVC-style answer would be just use Html.BeginForm and post to the ActionResult (with the [HttpPost] attribute), wherein you execute your logic, then call RedirectToAction at end after you have handled the post controller side.
This seems far easier than all the client-side fiddles, e.g. window.location.href = '' etc...

This is what your Form Post method should look like
<HttpPost>
<ActionName("Respond")>
Function Respond_post(viewModel As FormsRespondModel) As ActionResult
viewModel.form.formId = Guid.Parse(Request("formId"))
viewModel.form.loadForm(Guid.Parse(Request("formId")))
If (viewModel.form.formNotifications.onSuccess = "redirectOnSuccess") Then
Return Redirect(viewModel.form.formNotifications.redirectUrl)
End If
Return RedirectToRoute("form_finished")
End Function

Try this :
<input id="btnSave" name="btnSave" type="submit" value="Save" onclick="window.location = '#Url.Action("Action_Name", "Controller_Name")'; return false;" />

Related

What should I do when more than one submit cases exist

I have a form where I fill in a blank and then save it, which takes me to the read only version of the entry I've just saved. At this step I have 2 options:
Either "Confirm" or "Cancel". Both actions will update some values in the database, so they're both good candidates for submit button(HttpPost, of course). I know this shouldn't be tied to a particular web development technology as
all-in-all it's all about Request and Response, but still I'll talk in ASP.NET MVC "language" as that is what I'm using now. So far, the only idea that has come to my mind is to have a separate submit buttons with different names and on the server side check for the name and act accordingly. But this seems a bit ugly to me as I might have to have a huge and universal action method. Do you have any better approach? Maybe MVC has some built in way for this purpose?
huge and universal action method
That's entirely your responsibility. You write action methods to map HTTP requests to business logic.
public class PostModel<T>
{
public string SubmitAction { get; set; }
public T TheModel { get; set; }
}
public ActionResult HandleSomePost(PostModel<Foo> model)
{
switch (model.SubmitAction.ToUpperInvariant())
{
case "SAVE":
_yourBLL.Save(model.TheModel);
break;
case "CANCEL":
_yourBLL.Cancel(model.TheModel);
break;
default:
throw new ArgumentException("SubmitAction");
}
return View();
}
Then you can handle both submit buttons from this form:
#using (Html.BeginForm("HandleSomePost", "TheController", FormMethod.Post))
{
#Html.EditorFor(m => m.TheModel)
<input type="submit" name="SubmitAction" value="Cancel">
<input type="submit" name="SubmitAction" value="Save">
}
However, this will quickly become a mess. You can also use attributes to let submit buttons map to action methods (though for simplicity I removed the "action:" prefix used for localization, be sure to read that Q&A and the linked blog):
[HttpPost]
[MultipleSubmit(SubmitAction = "Save")]
public ActionResult Save(Foo model)
{
_yourBLL.Save(model);
return View();
}
[HttpPost]
[MultipleSubmit(SubmitAction = "Cancel")]
public ActionResult Cancel(Foo model)
{
_yourBLL.Cancel(model);
return View();
}
You could do this with 2 forms, each posting to different action methods:
<form method="post" action="/cancelAction">
<input name="id" type="hidden" value="some-id-value">
<input type="submit" value="Cancel">
</form>
<form method="post" action="/confirmAction">
<input name="id" type="hidden" value="some-id-value">
<input type="submit" value="Confirm">
</form>
Or using MVC Razor syntax since you mentioned it:
#using (Html.BeginForm("cancelAction", "MyController", FormMethod.Post))
{
#Html.HiddenFor(model => model.ID)
<input type="submit" value="Cancel">
}
#using (Html.BeginForm("confirmAction", "MyController", FormMethod.Post))
{
#Html.HiddenFor(model => model.ID)
<input type="submit" value="Confirm">
}
From the information above it seems hard to pin down the exact use case here, however it might not be neccessary to have both a post for the confirm and cancel.
Consider using the submit event for "confirmation" and then just call the cancel event using normal HTTP-GET and passing the item that needs to be cancelled's ID? Then you can either handle the confirm or cancel events in either of the Actions directly or do a RedirectToAction to the HugeUniversalAction.
#using (Html.BeginForm("Confirm","ExampleController",FormMethod.Post))
{
<input type/>
<input type="submit" value="confirm"/>
#Html.ActionLink("Cancel", "ExampleController", id = Model.Id)
}
Then in your controller you can call the larger universal method.
public ActionResult Cancel(int id)
{
// Cancel directly
// or
return RedirectToAction("HugeUniversalAction", new { confirm = "false", id = id });
}
[HttpPost]
public ActionResult Confirm(Foo model)
{
// Confirm Directly
// or
return RedirectToAction("HugeUniversalAction", new { confirm = "true", id = model.Id });
}
Then handle the two paths in whichever way you need to in your HugeUniversalAction
public ActionResult HugeUniversalAction(int id, confirm = false){ // If confirm confirm it else cancel it }

ASP.NET MVC 5: passing POST data between views

I'd like to ask a very simple question from a rookie. I want to pass data from view Alpha.cshtml, into controller HomeController.cs with action Beta(), and then display this data in view Beta.cshtml.
Here's my Alpha.cshtml:
#using (Html.BeginForm("Beta", "Home", null, FormMethod.Post, null))
{
#Html.TextBox("data")
<input type="submit" value="Submit" />
}
Here's my Beta.cshtml:
<p>The submitted value is: #ViewBag.Data</p>
And here's my Beta() action:
public ActionResult Beta()
{
ViewBag.Data = ???
return View();
}
What do I put in place of the ???
Thanks!
When the form is submitted, all form input fields will be posted to the server. ModelBinding will take care of reading the posted values and supplying them to your action method in the list of parameters.
[HttpPost]
public ActionResult Beta(string data)
{
ViewBag.Data = data
return View();
}

Using webforms in MVC

I am learning MVC, following THIS tutorial. (link will take you directly to where i'm stuck). so far I have learnt, there's a controller for every view. Now i have to take input from user through web entry form as mentioned in tutorial. In my project, i have a controller named Default1 and i can run it as localhost:xyz/Default1/Index. it runs perfect.
Then i created a new Controller, named Default2 and bound it to some view to display some data, and it worked perfect as localhost:xyz/Default2/Displaycustomer. the customer information was static (hard coded). and controller is as:
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = "12";
cobj.Name = "Zeeshan";
cobj.Amount = 7000;
return View("DisplayCustomers",cobj);
}
Now i have to take input from User, regarding cutomer iformation, using html page as mentioned in tutorial. so i tried adding a new webform under view folder, and and modified my controller as:
[HttpPost]
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = Request.Form["Id"].ToString();
cobj.Name = Request.Form["Name"].ToString();
cobj.Amount = Convert.ToDouble(Request.Form["Amount"].ToString());
return View("DisplayCustomers",cobj);
}
My Question is: How can i make my project stared, so that it takes input first, and then displays it, using above controller? Did i add the webform at right location? What would be the link to run it? i tried localhost:xyz/Default2/entryform etc. but failed.
(in my entryform.aspx, i have mentioned form action="DisplayCustomer" )
It sounds like what you're missing is an action to just display the form. In otherwords, you just need an action to display a form. That form's POST action should reference your controller's DisplayCustomers action.
So in your controller code:
public class CustomerController : Controller
{
[HttpGet]
public ViewResult New()
{
return View("NewCustomer"); //Our view that contains the new customer form.
}
// Add your code for displaying customers below
}
And in your view, you have code like this
#using(Html.BeginForm("DisplayCustomers", "Customer")) {
<!-- Add your form controls here -->
}
Notice that I'm using the version of the BeginForm helper that specifies the action method and controller to call. This will write the form tag to post back to your DisplayCustomers action. Here is the equivalent HTML:
<form method="POST" action="/Customer/DisplayCustomers">
You would then access your form using the URL http://test.server/Customer/New.
This may not be the best example in the world...but this will at least get you rolling..
url would be:localhost:1234/Home/Customer
the controller
public ActionResult Customer()
{
return View();
}
[HttpPost]
public ActionResult Customer(FormCollection frm)
{
var name = frm["name"].ToString();
var address = frm["address"].ToString();
ViewBag.Name = name;
ViewBag.Address = address;
return View();
}
The view
<div>
#using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="text" name="address" id="address"/>
<input type="submit" name="submit" value="submit" />
<input type="text" name="namedisplay" value='#ViewBag.Name'/>
<input type="text" name="addressdisplay" value='#ViewBag.Address'/>
}
</div>

ASP.NET MVC Html.BeginForm decodes URL

I'm requesting ASP.NET MVC the controller using the URL like this:
http://mysite.com/controller/myaction/Invalid%23name%25x
where Invalid%23name%25x is a parameter to
public ActionResult MyAction(string id) {
return View();
}
The GET request works fine.
MyAction view looks like this:
#using (Html.BeginForm()) {
...
<input name="Save" type="submit" value="Save" />
}
The generated HTML is:
<form action="/Controller/MyAction/Invalid#name%x" method="post">
...
<input name="Save" type="submit" value="Save" />
</form>
When I click on "Save", the form gets posted and the POST request goes to
http://mysite.com/controller/myaction/Invalid#name%x
i.e. the initial URL is decoded. This means the the POST action receives only the first part of the parameter - "Invalid"
[HttpPost]
public ActionResult MyAction(string id, ...) {
return View();
}
How can I prevent Html.BeginForm from decoding the initial URLs in order to preserve the initial state?
Pass ActionName and Controller in your form
#using (Html.BeginForm("ActionName", "Controller")) {
I would personally recommend you not to use id as string because as you have seen string can have many words in it.. let it mean what usually it does(numeric value).
use something like http://mysite.com/controller/myaction?Name=Invalid%23name%25x
public ActionResult MyAction(string Name) {
return View();
}
I suppose this would work for you..

Why Ajax.BeginForm does not pass form values?

I'm trying to show a partial view via calling Ajax.BeginForm, but I can't receive the values of my form(I need to get the value of hidden input, bookId, in controller, e.g 5).
// View
#using (Ajax.BeginForm("Detail", "Books", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "ShowBookDiv" }))
{
<input type="hidden" id="bookId" value="5" />
<input type="submit" id="sBtn" value="Details" />
}
// Controller
[HttpGet]
public ActionResult Detail(string bookId)
{
if (Request.IsAjaxRequest())
{
var a = Request["bookId"].ToString();
// some code to get details
return PartialView("ShowBooks", details);
}
...
}
When I trace the code in Controller bookId is null!
I've added the "name" property to hidden field and it works !!! really strange!
<input type="hidden" name="bookId" id="bookId" value="5" />
Ajax.BeginForm is a pain, IMO.
I would Use $.ajax from JQuery Ajax API :
http://api.jquery.com/jQuery.ajax
here is a good example for you to see how it works :
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views
Posting the whole form requires a little bit of work (in terms of validation, etc.) but you will have complete control over the action if you are good with JavaScript.

Resources