Seyed Morteza Mousavi
Seyed Morteza Mousavi

Reputation: 6963

Having two forms with single model in ASP.Net MVC

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

Answers (4)

Jakotheshadows
Jakotheshadows

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

Daniel Gpe Reyes
Daniel Gpe Reyes

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

Varun Vasishtha
Varun Vasishtha

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

Lion
Lion

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

Related Questions