通过实例学习Fireasy开发(补充)_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 通过实例学习Fireasy开发(补充)

通过实例学习Fireasy开发(补充)

 2015/4/5 22:46:40  fireasy  程序员俱乐部  我要评论(0)
  • 摘要:本文目录通过实例学习Fireasy开发(上篇)通过实例学习Fireasy开发(中篇)通过实例学习Fireasy开发(下篇)通过实例学习Fireasy开发(补充)前面的功能已经开发完成了,但是这里专门用一章来进行补充。一、EasyUI验证不知道你有没有发现,我们虽然在EmployeeMetada里加了验证特性RequiredAttribute、StringLengthAttribute,但是页面并没有在data-options里生成validType。这是由于少了Fireasy
  • 标签:学习 开发 实例

      本文目录

      通过实例学习Fireasy开发(上篇)

      通过实例学习Fireasy开发(中篇)

      通过实例学习Fireasy开发(下篇)

      通过实例学习Fireasy开发(补充)

 

 

      前面的功能已经开发完成了,但是这里专门用一章来进行补充。

 

      一、EasyUI验证

      不知道你有没有发现,我们虽然在EmployeeMetada里加了验证特性RequiredAttribute、StringLengthAttribute,但是页面并没有在data-options里生成validType。这是由于少了Fireasy.Portal组件造成了。我们只需要把ValidateBoxSettingBinder和NumberBoxSettingBinder这两个类拷贝过来就行了。

      ValidateBoxSettingBinder主要负责将基本的验证绑定到ValidateBoxSettings对象的ValidType属性中。

    /// <summary>
    /// <see cref="ValidateBoxSettings"/> 的绑定者。
    /// </summary>
    public class ValidateBoxSettingBinder : ISettingsBinder
    {
        public bool CanBind(ISettingsBindable settings)
        {
            return typeof(ValidateBoxSettings).IsAssignableFrom(settings.GetType());
        }

        public void Bind(Type modelType, string propertyName, ISettingsBindable settings)
        {
            //模型类型必须实现自 IEntity
            if (!typeof(IEntity).IsAssignableFrom(modelType))
            {
                return;
            }

            //获取对应的依赖属性
            var property = PropertyUnity.GetProperty(modelType, propertyName);
            if (property == null)
            {
                return;
            }

            var vsettings = settings as ValidateBoxSettings;
            //获取依赖属性所指定的验证特性
            var validTypes = new List<string>();
            foreach (var validation in ValidationUnity.GetValidations(property))
            {
                ParseValidation(vsettings, validation, validTypes);
            }

            vsettings.ValidType = validTypes.ToArray();
        }

        /// <summary>
        /// 解析 <see cref="ValidationAttribute"/> 对象。
        /// </summary>
        /// <param name="settings"></param>
        /// <param name="validation">要解析的 <see cref="ValidationAttribute"/> 对象。</param>
        /// <param name="validTypes">如果 <paramref name="validation"/>  能与 EasyUI 的客户端验证所对应,则添加到 validType 属性中。</param>
        private void ParseValidation(ValidateBoxSettings settings, ValidationAttribute validation, List<string> validTypes)
        {
            //必填验证特性
            var required = validation as RequiredAttribute;
            if (required != null)
            {
                settings.Required = true;
                return;
            }

            //长度验证特性
            var stringLength = validation as StringLengthAttribute;
            if (stringLength != null)
            {
                validTypes.Add(string.Format("length[{0},{1}]", stringLength.MinimumLength, stringLength.MaximumLength));
                return;
            }

            //电话验证特性
            var telphone = validation as TelphoneAttribute;
            if (telphone != null)
            {
                validTypes.Add("phone");
                return;
            }

            //手机验证特性
            var mobile = validation as MobileAttribute;
            if (mobile != null)
            {
                validTypes.Add("mobile");
                return;
            }

            //手机或电话验证特性
            var telOrMobile = validation as TelphoneOrMobileAttribute;
            if (telOrMobile != null)
            {
                validTypes.Add("phoneOrMobile");
                return;
            }

            //邮箱验证特性
            var email = validation as EmailAttribute;
            if (email != null)
            {
                validTypes.Add("email");
                return;
            }

            var ascii = validation as AsciiCodingAttribute;
            if (ascii != null)
            {
                validTypes.Add("ascii");
                return;
            }

            var un = validation as UserNameAttribute;
            if (un != null)
            {
                validTypes.Add("username");
                return;
            }

            var chinese = validation as ChineseCodingAttribute;
            if (chinese != null)
            {
                validTypes.Add("chinese");
            }
        }
    }

      NumberBoxSettingBinder主要负责把小数位、最大值、最小值绑定到NumberBoxSettings对象中。

    /// <summary>
    /// <see cref="NumberBoxSettings"/> 的绑定者。
    /// </summary>
    public class NumberBoxSettingBinder : ISettingsBinder
    {
        public bool CanBind(ISettingsBindable settings)
        {
            return typeof(NumberBoxSettings).IsAssignableFrom(settings.GetType());
        }

        public void Bind(Type modelType, string propertyName, ISettingsBindable settings)
        {
            var nsettings = settings as NumberBoxSettings;
            if (!typeof(IEntity).IsAssignableFrom(modelType))
            {
                return;
            }

            //获取对应的依赖属性
            var property = PropertyUnity.GetProperty(modelType, propertyName);
            if (property == null)
            {
                return;
            }

            nsettings.Precision = property.Info.Scale;

            //找 RangeAttribute 特性
            var range = ValidationUnity.GetValidations(property).Where(s => s is RangeAttribute).Cast<RangeAttribute>().FirstOrDefault();
            if (range != null)
            {
                nsettings.Min = range.Minimum.To<decimal?>();
                nsettings.Max = range.Maximum.To<decimal?>();
            }
        }
    }

      最后,在global.asax的Application_Start方法里,加入以下的代码:

        protected void Application_Start(object sender, EventArgs e)
        {
            //资源打包配置
            BundleHelper.Config();

            //默认是使用MEF导出服务的,改成使用aspx对应的类文件作为服务
            HttpConfiguration.Default.ServiceFactory = new AspPageServiceFactory();

            //配置http服务的路由,依子目录的级数而定
            HttpConfiguration.MapHttpRoute("{service}.ajx/{action}");
            HttpConfiguration.MapHttpRoute("{p1}/{service}.ajx/{action}");
            HttpConfiguration.MapHttpRoute("{p1}/{p2}/{service}.ajx/{action}");
            HttpConfiguration.MapHttpRoute("{p1}/{p2}/{p3}/{service}.ajx/{action}");

            SettingsBindManager.RegisterBinder("validatebox", new ValidateBoxSettingBinder());
            SettingsBindManager.RegisterBinder("numberbox", new NumberBoxSettingBinder());
        }

      为了达到效果,我们修改一下WebApplication1.Data项目下的EmployeeMetadata类(在Employee_Ex.cs文件内),为Mobile加上手机验证,为Name、Post、Sex和Birthday加上必填验证。

    public class EmployeeMetadata
    {
        
        /// <summary>
        /// 属性 Id 的验证特性。
        /// </summary>
        
        [Required]
        [StringLength(36)]
        public object Id { get; set; }

        /// <summary>
        /// 属性 DeptId 的验证特性。
        /// </summary>
        
        [Required]
        [StringLength(36)]
        public object DeptId { get; set; }

        /// <summary>
        /// 属性 No 的验证特性。
        /// </summary>
        
        [StringLength(20)]
        public object No { get; set; }

        /// <summary>
        /// 属性 Sex 的验证特性。
        /// </summary>
        
[Required] public object Sex { get; set; } /// <summary> /// 属性 Name 的验证特性。 /// </summary> [Required] [StringLength(20)] public object Name { get; set; } /// <summary> /// 属性 Birthday 的验证特性。 /// </summary> [Required] public object Birthday { get; set; } /// <summary> /// 属性 Post 的验证特性。 /// </summary> [Required] public object Post { get; set; } /// <summary> /// 属性 Mobile 的验证特性。 /// </summary> [Fireasy.Data.Validation.Mobile] [StringLength(20)] public object Mobile { get; set; } /// <summary> /// 属性 Address 的验证特性。 /// </summary> [StringLength(100)] public object Address { get; set; } /// <summary> /// 属性 Description 的验证特性。 /// </summary> [StringLength(500)] public object Description { get; set; } /// <summary> /// 属性 State 的验证特性。 /// </summary> public object State { get; set; } /// <summary> /// 属性 DelFlag 的验证特性。 /// </summary> public object DelFlag { get; set; } /// <summary> /// 属性 Photo 的验证特性。 /// </summary> [StringLength(200)] public object Photo { get; set; } }

      好了,我们现在来看看EmployeeEdit.aspx有表单有没有加上数据验证:

 

 

      二、数据列表的排序

      datagrid的columns中,我们默认生成了sortable属性,但是后台代码中并没有使用排序。其实代码是生成了的,只需将注释行Order(sorting)取消就要以了。

        /// <summary>
        /// 根据查询条件获取员工。
        /// </summary>
        /// <param name="deptNo">部门编码</param>
        /// <param name="startTime">开始日期</param>
        /// <param name="endTime">结束时间。</param>
        /// <param name="post">岗位类别。</param>
        /// <param name="keyword">关键字</param>
        /// <returns></returns>
        [ExceptionBehavior(true)]
        public object GetEmployees(string deptNo, DateTime? startTime, DateTime? endTime, PostKinds? post, string keyword)
        {
            var pager = EasyUIHelper.GetDataPager();
            var sorting = EasyUIHelper.GetSorting();
            using (var context = new DbContext())
            {
                var list = context.Employees
                    .Segment(pager)
                    .OrderBy(sorting)
                    .AssertWhere(!string.IsNullOrEmpty(deptNo), s => s.Dept.No.StartsWith(deptNo))
                    .AssertWhere(startTime != null, s => s.Birthday >= startTime.Value.StartOfDay())
                    .AssertWhere(endTime != null, s => s.Birthday <= endTime.Value.EndOfDay())
                    .AssertWhere(post != null, s => s.Post == post)
                    .AssertWhere(!string.IsNullOrEmpty(keyword), s => s.Name.Contains(keyword))
                    .Select(s => new
                        {
                            s.Id,
                            s.No,
                            s.Name,
                            Sex = ((Sex)s.Sex).GetDescription(),
                            Post = s.Post.GetDescription(),
                            s.Birthday,
                            s.Mobile,
                            s.Address,
                            s.Description
                        })
                    .ToList();
                return EasyUIHelper.Transfer(pager, list);
            }
        }

      但有一种情况,即没有单击列头的情况下,默认使用某一属性排序,比如按编码降序排列,这时,Order方法可以这样写:

        /// <summary>
        /// 根据查询条件获取员工。
        /// </summary>
        /// <param name="deptNo">部门编码。</param>
        /// <param name="startTime">开始日期。</param>
        /// <param name="endTime">结束时间。</param>
        /// <param name="post">岗位类别。</param>
        /// <param name="keyword">关键字</param>
        /// <returns></returns>
        [ExceptionBehavior(true)]
        public object GetEmployees(string deptNo, DateTime? startTime, DateTime? endTime, PostKinds? post, string keyword)
        {
            var pager = EasyUIHelper.GetDataPager();
            var sorting = EasyUIHelper.GetSorting();
            using (var context = new DbContext())
            {
                var list = context.Employees
                    .Segment(pager)
                    .OrderBy(sorting, u => u.OrderByDescending(t => t.No))
                    .AssertWhere(!string.IsNullOrEmpty(deptNo), s => s.Dept.No.StartsWith(deptNo))
                    .AssertWhere(startTime != null, s => s.Birthday >= startTime.Value.StartOfDay())
                    .AssertWhere(endTime != null, s => s.Birthday <= endTime.Value.EndOfDay())
                    .AssertWhere(post != null, s => s.Post == post)
                    .AssertWhere(!string.IsNullOrEmpty(keyword), s => s.Name.Contains(keyword))
                    .Select(s => new
                        {
                            s.Id,
                            s.No,
                            s.Name,
                            Sex = ((Sex)s.Sex).GetDescription(),
                            Post = s.Post.GetDescription(),
                            s.Birthday,
                            s.Mobile,
                            s.Address,
                            s.Description
                        })
                    .ToList();
                return EasyUIHelper.Transfer(pager, list);
            }
        }

 

      三、图片上传

      员工表设计了一个照片的字段,但是之前我们并没有用到它,现在我们就把照片上传给加上。

      首先,要引入上传所需的js,只需要在 BundleHelper.Render 后面再加上 upload 就可以了。

    <%= BundleHelper.Render("base", "upload") %>

    接下来修改一下表单的table,加一个图片和上传图片的链接:

        <table class="form-body">
            <tr>
                <td class="addon">部门</td>
                <td><%= Html.ComboBox(s => s.DeptId).MarkDelayedSet().MarkNoClear()%></td>
                <td rowspan="4" style="text-align:center">
                    <img id="img" src="../Images/nopic1.png" style="width: 161px; height: 110px" /><br />
                    <a target="#img" class="uploader">上传图片</a>
                </td>
            </tr>
            <tr>
                <td class="addon">编号</td>
                <td><%= Html.TextBox(s => s.No) %></td>
            </tr>
            <tr>
                <td class="addon">性别</td>
                <td><%= Html.ComboBox(s => s.Sex, typeof(WebApplication.Data.Model.Sex), new ComboBoxSettings { PanelHeight = 0 }).MarkNoClear() %></td>
            </tr>
            <tr>
                <td class="addon">姓名</td>
                <td><%= Html.TextBox(s => s.Name) %></td>
            </tr>
            <tr>
                <td class="addon">出生日期</td>
                <td><%= Html.DateBox(s => s.Birthday) %></td>
            </tr>
            <tr>
                <td class="addon">职务</td>
                <td><%= Html.ComboBox(s => s.Post, typeof(WebApplication.Data.Model.PostKinds), new ComboBoxSettings { PanelHeight = 0 }).MarkNoClear() %></td>
            </tr>
            <tr>
                <td class="addon">手机号码</td>
                <td><%= Html.TextBox(s => s.Mobile) %></td>
            </tr>
            <tr>
                <td class="addon">家庭住址</td>
                <td><%= Html.TextBox(s => s.Address) %></td>
            </tr>
            <tr>
                <td class="addon">个人说明</td>
                <td colspan="3"><%= Html.TextMultiBox(s => s.Description) %></td>
            </tr>
            <tr>
                <td class="addon">可用</td>
                <td><%= Html.CheckBox(s => s.State, true) %></td>
            </tr>
        </table>

      增加一个initUploader函数,用于添加“上传图片”的事件初始化,并在页面加载完成后调用initUploader函数:

        $(function () {
            loadInfo();
            initUploader();
        });

        //初始化上传插件
        function initUploader() {
            $('.uploader').upload({
                extFilter: 'png;jpg;jpeg;gif',
                action: 'EmployeeEdit.ajx/UploadPhoto?id=' + id,
                useHttpModule: false,
                onFileExtError: function () {
                    common.alert('只允许上传png、jpg、jpeg、gif类型的文件。')
                },
                onComplete: function (result, index, ele) {
                    $(ele.attr('target')).attr('src', '../' + result.fileName);
                    $(ele.attr('target')).attr('file', result.fileName);
                    if (id != '') {
                        var data = { id: id, url: encodeURI(result.fileName) };
                        $.post('EmployeeEdit.ajx/UpdatePhoto', data);
                    }
                }
            });
        }

      upload是一个jquery插件,可以为.uploader标签添加上传文件的事件。上传的处理请求是UploadPhoto方法,上传完后,更新员工的照片,即不需要点击保存按钮,也能生效。在EmployeeEdit.aspx.cs里增加UploadPhoto方法:

        /// <summary>
        /// 上传照片。
        /// </summary>
        /// <returns></returns>
        public object UploadPhoto()
        {
            ServiceContext.Current.ResultWriter = new FileUploadResultWriter();
            var request = HttpContext.Current.Request;
            if (request.Files.Count == 0)
            {
                return null;
            }

            var file = request.Files[0];
            var virtualPath = "upfiles\\photos";
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, virtualPath);
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            var fileId = Guid.NewGuid().ToString();
            var fileExt = file.FileName.Substring(file.FileName.LastIndexOf("."));

            var fileName = Path.Combine(path, fileId + fileExt);
            var virtualFile = Path.Combine(virtualPath, fileId + fileExt).Replace("\\", "/");
            file.SaveAs(fileName);

            return Result.Success("上传成功。", new { fileId, fileName = virtualFile });
        }

      DefaultResultWriter用于改变content-type,因为默认是使用application/json的,但是此时它会提示下载json,因此把content-type改成text/json即可。

    /// <summary>
    /// 针对文件上传的结果写入器。
    /// </summary>
    public class FileUploadResultWriter : DefaultResultWriter
    {
        protected override void WriteJson(ServiceContext serviceContext, HttpResponseBase response, object value)
        {
            response.ContentType = "text/json";
            response.Write(JsonSerialize(serviceContext, value));
        }
    }

      再增加一个UpdatePhoto方法,只用更新实体的Photo属性就可以了:

        /// <summary>
        /// 更新照片路径。
        /// </summary>
        /// <param name="id"></param>
        /// <param name="url"></param>
        public void UpdatePhoto(string id, string url)
        {
            using (var context = new DbContext())
            {
                context.Employees.Update(new Employee { Photo = url }, s => s.Id == id);
            }
        }

      最后,在EmployeeEdit.aspx中修改loadInfo函数的saveInfo函数如下:

        //加载信息
        function loadInfo() {
            if (id != '') {
                $.getJSON('EmployeeEdit.ajx/GetEmployee?id=' + id, function (data) {
                    common.processResult(data, function () {
                        $('#form1').form('load', data);
                        deptId = data.DeptId;
                        loadDepts();

                        if (data.Photo) {
                            $('#img').attr('file', data.Photo);
                            $('#img').attr('src', data.Photo);
                        }

                    });
                });

                $('#btnSaveAndNew').remove();
            }
            else {
                loadDepts();
            }
        }

        //保存信息
        function saveInfo(isNew) {
            if (!$('#form1').form('validate')) {
                return;
            }

            var postData = new Object();

            //将表单填充的内容序列化为json
            var data = $('#form1').form('save');
            data.DeptId = $('#cboDeptId').combotree('getValue');
            data.Photo = $('#img').attr('file');
            postData["info"] = JSON.stringify(data);

            common.showProcess();
            $.post('EmployeeEdit.ajx/SaveEmployee?id=' + id, postData, function (result) {
                common.processResult(result, function () {
                    if (isNew) {
                        $('#form1').form('clear');
                    }

                    id = isNew ? '' : result.data;
                    common.setReturnValue(true);
                });
            });
        }

      照片上传至此结束。

 

 

      非常感谢你的支持,在此附上示例的源代码:

      ★★★源代码下载★★★

发表评论
用户名: 匿名