问题的提出:在MVC下动态表单怎么生成?
好的,我们来看下面的例子:
接着上次的MVCMembership来讲
我们首先添加一个目录XML。然后添加View:
1.checkXml.aspx 用来检查我们输入的XML格式(利用XSD检查)
2.New.aspx 用来新增XML表单的
3.Show.aspx 用来显示XML表单的
4.ShowResult.aspx 用来显示XML表单提交的结果的
一、数据库结构
要用到动态的表单,这里我们利用SQLServer2005的XML类型来保存,建表的SQL如下:
use Test /*==============================================================*/ /* DBMS name: Microsoft SQL Server 2005 */ /* Created on: 2009/5/8 7:56:50 */ /*==============================================================*/ if exists (select 1 from sysindexes where id = object_id('XMLFORM') and name = 'IDX_XML' and indid > 0 and indid < 255) drop index XMLFORM.IDX_XML go if exists (select 1 from sysindexes where id = object_id('XMLFORM') and name = 'IDX_ID' and indid > 0 and indid < 255) drop index XMLFORM.IDX_ID go if exists (select 1 from sysobjects where id = object_id('XMLFORM') and type = 'U') drop table XMLFORM go /*==============================================================*/ /* Table: XMLFORM */ /*==============================================================*/ create table XMLFORM ( ID int identity, FORMXML xml not null, constraint PK_XMLFORM primary key (ID) ) go declare @CurrentUser sysname select @CurrentUser = user_name() execute sp_addextendedproperty 'MS_Description', 'XMLFORM', 'user', @CurrentUser, 'table', 'XMLFORM' go /*==============================================================*/ /* Index: IDX_ID */ /*==============================================================*/ create unique index IDX_ID on XMLFORM ( ID ASC ) go /*==============================================================*/ /* Index: IDX_XML */ /*==============================================================*/ create PRIMARY XML INDEX IDX_XML on XMLFORM ( FORMXML ) go
好了我们建了一个名为XMLForm的表,其中ID自增,FORMXML为我们需要的XML表单的内容
二、编写XML的Controller
XMLController.cs
主要的action
1.New
[AcceptVerbs(HttpVerbs.Post), ValidateInput(false)] public ActionResult New(string xmlContent) { System.Threading.Thread.Sleep(2000); //模拟提交等待 xmlContent = Server.UrlDecode(xmlContent); if (!string.IsNullOrEmpty(xmlContent)) { //if (!CheckXML(xmlContent, out strError)) //服务器端检测,如果用了ajax检测,就没必要了 //{ // ModelState.AddModelError("_FORM",strError); // return View(); //} XMLFormDataContext db = new XMLFormDataContext(); TransactionOptions opt = new TransactionOptions(); ViewData["xmlContent"] = xmlContent; opt.IsolationLevel = IsolationLevel.Serializable; using (TransactionScope tran = new TransactionScope(TransactionScopeOption.RequiresNew, opt)) { XMLFORM f = new XMLFORM(); try { f.FORMXML = XElement.Parse(xmlContent); db.XMLFORMs.InsertOnSubmit(f); db.SubmitChanges(); var id = db.XMLFORMs.Max(p => p.ID); ViewData["result"] = "success"; ViewData["id"] = (int)id; tran.Complete(); return View(); } catch { ViewData["result"] = "failure"; ModelState.AddModelError("_FORM", "envalid xml format"); return View(); } } } else return View(); }
XML:
<Form Title="testForm"> <Input Text="ID" Name="txtID" Type="TextBox" Required="true"></Input> <Input Text="Name" Name="txtName" Type="TextBox" Required="true"></Input> <Input Text="Job" Name="txtJob" Type="TextBox" Required="false"></Input> <Input Text="Validate" Name="btnValidate" Type="Button"></Input> <Input Text="Commit" Name="btnComit" Type="Button"></Input> </Form>
注意:我们使用了事务,所以不要忘了最后要提交。我就是忘了,找了3天错误
2.Show
[AcceptVerbs(HttpVerbs.Get)] public ActionResult Show(int? ID) { int nId = 0; XElement doc = null; if (int.TryParse(Request["id"], out nId)) { try { XMLFormDataContext db = new XMLFormDataContext(); var q = from f in db.XMLFORMs where f.ID == nId select f.FORMXML ; if (q.Count() > 0) { foreach (var qq in q) { doc = qq; } ViewData["xml"] = doc; } else { ModelState.AddModelError("_FORM", "Not Exists"); } ViewData["id"] = nId; } catch (Exception e) { ModelState.AddModelError("_FORM", e.Message); } } else { ModelState.AddModelError("_FORM", "Miss ID"); } return View(); }
注意这里Show.asp的写法.不能用<input …/>直接输出控件字符串,而要
Response.Write(Html.TextBox(i.Attribute("Name").Value, "", new { @class = "InputNormal" }));
否则提交后得不到form的值
代码如下:
<%using (Html.BeginForm()) { %> <%=Html.ValidationSummary()%> <h2> Show XML Form</h2> <div id="divResult"></div> <fieldset> <legend>XML Form Information</legend> <table cellpadding="0" cellspacing="0" width="90%"> <% XElement xml=(XElement)ViewData["xml"]; StringBuilder sbScript = new StringBuilder(); sbScript.AppendLine("<Script language='javascript'>"); sbScript.AppendLine("function checkControls() {"); var input = from p in xml.Elements() where p.Name == "Input" && p.Attribute("Type").Value != "Button" select p; foreach (var i in input) { Response.Write("<tr>"); if (bool.Parse(i.Attribute("Required").Value)) { sbScript.AppendLine(string.Format( @"$('#{0}').formValidator({{onshow:'please input {1}',onfocus:'{1} required',oncorrect: 'OK' }})", i.Attribute("Name").Value, i.Attribute("Text").Value) ); sbScript.AppendLine( string.Format(".inputValidator({{ min: 1, empty: {{ leftempty: true, rightempty: true}}, onerror: '{1} required' }});", i.Attribute("Name").Value, i.Attribute("Text").Value )); } Response.Write(string.Format("<td>{0}</td>", i.Attribute("Text").Value)); Response.Write("<td>"); Response.Write(Html.TextBox(i.Attribute("Name").Value, "", new { @class = "InputNormal" })); Response.Write("</td>"); Response.Write(string.Format("<td><div id='{0}Tip'></div></td>",i.Attribute("Name").Value)); Response.Write("</tr>"); } sbScript.AppendLine("}</script>"); Response.Write(sbScript); input = from p in xml.Elements() where p.Name == "Input" && p.Attribute("Type").Value == "Button" select p; foreach (var b in input) { Response.Write("<tr>"); switch (b.Attribute("Text").Value.ToLower()) { case "commit": Response.Write(string.Format("<td colspan=3><input id='{0}' type='submit' value='{1}' /></td>", b.Attribute("Name").Value, b.Attribute("Text").Value)); break; case "validate": Response.Write(string.Format("<td colspan=3><input id='{0}' type='button' value='{1}' onclick='return jQuery.formValidator.pageIsValid();' /></td>", b.Attribute("Name").Value, b.Attribute("Text").Value)); break; } Response.Write("</tr>"); } %> </table> </fieldset> <%} %>
XML内容的检测
我们可以利用XSD来检查。
代码如下
#region 检查xml [AcceptVerbs(HttpVerbs.Post), ValidateInput(false)] public ActionResult checkXML(string xmlContent) { string strOut = string.Empty; int nResult = (CheckXML(xmlContent, out strOut) == true) ? 1 : 0; Dictionary<string, string> dicResult = new Dictionary<string, string>(); dicResult.Add("State", nResult.ToString()); dicResult.Add("Message", strOut); return Json(dicResult); } private bool CheckXML(string xmlContent) { bool bResult = true; if (!string.IsNullOrEmpty(xmlContent)) { //利用XmlSchemaSet(XSD)检查XML XmlSchemaSet validator = new XmlSchemaSet(); validator.Add("", XmlReader.Create(Server.MapPath(Url.Content("~/Models/xmlTest.xsd")))); //Url.Content必须,否则找不到文件 XDocument doc = null; try { doc = XDocument.Parse(xmlContent); doc.Validate(validator, (sender, e) => { bResult = false; }); } catch { bResult = false; } } else bResult = false; return bResult; } private bool CheckXML(string xmlContent, out string outString) { bool bResult = true; string strError = string.Empty; if (!string.IsNullOrEmpty(xmlContent)) { //利用XmlSchemaSet(XSD)检查XML XmlSchemaSet validator = new XmlSchemaSet(); validator.Add("", XmlReader.Create(Server.MapPath(Url.Content("~/Models/xmlTest.xsd")))); //Url.Content必须,否则找不到文件 XDocument doc = null; try { doc = XDocument.Parse(xmlContent); doc.Validate(validator, (sender, e) => { strError = e.Message; bResult = false; }); } catch (XmlException e) { strError = e.Message; bResult = false; } } else bResult = false; if (!bResult) outString = strError; else outString = "OK"; return bResult; } #endregion
这里我们返回json数据,来ajax检查
$(document).ready(function() { $("form").submit(function() { if (jQuery.formValidator.pageIsValid()) $.blockUI({ message: '<h1 class="loading">Please Wait...</h1>' }); }); if ($("#xmlContent").val() != "") $("#xmlContent").val(decodeURI($("#xmlContent").val())); $.formValidator.initConfig(); $("#xmlContent").formValidator({ onshow: "please input xml", onfocus: "xml required", oncorrect: "OK" }) .inputValidator({ min: 1, empty: { leftempty: true, rightempty: true }, onerror: "xml required" }) .ajaxValidator({ type: "post", url: "checkXML", datatype: "json", success: function(responseData) { if (responseData.State == "1") { return true; } else { return false; } }, buttons: $("#submit"), error: function() { alert("server busy,try later..."); }, onerror: "XML Format error or same content", onwait: "XML checking,please wait..." }); }); function CheckForm() { result = jQuery.formValidator.pageIsValid(); if (result) { $("#xmlContent").val(encodeURI($("#xmlContent").val())); } return result; }
注意我们利用了encodeURI,decodeURI进行编码,来避免A potentially dangerous Request.QueryString value was detected from the client问题
3.最后编写ShowResult
[AcceptVerbs(HttpVerbs.Post)] public ActionResult ShowResult() { StringBuilder sbResult = new StringBuilder(); foreach(string key in Request.Form.Keys) { sbResult.AppendLine(string.Format("{0}={1}", key, Request.Form[key])); } return Json(sbResult.ToString()); }
很简单的直接输出form的内容,你也可以进行你自己的处理,用ajax来避免再次刷新
最后结果
代码演示和下载 我的个人网站