Reputation: 6963
I have two form in my view. One form searching records. One form for Goto page {number of page} to support pagination. As almost everyone suggested in similar question, I must create two separate action for every form. It will make my work very easy, but I have problem when using these approach.
Assume I have following model:
public class MyModel
{
public string Name { get; set; }
public string DateOfEmployment { get; set; }
public int? PageNumber { get; set; }
}
And following view:
@model WebApplication1.Models.MyModel
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { }))
{
@Html.LabelFor(m => m.DateOfEmployment)
@Html.EditorFor(m => m.DateOfEmployment)
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)
<input type='Submit' value='Search' />
}
<!-- Rows goes here-->
@using (Html.BeginForm("Pagination", "Home", FormMethod.Post, new { }))
{
@Html.LabelFor(m => m.PageNumber)
@Html.TextBoxFor(m => m.PageNumber)
<input type='Submit' value='Go' />
}
The problem is when user click Go
button, how can I know that what is search field values to recreate model rows?. If I use single form, I don't know which button clicked (in a clean way). So what should I do in these situation?
Upvotes: 0
Views: 3585
Reputation: 1515
Using a little javascript, you can use just one form and simply change the action of the form based on which button was clicked, that way no matter which action you post to, all form fields will be included.
@model WebApplication1.Models.MyModel
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id="MyForm" }))
{
@Html.LabelFor(m => m.DateOfEmployment)
@Html.EditorFor(m => m.DateOfEmployment)
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)
@Html.LabelFor(m => m.PageNumber)
@Html.TextBoxFor(m => m.PageNumber)
<button value='Search' onclick="search()" />
<button value='Go' onclick="go()" />
<input type="submit" style="display:none" />
}
<script type="text/javascript">
function search() {
var form = document.getElementById("MyForm");
form.action = "@Url.Action("ActionNameForSearch", "ControllerNameForSearch")";
form.submit();
}
function go() {
var form = document.getElementById("MyForm");
form.action = "@Url.Action("ActionNameForGo", "ControllerNameForGo")";
form.submit();
}
</script>
Upvotes: 1
Reputation: 417
if you are goin to implement just 1 form here is somenthign that maybe can help you
create a helper
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
public string Name { get; set; }
public string Argument { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var keyValue = string.Format("{0}:{1}", Name, Argument);
var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
isValidName = true;
}
return isValidName;
}
}
then in your controller
[HttpPost]
[MultipleButton(Name = "action", Argument = "Step1")]
public ActionResult Step1(YourModelType model)
{}
[HttpPost]
[MultipleButton(Name = "action", Argument = "Step2")]
public ActionResult Step2(YourModelType model)
{}
and then in your view
<form>
<input type="submit" value="Step1" name="action:Step1" class="button admin-button">
<input type="submit" value="Step2" name="action:Step2" class="button admin-button">
</form>
Upvotes: 1
Reputation: 461
You need not to take 2 forms to accomplish this, there is a simple way take single form with two button like this :
<button type='Submit' name="command" value='Search'>Search</button>
<button type='Submit' name="command" value='Go'>Go</button>
Now to recognize which button was click you can do this on action level :
[HttpPost]
public ActionResult Index(string command)
{
if(command == "Go")
{
//Do stuff
}
else
{
//do stuff
}
}
Upvotes: 4
Reputation: 17908
You need to store the search-data (name and date in your case) in a session which is comfortable in ASP.NET because its possible to store entire objects. See the following question how to to do that: How to use sessions in an ASP.NET MVC 4 application?
Or you can pass them to the request of your second form as I would solve this problem:
@using (Html.BeginForm("Pagination", "Home", FormMethod.Post, new { dateOfEmployment = Model.DateOfEmployment, name = Model.Name }))
// ...
}
This will result in an action like this:
[HttpPost]
public ActionResult Pagination(string dateOfEmployment, string name) {
// ...
}
Alternatively its also possible to pass them as hidden fields in the POST form like
@using (Html.BeginForm("Pagination", "Home", FormMethod.Post)) {
// ...
@Html.HiddenFor(model => model.DateOfEmployment)
@Html.HiddenFor(model => model.Name)
}
By the way I would recommend to use correct types like a DateTime for your attribute DateOfEmployment. This will make thinks more clean and easy. Escpecially when you have to filter your data for e.g. the form or some other sort of view.
Upvotes: 0