【问题标题】:Having two forms with single model in ASP.Net MVC在 ASP.Net MVC 中有两种形式的单一模型
【发布时间】:2015-10-09 01:55:31
【问题描述】:

在我看来,我有两种形式。一种形式的搜索记录。 Goto page {number of page} 的一种形式,支持分页。正如similar question 中几乎所有人所建议的那样,我必须为每个表单创建两个单独的操作。这将使我的工作变得非常轻松,但是在使用这些方法时我遇到了问题。

假设我有以下模型:

public class MyModel
{
    public string Name { get; set; }
    public string DateOfEmployment { get; set; }

    public int? PageNumber { get; set; }

}

以下观点:

@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' />

}

问题是当用户单击Go 按钮时,我怎么知道搜索字段值是什么来重新创建模型行?。如果我使用单一表单,我不知道单击了哪个按钮(以一种干净的方式)。那么在这种情况下我该怎么办呢?

【问题讨论】:

  • 你可以;将搜索字段保存在 Session 中或作为隐藏字段传递。
  • @ErikPhilips 你也同意有两个表格来解决这些问题?
  • 为什么需要两个表格?为什么不使用 1 项操作将整个模型与该表单中的所有字段一起使用?
  • @Jakotheshadows 我怎样才能找到点击了哪个按钮? GoSearch?
  • 为什么需要两个不同的按钮?有什么区别?

标签: c# asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

您不需要使用 2 个表单来完成此操作,有一种简单的方法可以使用带有两个按钮的单个表单,如下所示:

<button type='Submit' name="command" value='Search'>Search</button>

<button type='Submit' name="command" value='Go'>Go</button>

现在要识别点击了哪个按钮,您可以在操作级别执行此操作:

[HttpPost]
public ActionResult Index(string command)
{
    if(command == "Go")
    {
         //Do stuff
    }
    else
    {
         //do stuff
    }
}

【讨论】:

  • 我认为整个想法是他希望不同的命令执行不同的操作。
  • @Jakotheshadows 这是最初的问题:“如果我使用单一表单,我不知道点击了哪个按钮(以干净的方式)。那么在这种情况下我应该怎么做?”。我认为这清除了它
【解决方案2】:

如果你打算只实现 1 个表单,这里有一些可能对你有帮助的东西

创建一个助手

[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;
    }
}

然后在你的控制器中

    [HttpPost]
    [MultipleButton(Name = "action", Argument = "Step1")]
    public ActionResult Step1(YourModelType model)
    {}

    [HttpPost]
    [MultipleButton(Name = "action", Argument = "Step2")]
    public ActionResult Step2(YourModelType model)
    {}

然后在你看来

   <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>

【讨论】:

    【解决方案3】:

    使用一点 javascript,您可以只使用一个表单,并根据单击的按钮更改表单的操作,这样无论您发布到哪个操作,所有表单字段都将包含在内。

    @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>
    

    【讨论】:

      【解决方案4】:

      您需要将搜索数据(在您的情况下为名称和日期)存储在一个适合 ASP.NET 的会话中,因为它可以存储整个对象。请参阅以下问题如何做到这一点:How to use sessions in an ASP.NET MVC 4 application?

      或者您可以将它们传递给您的第二个表单的请求,因为我会解决这个问题:

      @using (Html.BeginForm("Pagination", "Home", FormMethod.Post, new { dateOfEmployment = Model.DateOfEmployment, name = Model.Name }))
          // ...
      }
      

      这将导致如下操作:

      [HttpPost]
      public ActionResult Pagination(string dateOfEmployment, string name) {
          // ...
      }
      

      或者,也可以将它们作为 POST 表单中的隐藏字段传递,例如

      @using (Html.BeginForm("Pagination", "Home", FormMethod.Post)) {
          // ...
          @Html.HiddenFor(model => model.DateOfEmployment)
          @Html.HiddenFor(model => model.Name)
      }
      

      顺便说一句,我建议您为属性 DateOfEmployment 使用正确的类型,例如 DateTime。这将使思考更加清晰和容易。特别是当您必须过滤数据时,例如形式或某种其他类型的视图。

      【讨论】:

      • 你的方法很好。但是我的隐藏字段列表太长,无法以分页形式放回。
      • 我不明白为什么您的答案有一个名为“分页”的操作但没有页码作为参数,以及为什么您不只是将整个模型作为参数。
      猜你喜欢
      • 2014-04-12
      • 1970-01-01
      • 2013-12-13
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多