diff --git a/NewLife.Cube/Common/EntityController.cs b/NewLife.Cube/Common/EntityController.cs
index 2a7196a4..032a61b0 100644
--- a/NewLife.Cube/Common/EntityController.cs
+++ b/NewLife.Cube/Common/EntityController.cs
@@ -5,29 +5,17 @@
using NewLife.Data;
using NewLife.Log;
using NewLife.Reflection;
+using NewLife.Remoting;
using XCode;
using XCode.Membership;
namespace NewLife.Cube;
-/// 实体控制器基类
-///
-public class EntityController : EntityController where TEntity : Entity, new() { }
-
/// 实体控制器基类
/// 实体类型
/// 数据模型,用于接口数据传输
-public class EntityController : ReadOnlyEntityController where TEntity : Entity, new()
+public partial class EntityController : ReadOnlyEntityController where TEntity : Entity, new()
{
- #region 属性
- private String CacheKey => $"CubeView_{typeof(TEntity).FullName}";
- #endregion
-
- #region 构造
- /// 实例化
- public EntityController() => PageSetting.IsReadOnly = false;
- #endregion
-
#region 默认Action
/// 删除数据
///
@@ -37,30 +25,22 @@ namespace NewLife.Cube;
[HttpDelete("/[area]/[controller]")]
public virtual ApiResponse Delete([Required] String id)
{
+ var act = "删除";
var entity = FindData(id);
- var rs = false;
- var err = "";
try
{
- if (Valid(entity, DataObjectMethodType.Delete, true))
- {
- OnDelete(entity);
-
- rs = true;
- }
- else
- err = "验证失败";
+ act = ProcessDelete(entity);
+
+ return new ApiResponse(0, $"{act}成功!", entity);
}
catch (Exception ex)
{
- err = ex.GetTrue().Message;
+ var code = ex is ApiException ae ? ae.Code : 500;
+ var err = ex.GetTrue().Message;
WriteLog("Delete", false, err);
- }
- if (rs)
- return new ApiResponse(0, "删除成功!", entity);
- else
- return new ApiResponse(500, "删除失败!" + err, entity);
+ return new ApiResponse(code, $"{act}失败!" + err, entity);
+ }
}
/// 添加数据
@@ -72,15 +52,14 @@ public virtual ApiResponse Delete([Required] String id)
public virtual async Task> Insert(TModel model)
{
// 实例化实体对象,然后拷贝
- if (model is not TEntity entity)
- {
- entity = Factory.Create(false) as TEntity;
+ if (model is TEntity entity) return await Insert(entity);
- if (model is IModel src)
- entity.CopyFrom(src, true);
- else
- entity.Copy(model);
- }
+ entity = Factory.Create(false) as TEntity;
+
+ if (model is IModel src)
+ entity.CopyFrom(src, true);
+ else
+ entity.Copy(model);
return await Insert(entity);
}
@@ -95,49 +74,35 @@ public virtual async Task> Insert(TEntity entity)
if (Factory.Unique.IsIdentity && entity[Factory.Unique.Name].ToInt() != 0)
throw new Exception("我们约定添加数据时路由id部分默认没有数据,以免模型绑定器错误识别!");
- var rs = false;
- var err = "";
try
{
- if (Valid(entity, DataObjectMethodType.Insert, true))
- {
- //SaveFiles(entity);
+ if (!Valid(entity, DataObjectMethodType.Insert, true))
+ throw new Exception("验证失败");
- OnInsert(entity);
+ OnInsert(entity);
- // 先插入再保存附件,主要是为了在附件表关联业务对象主键
- var fs = await SaveFiles(entity);
- if (fs.Count > 0) OnUpdate(entity);
+ // 先插入再保存附件,主要是为了在附件表关联业务对象主键
+ var fs = await SaveFiles(entity);
+ if (fs.Count > 0) OnUpdate(entity);
- if (LogOnChange) LogProvider.Provider.WriteLog("Insert", entity);
+ if (LogOnChange) LogProvider.Provider.WriteLog("Insert", entity);
- rs = true;
- }
- else
- err = "验证失败";
+ return new ApiResponse(0, "添加成功!", entity);
}
catch (Exception ex)
{
- err = ex.Message;
- ModelState.AddModelError((ex as ArgumentException)?.ParamName ?? "", ex.Message);
- }
+ var code = ex is ApiException ae ? ae.Code : 500;
+ var msg = ex.Message;
- var msg = "";
- if (!rs)
- {
- WriteLog("Add", false, err);
+ WriteLog("Add", false, msg);
- msg = SysConfig.Develop ? ("添加失败!" + err) : "添加失败!";
+ msg = SysConfig.Develop ? ("添加失败!" + msg) : "添加失败!";
// 添加失败,ID清零,否则会显示保存按钮
- entity[Entity.Meta.Unique.Name] = 0;
+ entity[Factory.Unique.Name] = 0;
- return new ApiResponse(500, msg, null);
+ return new ApiResponse(code, msg, entity);
}
-
- msg = "添加成功!";
-
- return new ApiResponse(0, msg, entity);
}
/// 更新数据
@@ -149,19 +114,18 @@ public virtual async Task> Insert(TEntity entity)
public virtual async Task> Update(TModel model)
{
// 实例化实体对象,然后拷贝
- if (model is not TEntity entity)
- {
- var uk = Factory.Unique;
- var key = model is IModel ext ? ext[uk.Name] : model.GetValue(uk.Name);
+ if (model is TEntity entity) return await Update(entity);
- // 先查出来,再拷贝。这里没有考虑脏数据的问题,有可能拷贝后并没有脏数据
- entity = FindData(key);
+ var uk = Factory.Unique;
+ var key = model is IModel ext ? ext[uk.Name] : model.GetValue(uk.Name);
- if (model is IModel src)
- entity.CopyFrom(src, true);
- else
- entity.Copy(model, false, uk.Name);
- }
+ // 先查出来,再拷贝。这里没有考虑脏数据的问题,有可能拷贝后并没有脏数据
+ entity = FindData(key);
+
+ if (model is IModel src)
+ entity.CopyFrom(src, true);
+ else
+ entity.Copy(model, false, uk.Name);
return await Update(entity);
}
@@ -172,352 +136,30 @@ public virtual async Task> Update(TModel model)
[NonAction]
public virtual async Task> Update(TEntity entity)
{
- var rs = false;
- var err = "";
try
{
- if (Valid(entity, DataObjectMethodType.Update, true))
- {
- await SaveFiles(entity);
+ if (!Valid(entity, DataObjectMethodType.Update, true))
+ throw new Exception("验证失败");
+
+ await SaveFiles(entity);
- OnUpdate(entity);
+ OnUpdate(entity);
- rs = true;
- }
- else
- err = "验证失败";
+ return new ApiResponse(0, "保存成功!", entity);
}
catch (Exception ex)
{
- err = ex.Message;
+ var code = ex is ApiException ae ? ae.Code : 500;
+ var err = ex.Message;
ModelState.AddModelError((ex as ArgumentException)?.ParamName ?? "", ex.Message);
- }
-
- Object id = null;
- if (Factory.Unique != null) id = entity[Factory.Unique.Name];
- var msg = "";
- if (!rs)
- {
WriteLog("Edit", false, err);
- msg = SysConfig.Develop ? ("保存失败!" + err) : "保存失败!";
-
- return new ApiResponse(500, msg, null);
- }
- else
- {
- msg = "保存成功!";
+ err = SysConfig.Develop ? ("保存失败!" + err) : "保存失败!";
- return new ApiResponse(0, msg, entity);
+ return new ApiResponse(code, err, null);
}
}
-
- /// 保存所有上传文件
- /// 实体对象
- /// 上传目录。为空时默认UploadPath配置
- ///
- protected virtual async Task> SaveFiles(TEntity entity, String uploadPath = null)
- {
- var rs = new List();
-
- if (!Request.HasFormContentType) return rs;
-
- var files = Request.Form.Files;
- var fields = Factory.Fields;
- foreach (var fi in fields)
- {
- var dc = fi.Field;
- if (dc.IsAttachment())
- {
- // 允许一次性上传多个文件到服务端
- var list = new List();
- foreach (var file in files)
- {
- if (file.Name.EqualIgnoreCase(fi.Name, fi.Name + "_attachment"))
- {
- var att = await SaveFile(entity, file, uploadPath, null);
- if (att != null)
- {
- var url = ViewHelper.GetAttachmentUrl(att);
- list.Add(url);
- rs.Add(url);
- }
- }
- }
-
- if (list.Count > 0) entity.SetItem(fi.Name, list.Join(";"));
- }
- }
-
- return rs;
- }
-
- /// 保存单个文件
- /// 实体对象
- /// 文件
- /// 上传目录,默认使用UploadPath配置
- /// 文件名,如若指定则忽略前面的目录
- ///
- protected virtual async Task SaveFile(TEntity entity, IFormFile file, String uploadPath, String fileName)
- {
- if (fileName.IsNullOrEmpty()) fileName = file.FileName;
-
- using var span = DefaultTracer.Instance?.NewSpan(nameof(SaveFile), fileName ?? file.FileName);
-
- var id = Factory.Unique != null ? entity[Factory.Unique] : null;
- var att = new Attachment
- {
- Category = typeof(TEntity).Name,
- Key = id + "",
- Title = entity + "",
- //FileName = fileName ?? file.FileName,
- ContentType = file.ContentType,
- Size = file.Length,
- Enable = true,
- UploadTime = DateTime.Now,
- };
-
- if (id != null)
- {
- var ss = GetControllerAction();
- att.Url = $"/{ss[0]}/{ss[1]}/Detail/{id}";
- }
-
- var rs = false;
- var msg = "";
- try
- {
- rs = await att.SaveFile(file.OpenReadStream(), uploadPath, fileName);
- }
- catch (Exception ex)
- {
- rs = false;
- msg = ex.Message;
- span?.SetError(ex, att);
-
- throw;
- }
- finally
- {
- // 写日志
- var type = entity.GetType();
- var log = LogProvider.Provider.CreateLog(type, "上传", rs, $"上传 {file.FileName} ,目录 {uploadPath} ,保存为 {att.FilePath} " + msg, 0, null, UserHost);
- log.LinkID = id.ToLong();
- log.SaveAsync();
- }
-
- return att;
- }
-
- ///// 批量启用
- ///// 主键集合
- ///// 操作原因
- /////
- //[EntityAuthorize(PermissionFlags.Update)]
- //[HttpPost]
- //public virtual ActionResult EnableSelect(String keys, String reason) => EnableOrDisableSelect(true, reason);
-
- ///// 批量禁用
- ///// 主键集合
- ///// 操作原因
- /////
- //[EntityAuthorize(PermissionFlags.Update)]
- //[HttpPost]
- //public virtual ActionResult DisableSelect(String keys, String reason) => EnableOrDisableSelect(false, reason);
-
- ///
- /// 批量启用或禁用
- ///
- /// 启用/禁用
- /// 操作原因
- ///
- protected virtual ActionResult EnableOrDisableSelect(Boolean isEnable, String reason)
- {
- var count = 0;
- var ids = GetRequest("keys").SplitAsInt();
- var fields = Factory.AllFields;
- if (ids.Length > 0 && fields.Any(f => f.Name.EqualIgnoreCase("enable")))
- {
- var log = LogProvider.Provider;
- foreach (var id in ids)
- {
- var entity = Factory.Find("ID", id);
- if (entity != null && entity["Enable"].ToBoolean() != isEnable)
- {
- entity.SetItem("Enable", isEnable);
-
- log.WriteLog("Update", entity);
- log.WriteLog(entity.GetType(), isEnable ? "Enable" : "Disable", true, reason);
-
- entity.Update();
-
- Interlocked.Increment(ref count);
- }
- }
- }
-
- return Json(0, $"共{(isEnable ? "启用" : "禁用")}[{count}]个");
- }
- #endregion
-
- #region 高级Action
- ///// 导入Excel
- ///// 当前采用前端解析的excel,表头第一行数据无效,从第二行开始处理
- /////
- //[EntityAuthorize(PermissionFlags.Insert)]
- //[DisplayName("导入Excel")]
- //[HttpPost]
- //public virtual ActionResult ImportExcel(String data)
- //{
- // if (String.IsNullOrWhiteSpace(data)) return Json(500, null, $"“{nameof(data)}”不能为 null 或空白。");
- // try
- // {
- // var fact = Factory;
- // var dal = fact.Session.Dal;
- // var type = Activator.CreateInstance(fact.EntityType);
- // var json = new JsonParser(data);
- // var dataList = json.Decode() as IList