I recently came upon this question as I have a solution I need to work on.
I have a controller which does some logic, with some method:
public Controller1: MvcController
{
public ActionResult SomeLogic(Model model)
{
return view();
}
public ActionResult SomeLogic2(Model model)
{
return view();
}
}
And I have a second controller which does different logic:
public Controller2: MvcController
{
public ActionResult SomeLogic(Model model)
{
return view();
}
public ActionResult SomeLogic2(Model model)
{
return view();
}
}
Both are working on the same view:
MyView.cshtml
The view contains a begin form that works on submit:
#using(Html.BeginForm("SomeLogic", "Controller1", FormMethod.Post)
and 4 submit buttons:
<input type='submit' formaction='SomeLogic' value='submit' />
<input type='submit' formaction='SomeLogic2' value='submit2' />
<input type='submit' formaction='SomeLogic' value='submit3' />
<input type='submit' formaction='SomeLogic2' value='submit4' />
I know I can control the action to which I am redirecting the submit using the:
formaction attribute.
I there a way to change the controller as well? meaning that:
<input type='submit' formaction='SomeLogic' value='submit3' />
<input type='submit' formaction='SomeLogic2' value='submit4' />
Will submit to controller2 instead of Controller1 which is defined in my begin form.
This will solve my debate whether to create a new controller or use the existing one, which is already full of complex logic.
You need to include controller name in the formaction attribute.
Note that your controller names are not valid, but assuming your have
public FirstController: Controller
{
[HttpPost]
public ActionResult SomeLogic(Model model)
{
return view();
}
}
public SecondController: Controller
{
[HttpPost]
public ActionResult SomeLogic(Model model)
{
return view();
}
}
Then you can post to the correct controller using
// Post to the SomeLogic method of FirstController
<input type="submit" formaction="#Url.Action("SomeLogic", "First")" value="submit" />
// Post to the SomeLogic method of SecondController
<input type="submit" formaction="#Url.Action("SomeLogic", "Second")" value="submit3" />
Just intercept the submit with jQuery
You can add an ID to your form, to be able to select it easily in jQuery
#using(Html.BeginForm("SomeLogic", "Controller1", FormMethod.Post, new { #id = "yourForm" })
Then
$("#yourForm").submit(function(e){
e.preventDefault();
var url1 = '#(Url.Action("SomeLogic1", "SomeController", null, Request.Url.Scheme))';
var url2 = '#(Url.Action("SomeLogic", "SomeController2", null, Request.Url.Scheme))';
//Whatever logic should you do to select which URL you want to POST to
$.ajax({
type: 'POST',
url: url_selected_above,
data: $('#yourForm').serializeArray(),
success: function (xhr, response) {
//...
},
error: function (xhr, response) {
//...
}
});
});
This should work if all the methods expect the same view model.
Alternatively, if you do not want to mess around in the UI, you can do something as such in the action that generates the form.
var controllerName = "SomeController";
var actionName = "Action1";
//do your logic to select whichever controller/action.
viewModel.ControllerName = controllerName;
viewModel.ActionName = actionName;
And in the view that has the form:
#using(Html.BeginForm(#Model.ActionName, #Model.ControllerName, FormMethod.Post)
Again, if all the actions expect the same view model, that should work.
Related
I can post elements from my form if I make a direct reference to the named element in the controller parameters. I am trying to use FormCollection so I do not have to type every element from the form in the post ActionResult parameters.
The HTML form:
#using (Html.BeginForm("legallabels", "Reports", FormMethod.Post, new { id = "reportForm", #class = "report-form col-9" }))
{
<div class="col-12">
<b>Beginning </b><input type="text" class="form-control col-2" id="beginningDatePicker" name="beginningDate" value="#DateTime.Today.Date.ToString("MM/dd/yyyy")" />
</div>
<input type="submit" value="submit">
}
Controller using named parameter (beginningDate):
[HttpPost]
public ActionResult LegalLabels(string beginningDate)
{
return View();
}
When using FormCollection, it does not get passed to the controller:
[HttpPost]
public ActionResult LegalLabels(FormCollection form)
{
return View();
}
Using a breakpoint in the controller, I can see that the form is posting correctly and everything works fine when naming form elements (beginningDate) in the parameters. I've looked at similar samples of code that use FormCollection and they seem to work fine. Why are my FormCollection values not getting passed to the controller?
Tested your code, it works fine. If you see the snippet below you can loop through all posted values and check.
[HttpPost]
public ActionResult LegalLabels(FormCollection form)
{
StringBuilder sb = new StringBuilder();
foreach (var key in form.AllKeys)
{
sb.AppendLine(string.Format("Key: {0}. Value: {1}.<br>", key, form[key]));
}
ViewBag.FormData = sb.ToString();
return View();
}
On the cshtml
<div>
#Html.Raw(ViewBag.FormData)
</div>
After renaming FormCollection to IFormCollection, everything is working properly.
Ajax.BeginForm() not working when Html.EditorFor() contains special charactor <
It does not invoke the controller action on submit the form
Have you tried the following:
Index.cshtml
#using (Ajax.BeginForm("PostForm", "Home", new AjaxOptions()))
{
string myFormValue = "";
#Html.EditorFor(x => myFormValue)
<input type="submit" value="Submit"/>
}
HomeController.cs
public class HomeController : Controller
{
public ActionResult PostForm(string myFormValue)
{
return View("Index");
}
When i debug it seems to work:
May you post your code?
Controller's get and post method
[HttpGet]
public ActionResult Index()
{
SoSession.Authenticate("pierre", "pierre");
return View();
}
[HttpPost]
public ActionResult Index(CompanySearch model)
{
return RedirectToAction("Companies",new{searchString=model.SearchString});
}
in view
#using (Html.BeginForm("Index", "Company"))
{
<div class="input-block-level">
#Html.TextBoxFor(m => m.SearchString)
#Ajax.ActionLink(
"Submit",
"Index",
new{},
new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "partialDiv" })
</div>
}
<div id="partialDiv"></div>
Problem
Whenever user clicks submit link i get forwarded to get method and not post method. How do i forward the call to post method of my controller?
Make sure you have the unobutrusive ajax library file (and it's dependencies (jQuery)) loaded to your view properly. If you do not have this file loaded to your page, Clicking on the link produced by Ajax.ActionLink helper method will do a GET request instead of the asynchronous POST you were expecting.
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
It sounds like you are trying to use an ajax form:
#using Ajax.BeginForm("Submit", "Company", FormMethod.Post, new AjaxOptions { UpdateTargetId = "partialDiv", InsertionMode = InsertionMode.Replace}) {
#Html.TextBoxFor(m => m.SearchString)
}
If you include the ajax js libraries that should work.
You can also use JQuery for the partial load although the controller would return a partial. I do agree with mayabelle that Ajax.BeginForm() is another route to take.
[HttpGet]
public ActionResult Companies(string searchString)
{
return this.PartialView("MyView", MyObject)
}
inside of the cshtml javascript:
var searchString = $("#SearchString").val();
$("#partialDiv").load('#Url.Content("~/Home/Companies/")' + searchString, function(){ DoSomething(); });
I am new to mvc 3. i am trying to create a view and controller. my scenario is that i have controller which has two actions. while i call first action inside controller i have to load default values to view. inside view i have a buttons to post back values. so while click one of the button inside view, it has to go second action in same controller and has to return back to same view with success or failure message.
My view is like this
#using (Html.BeginForm())
{
<table>
<tr>
<td>
#Html.TextBox("txtTitle")
</td>
<td>
<input type="button" value="Go Somewhere Else" onclick="location.href='#Url.Action("Postback", "Default1")'" />
</td>
</tr>
</table>
}
My Controller,
public class Default1Controller : Controller
{
//
// GET: /Default1/
public ActionResult Index()
{
// has to default load value to text box
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Postback(FormCollection obj)
{
// has to take value from txt box
object obj1 = Request["txtTitle"];
return View("Index");
}
}
My problem if call Postback action from any other view it works. but inside same view if i click on button the error shows like "http://localhost:14953/Default1/Postback".
What is solution here? i expect to navigate to same controller as well as to other controller inside same form and return to same view.
As reference to this article.....
public class HttpParamActionAttribute : ActionNameSelectorAttribute {
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
return false;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
In view form like this...
#using (Html.BeginForm("Action", "Post")) {
<!— …form fields… -->
<input type="submit" name="SaveDraft" value="Save Draft" />
<input type="submit" name="Publish" value="Publish" />
}
and actions in controller...
public class PostController : Controller {
[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveDraft(…) {
//…
}
[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Publish(…) {
//…
}
}
You can specify an ActionName to your Postback method like this:
[ActionName("Index")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Postback(FormCollection obj)...
So F5 repost the same values and calling the URL directly from the address bar returns the View as expected.
There is a constructor for Html.BeginForm Helper method which takes action name and controller name. Use that
public static MvcForm BeginForm(
this HtmlHelper htmlHelper,
string actionName,
string controllerName
)
http://msdn.microsoft.com/en-us/library/dd492590.aspx
So your form should look like this. You dont need the onclick function in your input element.
#using (Html.BeginForm("Postback", "Default1"))
{
//Your elements
<input type="button" value="Go Somewhere Else" />
}
That will render the HTML markup like this
<form action="/Default1/Postback" method="post">
// Your elements
<input type="button" value="Go Somewhere Else" />
</form>
If you want multiple submit button in the same form, It is answered here
I think we can specific action and controller at Html helper.
#using (Html.BeginForm("Postback", "Default1"))
{
<table>
<tr>
<td>
#Html.TextBox("txtTitle")
</td>
<td>
<input type="submit" value="Go Somewhere Else" />
<!-- the input should be submit?-->
</td>
</tr>
How can i pass to asp.net mvc action parameters like: line[first], line[second], line[third], people[john] etc?
For example we have html:
<form>
<input type="hidden" name="line[first]" value="hello" />`
<input type"submit" value="send" />
</form>
How we can take "line[first]" value when user clicks on send button?
[HttpPost, ValidateAntiForgeryToken]
public ActionResult ShowLogin(LoginModel model)
{
model.username;
model.password
}
instead of admin you can have
public ActionResult ShowLogin(FormCollection form)
{
var user = form["username"];
}