排除不再使用的文件
大石头 编写于 2020-02-05 12:00:34
NewLife.Cube
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using NewLife.Web;
using XCode;
using XCode.Membership;
using NewLife.Reflection;
using NewLife.Log;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Net.Http;
using NewLife.Serialization;
using NewLife.Http;
using NewLife.Remoting;
#if __CORE__
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Net.Http.Headers;
using NewLife.Cube.Extensions;
#else
using System.Web.Mvc;
#endif

namespace NewLife.Cube
{
    /// <summary>实体控制器基类</summary>
    /// <typeparam name="TEntity"></typeparam>
    //[EntityAuthorize]
    public class EntityController<TEntity> : ReadOnlyEntityController<TEntity> where TEntity : Entity<TEntity>, new()
    {
        #region 属性
        private String CacheKey => $"CubeView_{typeof(TEntity).FullName}";
        #endregion

        #region 构造
        #endregion

        #region 默认Action
        /// <summary>删除</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Delete)]
        [DisplayName("删除{type}")]
        public virtual ActionResult Delete(String id)
        {
#if __CORE__
            var url = Request.Headers["Referer"].FirstOrDefault() + "";
#else
            var url = Request.UrlReferrer + "";
#endif

            var entity = FindData(id);
            Valid(entity, DataObjectMethodType.Delete, true);

            OnDelete(entity);

            if (Request.IsAjaxRequest())
                return JsonRefresh("删除成功!");
            else if (!url.IsNullOrEmpty())
                return Redirect(url);
            else
                return RedirectToAction("Index");
        }

        /// <summary>表单,添加/修改</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Insert)]
        [DisplayName("添加{type}")]
        public virtual ActionResult Add()
        {
            var entity = Factory.Create() as TEntity;

#if __CORE__
            // 填充QueryString参数
            var qs = Request.Query;
            foreach (var item in Entity<TEntity>.Meta.Fields)
            {
                var v = qs[item.Name];
                if (v.Count > 0) entity[item.Name] = v[0];
            }
#else
            // 填充QueryString参数
            var qs = Request.QueryString;
            foreach (var item in Entity<TEntity>.Meta.Fields)
            {
                var v = qs[item.Name];
                if (!v.IsNullOrEmpty()) entity[item.Name] = v;
            }
#endif

            // 验证数据权限
            Valid(entity, DataObjectMethodType.Insert, false);

            // 记下添加前的来源页,待会添加成功以后跳转
            //Session["Cube_Add_Referrer"] = Request.UrlReferrer.ToString();
#if __CORE__
            var url = Request.Headers["Referer"].FirstOrDefault() + "";
#else
            var url = Request.UrlReferrer + "";
#endif
            Session["Cube_Add_Referrer"] = url;

            return FormView(entity);
        }

        /// <summary>保存</summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Insert)]
        [HttpPost]
#if __CORE__
        [ValidateAntiForgeryToken]
#else
        [ValidateInput(false)]
#endif
        public virtual ActionResult Add(TEntity entity)
        {
            // 检测避免乱用Add/id
            if (Factory.Unique.IsIdentity && entity[Factory.Unique.Name].ToInt() != 0) throw new Exception("我们约定添加数据时路由id部分默认没有数据,以免模型绑定器错误识别!");

            if (!Valid(entity, DataObjectMethodType.Insert, true))
            {
                ViewBag.StatusMessage = "验证失败!";
                return FormView(entity);
            }

            var rs = false;
            var err = "";
            try
            {
                OnInsert(entity);
                rs = true;
            }
            catch (ArgumentException aex)
            {
                err = aex.Message;
                ModelState.AddModelError(aex.ParamName, aex.Message);
            }
            catch (Exception ex)
            {
                err = ex.Message;
                ModelState.AddModelError("", ex.Message);
            }

            if (!rs)
            {
                ViewBag.StatusMessage = "添加失败!" + err;
                // 添加失败,ID清零,否则会显示保存按钮
                entity[Entity<TEntity>.Meta.Unique.Name] = 0;
                return FormView(entity);
            }

            ViewBag.StatusMessage = "添加成功!";

            var url = Session["Cube_Add_Referrer"] as String;
            if (!url.IsNullOrEmpty())
                return Redirect(url);
            else
                // 新增完成跳到列表页,更新完成保持本页
                return RedirectToAction("Index");
        }

