关于后台的说明:
后台将会用easyui + ajax模式。
这里涉及两个问题,一个是使用easyui如何在前台验证模型的问题,另一个是ajax提交后返回数据。
一、Easyui验证
前台验证采用easyui控件的ValidateBox验证,通过自定义htmlhelper的方式建立与模型的联系。
1、到http://www.jeasyui.com/download/index.php下载EasyUi的最新版本,将js文件解压到~/script文件夹
将式样放到~/Areas/Admin/Content/Easyui/
然后打开BundleConfig.cs,添加如下代码
bundles.Add(new ScriptBundle("~/Scripts/Easyui").Include( "~/Scripts/Easyui/jquery.easyui.js", "~/Scripts/Easyui/locale/easyui-lang-zh_CN.js")); bundles.Add(new StyleBundle("~/Css/Admin/Easyui").Include("~/Areas/Admin/Content/Easyui/icon.css", "~/Areas/Admin/Content/Easyui/metro-blue/easyui.css"));
2、在~/Extensions文件夹中添加类EasyuiExtensions.cs
此类的目的是利用ModelMetadata元数据获取Model的验证Attribute然后生成带ValidateBox验证输入控件。
思路为:使用ModelMetadata.FromLambdaExpression获取模型字段的元数据->使用ModelValidatorProviders.Providers.GetValidators获取元数据中验证属性->根据属性生成ValidateBox的validType。
代码如下:
//////////////////// //Easyui控件Mvc扩展 //版本v1 //创建日期2013-09-28 //////////////////// using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace System.Web.Mvc.Html { /// <summary> /// EasyUi控件 /// </summary> public static class EasyuiExtensions { public static MvcHtmlString EasyuiInput<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string type = "input") { return htmlHelper.EasyuiInput(expression, null,type:type); } public static MvcHtmlString EasyuiInput<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, string type = "input") { return htmlHelper.EasyuiInput(expression, htmlAttributes: HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),type:type); } public static MvcHtmlString EasyuiInput<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, string type = "input") { ModelMetadata _metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); string _name = ExpressionHelper.GetExpressionText(expression); string _fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(_name); string _htmlCtrlstr = string.Empty;//控件Html字符 if (String.IsNullOrEmpty(_fullName)) { throw new ArgumentException(_name + " 字段不存在!", "name"); } TagBuilder tagBuilder = new TagBuilder(type); tagBuilder.MergeAttributes(htmlAttributes); tagBuilder.MergeAttribute("name", _fullName, true); tagBuilder.MergeAttribute("id", _fullName, true); //值 if (_metadata.Model != null) { if (type.ToLower() == "input") tagBuilder.MergeAttribute("value", (string)_metadata.Model); else if (type.ToLower() == "textarea") tagBuilder.InnerHtml = (string)_metadata.Model; } ///验证部分代码开始 Dictionary<string, object> _results = new Dictionary<string, object>(); string _validType = string.Empty; if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled) { IEnumerable<ModelClientValidationRule> _clientRules = ModelValidatorProviders.Providers.GetValidators(_metadata ?? ModelMetadata.FromStringExpression(_name, htmlHelper.ViewData), htmlHelper.ViewContext).SelectMany(v => v.GetClientValidationRules()); if (_clientRules.Count() > 0) { _validType = string.Empty; foreach (ModelClientValidationRule rule in _clientRules) { switch (rule.ValidationType) { case "required": break; case "length": if (!string.IsNullOrEmpty(_validType)) _validType += ","; if (rule.ValidationParameters.ContainsKey("min")) _validType += "'" + rule.ValidationType + "[" + rule.ValidationParameters["min"].ToString() + "," + rule.ValidationParameters["max"].ToString() + "]'"; else _validType += "'" + rule.ValidationType + "[0," + rule.ValidationParameters["max"].ToString() + "]'"; break; default: if (!string.IsNullOrEmpty(_validType)) _validType += ","; _validType += "'" + rule.ValidationType + "'"; break; } } if(!string.IsNullOrEmpty(_validType)) _validType = "validType:["+_validType+"]"; if (_metadata.IsRequired) { if (string.IsNullOrEmpty(_validType)) _validType = "required:true"; else _validType = "required:true," + _validType; } if (!string.IsNullOrEmpty(_validType)) tagBuilder.MergeAttribute("data-options", _validType); } } ///验证部分代码结束 if (type.ToLower() == "input") _htmlCtrlstr = tagBuilder.ToString((TagRenderMode.SelfClosing)); else if (type.ToLower() == "textarea") _htmlCtrlstr = tagBuilder.ToString(); return new MvcHtmlString(_htmlCtrlstr); } } }
二、ajax返回数据
ajax提交后返回数据包含是否成功,及消息提示,另外如果服务器验证失败的话还要返回一个失败字段列表,干脆建一个类。
在~/Models文件夹中添加类JsonData,代码如下:
///////////////// //版本:V1 //创建日期:2013-10-23 ///////////////// using System.Collections.Generic; namespace Ninesky.Models { public class JsonData { /// <summary> /// 操作成功 /// </summary> public bool Success { get; set; } /// <summary> /// 消息 /// </summary> public string Msg { get; set; } /// <summary> /// 消息列表 /// </summary> public Dictionary<string, string> MsgLsit { get; set; } public JsonData() { MsgLsit = new Dictionary<string, string>(); } } }
后台ajax提交后固定返回JsonData的json类型。
三、开始搭架子
1、添加布页
在~/Areas/Admin/Views/Shared中添加_Layout.cshtml。
后台页面采用easyui的layout,分north、south、west、center四个部分。代码如下:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> @Styles.Render("~/Css/Admin") @Styles.Render("~/Css/Admin/Easyui") @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/Scripts/Easyui") @Scripts.Render("~/Areas/Admin/Scripts/global.js") </head> <body class="easyui-layout"> <div id="north" data-options="region:'north'"> @Html.Action("PartialNorth","Home") </div> <div id="south" data-options="region:'south'"></div> @RenderBody() </body> </html>
2、后台管理的主页——Home
在~/Areas/Admin/Controllers 添加【HomeController】
为[Index] action添加视图
@{ ViewBag.Title = "管理中心"; } <div id="west" data-options="region:'west',title:' ',split:true" style="border-top:solid 1px #1BA1E2;border-right:solid 1px #1BA1E2;border-bottom:solid 1px #1BA1E2"></div> <div id="center" data-options="region:'center'"> <div id="tabs" class="easyui-tabs" data-options="fit:true" style="margin-left: auto; margin-right: auto"> <div title="欢迎" style="padding:20px;">欢迎使用后台管理……</div> </div> </div>
这里用到了easyui的layout和tabs。
添加返回分部视图的action [PartialNorth] 这个在布局也中调用,显示layout的North部分,也就是页面的头部(图中1的位置)。
/// <summary> /// 顶部视图 /// </summary> /// <returns></returns> public PartialViewResult PartialNorth() { return PartialView(); }
添加相应视图。
<div class="admininfo_bar">欢迎您:洞庭夕照 修改密码 退出 </div> <div class="tools_bar"> <a id="home" href="#"><img src="~/Areas/Admin/Content/images/home.png" /> 首页</a> <a id="cagegory_cfg" href="#"><img src="~/Areas/Admin/Content/images/folder.png" /> 栏目管理</a> <a id="system_cfg" href="javascript:void(0)"><img src="~/Areas/Admin/Content/images/config.png" /> 系统设置</a> </div>
完成后界面如下: