MVC 一页多个提交表单(Multi_Form in one page)

前几天遇到同一页有多个提交表单的情况,经过艰苦奋斗终于解决。与大家分享一下。

我的要求有两个:①可以验证显示错误信息②显示错误信息的时候原保留填写的内容

未查找资料之前想了3个解决方案:

①将页面中所有的提交对象封装为一个对象,提交的时候只提交所需要的内容,当有错误信息的时候将已填的内容付给此此对象然后返回它。

优点:可以使用ModelState验证

缺点:如果需要重新写类,如果属性多就很麻烦,重用性低

②页面的对象定为多个form中的一个,其余的使用js验证

优点:可以部分使用ModelState验证

缺点:js使用麻烦需要前台后台写方法,验证麻烦

③建立多个相同的页面,不过页面的对象不同,每个form的对象一个页面,如果有错则转到对象对应的页面。

优点:可以使用ModelState验证

缺点:需要建立多个页面,其实质是转到其他地址。

 

经过深思熟虑如果第一种改良一下是不错的。

在网上找了半天终于找到与第一种相似的解决方案,不过国家完美。

方法如下:

①扩展HtmlHelper的beginForm 方法,添加一个参数表单名“formName”指定选用哪个Action方法,如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc.Html;
using System.Web.Mvc;

namespace MultiFormTest
{
    public static class HtmlHelperExtession
    {
        /// <summary>
        /// formName
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="formName">formName</param>
        /// <returns></returns>
        public static MvcForm BeginForm(this HtmlHelper htmlHelper, string formName)
        {
            return BeginForm(htmlHelper, null, formName);
        }
        /// <summary>
        /// MvcForm form, string formName
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="form">form</param>
        /// <param name="formName">formName</param>
        /// <returns></returns>
        public static MvcForm BeginForm(this HtmlHelper htmlHelper, MvcForm form, string formName)
        {
            if (String.IsNullOrEmpty(formName))
                throw new ArgumentNullException("formName");

            if (form == null)
                form = htmlHelper.BeginForm();

            htmlHelper.ViewContext.Writer.WriteLine("<input name=\"n.__formName\" type=\"hidden\" value=\"" + formName + "\" />");

            return form;
        }
    }
}

Model对象如下,AccountModel 为页面对象,TestModel 和LogOnModel为form对象,将Form对象作为属性传给页面

 

 public class AccountModel
    {
        public TestModel Test { get; set; }
        public LogOnModel LogOn { get; set; }
    }
    public class TestModel
    {
        public string MyUserName { get; set; }
        public string MyEmail { get; set; }
        public string MyPassword { get; set; }
        public string MyConfirmPassword { get; set; }
    }
    public class LogOnModel
    {
        [Required]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        public bool RememberMe { get; set; }
    }

actionResult 方法,其中"LogOn"和Registertest"表单名

        [HttpPost]
        [FormActionSelector("LogOn")]
        public ActionResult Index(LogOnModel logOn)
        {
            var account = new AccountModel { LogOn = logOn };
            return View(account);
        }

        [HttpPost]
        [FormActionSelector("Registertest")]
        public ActionResult Index(TestModel test)
        {
            var account = new AccountModel { Test = test };
            return View(account);
        }

页面代码

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MultiFormTest.AccountModel>" %>

<%@ Import Namespace="MultiFormTest" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        <%: ViewData["Message"] %></h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">
            http://asp.net/mvc</a>.
    </p>
      <% using (Html.BeginForm("Registertest"))
       { %>
    <%: Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.") %>
    <div>
        <fieldset>
            <legend>Account Information</legend>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.Test.MyUserName)%>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Test.MyUserName)%>
                <%: Html.ValidationMessageFor(m => m.Test.MyUserName)%>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.Test.MyEmail)%>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Test.MyEmail)%>
                <%: Html.ValidationMessageFor(m => m.Test.MyEmail)%>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.Test.MyPassword)%>
            </div>
            <div class="editor-field">
                <%: Html.PasswordFor(m => m.Test.MyPassword)%>
                <%: Html.ValidationMessageFor(m => m.Test.MyPassword)%>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.Test.MyConfirmPassword)%>
            </div>
            <div class="editor-field">
                <%: Html.PasswordFor(m => m.Test.MyConfirmPassword)%>
                <%: Html.ValidationMessageFor(m => m.Test.MyConfirmPassword)%>
            </div>
            <p>
                <input type="submit" value="Register" />
            </p>
        </fieldset>
    </div>
    <% } %>
    <% using (Html.BeginForm("LogOn"))
       { %>
    <%: Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %>
    <div>
        <fieldset>
            <legend>Account Information</legend>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.LogOn.UserName) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(m => m.LogOn.UserName)%>
                <%: Html.ValidationMessageFor(m => m.LogOn.UserName)%>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(m => m.LogOn.Password)%>
            </div>
            <div class="editor-field">
                <%: Html.PasswordFor(m => m.LogOn.Password)%>
                <%: Html.ValidationMessageFor(m => m.LogOn.Password)%>
            </div>
            <div class="editor-label">
                <%: Html.CheckBoxFor(m => m.LogOn.RememberMe)%>
                <%: Html.LabelFor(m => m.LogOn.RememberMe)%>
            </div>
            <p>
                <input type="submit" value="Log On" />
            </p>
        </fieldset>
    </div>
    <% } %>
  
</asp:Content>
HTML代码
<fieldset>
 <legend>Account Information</legend>
            <div class="editor-label">
                <label for="LogOn_UserName">UserName</label>
            </div>
            <div class="editor-field">
                <input id="LogOn_UserName" name="LogOn.UserName" type="text" value="admin" />
      </div>
            <div class="editor-label">
                <label for="LogOn_Password">Password</label>
            </div>
            <div class="editor-field">
                <input id="LogOn_Password" name="LogOn.Password" type="password" />
           </div>
            <div class="editor-label">
                <input id="LogOn_RememberMe" name="LogOn.RememberMe" type="checkbox" value="true" /><input name="LogOn.RememberMe" type="hidden" value="false" />
                <label for="LogOn_RememberMe">RememberMe</label>
            </div>
            <p>
                <input type="submit" value="Log On" />
            </p>
        </fieldset>
可以看到控件的Name 的值是对象.属性(如LogOn.UserName ),MVC识别这种样式,这是我所没想到的
效果:
image
 

image

 

image

经测试,有时这种方法得到的对象属性为Null ,不知为什么,很是郁闷,希望大家使用的的话命名等小心一下。不过可以将每个表单做成一个用户控件,控件对象为表单对象就可以避免这个情况。

测试model项目http://u.115.com/file/f1f7377159 

posted @ 2011-03-20 23:12  三岔路  阅读(3610)  评论(3编辑  收藏  举报