        /// <summary>表单,添加/修改</summary>
        /// <param name="id">主键。可能为空(表示添加),所以用字符串而不是整数</param>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Update)]
        [DisplayName("更新{type}")]
        public virtual ActionResult Edit(String id)
        {
            var entity = FindData(id);
            if (entity == null || (entity as IEntity).IsNullKey) throw new XException("要编辑的数据[{0}]不存在!", id);

            // 验证数据权限
            Valid(entity, DataObjectMethodType.Update, false);

            // Json输出
            if (IsJsonRequest) return Json(0, null, entity);

            return FormView(entity);
        }

        /// <summary>保存</summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Update)]
        [HttpPost]
#if __CORE__
        [ValidateAntiForgeryToken]
#else
        [ValidateInput(false)]
#endif
        public virtual ActionResult Edit(TEntity entity)
        {
            if (!Valid(entity, DataObjectMethodType.Update, true))
            {
                ViewBag.StatusMessage = "验证失败!";
                return FormView(entity);
            }

            var rs = 0;
            var err = "";
            try
            {
                rs = OnUpdate(entity);
                if (rs <= 0) rs = 1;
            }
            catch (ArgumentException aex)
            {
                err = aex.Message;
                ModelState.AddModelError(aex.ParamName, aex.Message);
            }
            catch (Exception ex)
            {
                //err = ex.Message;
                //ModelState.AddModelError("", ex.Message);
#if __CORE__
                ModelState.AddModelError("", ex.Message);
#else
                ModelState.AddModelError("", ex);
#endif
            }

            ViewBag.RowsAffected = rs;
            if (rs <= 0)
            {
                ViewBag.StatusMessage = "保存失败!" + err;
                return FormView(entity);
            }
            else
            {
                ViewBag.StatusMessage = "保存成功!";
                // 更新完成保持本页
                return FormView(entity);
            }
        }
        #endregion

        #region 高级Action
        /// <summary>导入Xml</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Insert)]
        [DisplayName("导入")]
        [HttpPost]
        public virtual ActionResult ImportXml() => throw new NotImplementedException();

        /// <summary>导入Json</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Insert)]
        [DisplayName("导入")]
        [HttpPost]
        public virtual ActionResult ImportJson() => throw new NotImplementedException();
        #endregion

        #region 批量删除
        /// <summary>删除选中</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Delete)]
        [DisplayName("删除选中")]
        public virtual ActionResult DeleteSelect()
        {
            var count = 0;
            var keys = SelectKeys;
            if (keys != null && keys.Length > 0)
            {
                using (var tran = Entity<TEntity>.Meta.CreateTrans())
                {
                    var list = new List<IEntity>();
                    foreach (var item in keys)
                    {
                        var entity = Entity<TEntity>.FindByKey(item);
                        if (entity != null)
                        {
                            // 验证数据权限
                            if (Valid(entity, DataObjectMethodType.Delete, true)) list.Add(entity);

                            count++;
                        }
                    }
                    list.Delete();
                    tran.Commit();
                }
            }
            return JsonRefresh("共删除{0}行数据".F(count));
        }

        /// <summary>删除全部</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Delete)]
        [DisplayName("删除全部")]
        public virtual ActionResult DeleteAll()
        {
#if __CORE__
            var url = Request.Headers["Referer"].FirstOrDefault() + "";
#else
            var url = Request.UrlReferrer + "";
#endif

            var count = 0;
            var p = Session[CacheKey] as Pager;
            p = new Pager(p);
            if (p != null)
            {
                p.PageIndex = 1;
                p.PageSize = 100_000;
                // 不要查记录数
                p.RetrieveTotalCount = false;

                var list = SearchData(p).ToList();
                count += list.Count;
                //list.Delete();
                using (var tran = Entity<TEntity>.Meta.CreateTrans())
                {
                    var list2 = new List<IEntity>();
                    foreach (var entity in list)
                    {
                        // 验证数据权限
                        if (Valid(entity, DataObjectMethodType.Delete, true)) list2.Add(entity);
                    }
                    list2.Delete();
                    tran.Commit();
                }
            }

            if (Request.IsAjaxRequest())
                return JsonRefresh("共删除{0}行数据".F(count));
            else if (!url.IsNullOrEmpty())
                return Redirect(url);
            else
                return RedirectToAction("Index");
        }

        /// <summary>清空全表数据</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Delete)]
        [DisplayName("清空")]
        public virtual ActionResult Clear()
        {
#if __CORE__
            var url = Request.Headers["Referer"].FirstOrDefault() + "";
#else
            var url = Request.UrlReferrer + "";
#endif

            var p = Session[CacheKey] as Pager;
            p = new Pager(p);
            if (p != null && p.Params.Count > 0) return Json(500, "当前带有查询参数,为免误解,禁止全表清空!");

            var count = Entity<TEntity>.Meta.Session.Truncate();

            if (Request.IsAjaxRequest())
                return JsonRefresh("共删除{0}行数据".F(count));
            else if (!url.IsNullOrEmpty())
                return Redirect(url);
            else
                return RedirectToAction("Index");
        }
        #endregion

        #region 实体操作重载
        /// <summary>添加实体对象</summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected virtual Int32 OnInsert(TEntity entity) => entity.Insert();

        /// <summary>更新实体对象</summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected virtual Int32 OnUpdate(TEntity entity) => entity.Update();

        /// <summary>删除实体对象</summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected virtual Int32 OnDelete(TEntity entity) => entity.Delete();
        #endregion

        #region 同步数据
        /// <summary>同步数据</summary>
        /// <returns></returns>
        [EntityAuthorize(PermissionFlags.Insert)]
        [DisplayName("同步{type}")]
        public async Task<ActionResult> Sync()
        {
            //if (id.IsNullOrEmpty()) return RedirectToAction(nameof(Index));

            // 读取系统配置
            var ps = Parameter.FindAllByUserID(ManageProvider.User.ID); // UserID=0 && Category=Sync
            ps = ps.Where(e => e.Category == "Sync").ToList();
            var server = ps.FirstOrDefault(e => e.Name == "Server")?.Value;
            var token = ps.FirstOrDefault(e => e.Name == "Token")?.Value;
            var models = ps.FirstOrDefault(e => e.Name == "Models")?.Value;

            if (server.IsNullOrEmpty()) throw new ArgumentNullException("未配置 Sync:Server");
            if (token.IsNullOrEmpty()) throw new ArgumentNullException("未配置 Sync:Token");
            if (models.IsNullOrEmpty()) throw new ArgumentNullException("未配置 Sync:Models");

            var mds = models.Split(",");

            //// 创建实体工厂
            //var etype = mds.FirstOrDefault(e => e.Replace(".", "_") == id);
            //var fact = etype.GetTypeEx()?.AsFactory();
            //if (fact == null) throw new ArgumentNullException(nameof(id), "未找到模型 " + id);

            // 找到控制器,以识别动作地址
#if __CORE__
            var act = ControllerContext.ActionDescriptor;
            var action = act.ControllerName;
#else
            var ctrl = RouteData.Values["controller"];
            var action = ctrl;
            if (RouteData.Values.TryGetValue("Area", out var area)) action = $"{area}/{ctrl}";
#endif
            if (!mds.Contains(action)) throw new InvalidOperationException($"[{action}]未配置为允许同步 Sync:Models");

            // 创建客户端,准备发起请求
            var url = server.EnsureEnd("/") + $"{action}/Json/{token}?PageSize=100000";

            var http = new HttpClient();
            http.BaseAddress = new Uri(url);

            var sw = Stopwatch.StartNew();

            var list = await http.InvokeAsync<TEntity[]>(HttpMethod.Get, null);

            sw.Stop();

            var fact = Factory;
            XTrace.WriteLine("[{0}]共同步数据[{1:n0}]行,耗时{2:n0}ms,数据源:{3}", fact.EntityType.FullName, list.Length, sw.ElapsedMilliseconds, url);

            var arrType = fact.EntityType.MakeArrayType();
            if (list.Length > 0)
            {
                XTrace.WriteLine("[{0}]准备覆盖写入[{1}]行数据", fact.EntityType.FullName, list.Length);
                using (var tran = fact.CreateTrans())
                {
                    // 清空
                    try
                    {
                        fact.Session.Truncate();
                    }
                    catch (Exception ex) { XTrace.WriteException(ex); }

                    // 插入
                    //ms.All(e => { e.AllChilds = new List<Menu>(); return true; });
                    fact.AllowInsertIdentity = true;
                    //ms.Insert();
                    //var empty = typeof(List<>).MakeGenericType(fact.EntityType).CreateInstance();
                    foreach (IEntity entity in list)
                    {
                        if (entity is IEntityTree tree) tree.AllChilds.Clear();

                        entity.Insert();
                    }
                    fact.AllowInsertIdentity = false;

                    tran.Commit();
                }
            }

            return Index();
        }
        #endregion
    }
}