從頭開始一步一步實現EF6+Autofac+MVC5+Bootstarp極簡的實現前後臺ajax表格展示及分頁實現

来源:http://www.cnblogs.com/yuzeyong/archive/2016/04/19/5406638.html
-Advertisement-
Play Games

本來是想試著做一個簡單OA項目玩玩的,真是不做不知道,一做嚇死人,原來以為很簡單的事情,但是做起來不是忘這就是忘那的,有的技術還得重新溫習。所以還是得記錄。免得哪天電腦掛了,就全沒有了。 開始是看了園子里何鎮汐的一系列文章,寫的太好了,只看了幾篇就有想寫代碼的衝動,很大一部分都是搬他的東西。但是我還 ...


本來是想試著做一個簡單OA項目玩玩的,真是不做不知道,一做嚇死人,原來以為很簡單的事情,但是做起來不是忘這就是忘那的,有的技術還得重新溫習。所以還是得記錄。免得哪天電腦掛了,就全沒有了。

開始是看了園子里何鎮汐的一系列文章,寫的太好了,只看了幾篇就有想寫代碼的衝動,很大一部分都是搬他的東西。但是我還是領誤不了DDD,所以先就著三層搞搞。

我搞了兩個解決方案,一個本著是想做框架,把有通用的封裝了,以後要用就引dll,由於太枯燥,另一個就是想做個玩具項目,兩邊輪流搞搞

先是dll部分的,當然很多都沒實現反正是自己的,以後再慢慢補,我這裡東西很少,所以沒用文件夾之類的,全部直接一個命名空間

先是autofac封裝類,只是簡單封裝了一下,做玩具夠用,跟上一篇博客一樣的,這裡不說了

using Autofac;
using System;

namespace MTF.Domain
{
    public class DependencyContainer
    {
        public static IContainer Container { get { return container; } }
        public static IContainer container;
        private DependencyContainer() { }
        public static void Initializer(Action<ContainerBuilder> action)
        {
            ContainerBuilder builder = new ContainerBuilder();
            if (action != null)
            {
                action(builder);
                container = builder.Build();
            }
        }
        private static void Error()
        {
            if (container == null)
                throw new InvalidOperationException("容器沒有初始化");
            else
                return;
        }
        public static TService Resolve<TService>()
        {
            return container.Resolve<TService>();
        }
    }
}
Dependency類代碼

 

BaseEntity 的設計是參考何兄的,大家可以去看他的文章,寫的太好了,這裡幾乎是搬的

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MTF.Domain
{
    public abstract class BaseEntity<TKey> : IEntity<TKey>
    {
        #region 初始化
        public TKey GId { get; private set; }
        protected BaseEntity(TKey id)
        {
            this.GId = id;
            validationRules = new List<IValidationRule>();
        } 
        #endregion

        #region 實體相等性比較
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (!(obj is BaseEntity<TKey>))
                return false;
            return this == (BaseEntity<TKey>)obj;
        }
        public override int GetHashCode()
        {
            return this.GId.GetHashCode();
        }
        public static bool operator ==(BaseEntity<TKey> entity1, BaseEntity<TKey> entity2)
        {
            if ((object)entity1 == null || (object)entity2 == null)
                return false;
            if (entity1.GId == null)
                return false;
            if (entity1.GId.Equals(default(TKey)))
                return false;
            return entity1.GId.Equals(entity2.GId);
        }
        public static bool operator !=(BaseEntity<TKey> entity1, BaseEntity<TKey> entity2)
        {
            return !(entity1 == entity2);
        }
        #endregion

        #region 驗證、驗證規則添加及驗證處理
        private List<IValidationRule> validationRules;//驗證結果集合
        private ICollection<ValidationResult> validationResults;//驗證規則集合
        private IValidationHandler validationHandler;//驗證處理器

        private void DefaultValidtae()
        {
            validationResults = new List<ValidationResult>();
            ValidationContext context = new ValidationContext(this, null, null);
            Validator.TryValidateObject(this, context, validationResults, true);//預設驗證實體特性註解

            if (validationRules.Count > 0)//如果有其它驗證規則
            {
                validationRules.ForEach(o =>
                {
                    if (o.Validate() == ValidationResult.Success || o.Validate() == null)
                        return;
                    //其它規則不通過時
                    validationResults.Add(o.Validate());//添加到驗證結果集合
                });
            }
        }
        /// <summary>
        /// 驗證標識
        /// </summary>
        public virtual bool IsValid { get
            {
                DefaultValidtae();
                return validationResults.Count <= 0;
            } }

        /// <summary>
        /// 添加驗證規則
        /// </summary>
        /// <param name="rule"></param>
        public void AddValidationRule(IValidationRule rule)
        {
            if (rule == null)
                return;
            validationRules.Add(rule);
        }
        /// <summary>
        ///  預設驗證當前實體方法
        /// </summary>
        public virtual void Validate()
        {

            if (IsValid)
                return;

            //驗證不通過時            
            try
            {
                validationHandler = DependencyContainer.Resolve<IValidationHandler>();//設置驗證處理器
            }
            catch
            {
                throw new InvalidOperationException("當前實體沒有通過驗證,但未設置驗證處理器,請檢查容器是否註入");
            }
            
            validationHandler.Handle(validationResults);//處理驗證結果
            
        } 
        #endregion

    }
}
View Code

Repository數據操作介面,這裡也是搬的,但有一點不一樣,考慮到排序我不想用Guid類型的,所以沒有約束Entity必須實現IBaseEntity介面或者聚合根,因為我用的三層,沒用聚合根,再者我在後面的Service層想用到分頁排序,看到後面應該就能理解的。但是我並不知道這樣對不對

IUnitOfWork只搞了一個方法,以後再搞

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace MTF.Domain
{
     public interface IRepository<TEntity,TKey> where TEntity:class
    {
        /// <summary>
        /// 添加單個實體
        /// </summary>
        /// <param name="entity"></param>
        void Add(TEntity entity);
        /// <summary>
        /// 添加實體集合
        /// </summary>
        /// <param name="entities"></param>
        void Add(IEnumerable<TEntity> entities);
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="entity"></param>
        void Update(TEntity entity);
        /// <summary>
        /// 根據Id刪除實體
        /// </summary>
        /// <param name="id"></param>
        void Remove(TKey id);
        /// <summary>
        /// 刪除實體
        /// </summary>
        /// <param name="entity"></param>
        void Remove(TEntity entity);
        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <returns></returns>
        List<TEntity> FindAll();
        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <returns></returns>
        IQueryable<TEntity> Find();
        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        //List<TEntity> Find(IEnumerable<TKey> ids);
        /// <summary>
        /// 根據Id查找實體
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity Find(params object[] id);
        /// <summary>
        /// 判斷實體是否存在
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        bool Exists(Expression<Func<TEntity, bool>> predicate);
        /// <summary>
        /// 索引器查找
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity this[TKey id] { get; }
        /// <summary>
        /// 保存
        /// </summary>
        void Save();
        /// <summary>
        /// 獲取工作單元
        /// </summary>
        /// <returns></returns>
        IUnitOfWork GetUnitOfWork();

        IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> where);
       
    }
}
View Code
using System;

namespace MTF.Domain
{
    public interface IUnitOfWork:IDisposable
    {
        void Commit();
    }
}
View Code
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MTF.Domain
{
    public interface IValidationHandler
    {
        void Handle(ICollection<ValidationResult> validationResults);
    }
}
View Code
using System.ComponentModel.DataAnnotations;

namespace MTF.Domain
{
    public interface IValidationRule
    {
        ValidationResult Validate();
    }
}
View Code

 

Domain現在只完成了這麼多,其它的介面還沒搞,還是以後再搞,懶的。

後面是EF部分了,引用Domain層

簡單的工作單元

using MTF.Domain;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;

namespace MTF.EFDatas
{
    public class EFUnitOfWork :DbContext, IUnitOfWork
    {
        protected EFUnitOfWork(string connection) : base(connection) { }
        public void Commit()
        {
            try
            {
                SaveChanges();
            }
            catch(DbUpdateConcurrencyException)
            {
                throw;
            }
            catch(DbEntityValidationException)
            {
                throw;
            }
        }
        
    }
}
EFUnitOfWork

簡單的EF數據操作,還是以後慢慢再搞

using MTF.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace MTF.EFDatas
{
    public class EFRepository<TEntity,TKey>: IRepository<TEntity,TKey> where TEntity:class
    {
        protected EFUnitOfWork unitOfWork { get; private set; }
        public EFRepository()
        {
            this.unitOfWork = DependencyContainer.Resolve<EFUnitOfWork>();
        }
        public void Add(TEntity entity)
        {
            unitOfWork.Set<TEntity>().Add(entity);
        }
        public void Add(IEnumerable<TEntity> entities)
        {
            unitOfWork.Set<TEntity>().AddRange(entities);
        }
        public void Update(TEntity entity)
        {
            unitOfWork.Entry(entity).State = System.Data.Entity.EntityState.Modified;

        }
        public void Remove(TKey id)
        {
            unitOfWork.Set<TEntity>().Remove(Find(id));
        }
        public void Remove(TEntity entity)
        {
            unitOfWork.Set<TEntity>().Remove(entity);
        }
        public List<TEntity> FindAll()
        {
            return Find().ToList();
        }
        public IQueryable<TEntity> Find()
        {
            return unitOfWork.Set<TEntity>();
        }
        //public List<TEntity> Find(IEnumerable<TKey> ids)
        //{
        //    if (ids == null)
        //        return null;
        //    return Find().Where(o => ids.Contains(o.GId)).ToList();
        //}
        public TEntity Find(params object[] id)
        {
            return unitOfWork.Set<TEntity>().Find(id);
        }
        public IQueryable<TEntity> Find(Expression<Func<TEntity,bool>> where)
        {
            return Find().Where(where);
        }
        public bool Exists(Expression<Func<TEntity, bool>> predicate)
        {
            return unitOfWork.Set<TEntity>().Any(predicate);
        }
        public TEntity this[TKey id] { get { return Find(id); } }
        public void Save()
        {
            unitOfWork.Commit();
        }
        public IUnitOfWork GetUnitOfWork()
        {
            return unitOfWork;
        }
        
    }
    
}
EFRepository

 

這裡我自己寫了一個分頁類EF專用的,因為不想一定要用ID分類,所以加了個泛型類型,專門用於排序用的,本來想著這個類是專門給service用的,不應該用public的,但是想著以後別的地方可能會用到,所以還是公共了

using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace MTF.EFDatas
{
    /// <summary>
    /// 分頁
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TOrder">要排序的類型</typeparam>
    public class Pager<TEntity,TOrder> where TEntity : class
    {
        public Pager(DbContext eow)
        {
            this.unitOfWork = eow;
            this.total = eow.Set<TEntity>().Count();
            Initia(1, 20);
        }
        private DbContext unitOfWork;
        public int PageIndex { get { return pageIndex; } }
        private int pageIndex;
        public int PageCount { get { return pageCount; } }
        private int pageCount;
        public int Total { get { return total; } }
        private int total;
        public int PageSize { get { return pageSize; } }
        private int pageSize;
        public int Skip { get { return skip; } }
        private int skip;
        public int Take { get { return take; } }
        private int take;

        private void Initia(int index, int size)
        {
            if (index < 1)
                index = 1;
            if (size >= total)
            {
                pageIndex = 1; pageCount = 1; pageSize = total; skip = 0; take = pageSize;
            }
            if (size < total)
            {
                int n = total % size; int x = total / size;
                if (n == 0)
                {
                    pageSize = size;
                    pageCount = x;

                    if (index > pageCount)
                    {
                        index = PageCount;
                        pageIndex = index;
                    }
                    pageIndex = index;

                    skip = (pageIndex - 1) * size;
                    take = size;
                }
                else
                {
                    pageCount = x + 1;
                    if (index > pageCount)
                    {
                        pageIndex = pageCount;
                    }

                    else
                    {
                        pageIndex = index;
                    }

                    if (pageIndex == pageCount)
                    {
                        pageIndex = PageCount;
                        pageSize = n;
                        skip = (pageIndex - 1) * size;
                        take = n;
                    }
                    else
                    {
                        pageSize = size;
                        skip = (pageIndex - 1) * size;
                        take = size;
                    }
                }
            }
        }
        public void SetPageSize(int size)
        {
            pageSize = size;
            Initia(PageIndex, PageSize);
        }

        public IQueryable<TEntity> GetPageList(Expression<Func<TEntity, TOrder>> order)
        {
            return unitOfWork.Set<TEntity>().OrderBy(order).Skip(Skip).Take(Take);
        }
        public IQueryable<TEntity> GetPageList(int pageIndex, Expression<Func<TEntity, TOrder>> order)
        {
            this.pageIndex = pageIndex;
            Initia(PageIndex, PageSize);
            return GetPageList(order);
        }

        public IQueryable<TEntity> GetPageList(int pageIndex, int pageSize, Expression<Func<TEntity, TOrder>> order)
        {
            this.pageIndex = pageIndex;
            this.pageSize = pageSize;
            Initia(PageIndex, PageSize);
            return GetPageList(order);
        }
    }
}
自己寫的Pager

 

直接給代碼先,都是很簡單,不知道合不合理,這裡用到了Pager類,當作屬性使用,客戶端得到Service就可以使用它的,它們共用一個工作單元

using MTF.Domain;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace MTF.EFDatas
{
    public class BaseService<TEntity,TKey,TOrderPage> where TEntity:class
    {
        private IRepository<TEntity, TKey> Repository;
        private Pager<TEntity, TOrderPage> pager;
        public Pager<TEntity,TOrderPage> Pager { get { return pager; } }
        public BaseService()
        {
            Repository = DependencyContainer.Resolve<IRepository<TEntity, TKey>>();
            pager = new Pager<TEntity, TOrderPage>(DependencyContainer.Resolve<EFUnitOfWork>());
        }
        
       
        public void Add(TEntity entity)
        {
            Repository.Add(entity);
        }
        public void Add(IEnumerable<TEntity> entities)
        {
            Repository.Add(entities);
        }
        public void Update(TEntity entity)
        {
            Repository.Update(entity);
        }
        public void Remove(TKey id)
        {
            Repository.Remove(id);
        }
        public void Remove(TEntity entity)
        {
            Repository.Remove(entity);
        }
        public List<TEntity> FindAll()
        {
            return Repository.FindAll();
        }
        public IQueryable<TEntity> Find()
        {
            return Repository.Find();
        }
        //public List<TEntity> Find(IEnumerable<TKey> ids)
        //{
        //    return Repository.Find(ids);
        //}
        public TEntity Find(params object[] id)
        {
            return Repository.Find(id);
        }
        public IQueryable<TEntity> Find(Expression<Func<TEntity,bool>> where)
        {
            return Find().Where(where);
        }
        public bool Exists(Expression<Func<TEntity, bool>> predicate)
        {
            return Repository.Exists(predicate);
        }
        public TEntity this[TKey id] { get { return Find(id); } }
        public void Save()
        {
            Repository.Save();
        }
    }
}
BaseService

由於沒有寫測試代碼,寫到這裡的時候 我都有點迫不及待想試試了,所以就先到此生成。另外寫一個MVC試試唄,搞個三層玩玩

DataModel層添加上面的DLL引用,我叫MTF指的是My Test Frame呵呵,不會英語,反正是搞的玩。

安裝EF和AUTOFAC包開搞,先搞個BaseEntity,由於我int 類型不會初始化的時候賦值,

但是又不想GUID來排序,所以我想的辦法是實體介面的時候,給的GId的屬性名,主鍵我還是用的int類型,Guid初始化的時候賦值,它同樣是唯一的,方便記憶體操作,int類型做自增的主鍵,在插入資料庫後才有值。

做了三個類,用戶,許可權和角色,還有三個中間類,以配多對多關係,本著學習的精神,我用的CodeFirst和F..Api(不會定這個單詞了,暈)方式配置映射

一樣的簡單玩玩的,可能還沒有註釋,直接上了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MTF.Domain;

namespace OADemo.DataModel.Domains
{
    public class EntityBase:BaseEntity<Guid>
    {
        protected EntityBase(Guid id) : base(id) { }//guid類型的屬性以後應該可以用到,它是在初始化的時候賦值的,記憶體中好找
        public EntityBase() : this(Guid.NewGuid())//int類型映射主鍵,插入資料庫時才有值,方便資料庫不方便記憶體操作
        {
            SubTime = DateTime.Now;//提交時間為當前時間
            IsDeleted = false;//這個好像有點多餘,預設應該就是false,但不確定,所以加上了
        }
        //子類共有的屬性
        public int Id { get; set; }
        public bool IsDeleted { get; set; }
        public DateTime SubTime { get; set; }
        public string Remark { get; set; }
    }
}
EntityBase
using System.Collections.Generic;

namespace OADemo.DataModel.Domains
{
    public class UserEntity:EntityBase
    {
        public ICollection<UserRole> UserRoles { get; set; } = new List<UserRole>();//導航屬性
        public ICollection<UserPermission> UserPermissions { get; set; } = new List<UserPermission>();//導航屬性
        public string Name { get; set; }
        public int Age { get; set; }
        public string Email { get; set; }
        public string RealName { get; set; }
    }
    public class RoleEntity:EntityBase
    {
        public ICollection<UserRole> UserRoles { get; set; } = new List<UserRole>();
        public ICollection<RolePermission> RolePermissions { get; set; } = new List<RolePermission>();
        public string Name { get; set; }
        public string Description { get; set; }
    }
    public class	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 設備管理員 Device Admin 獲取DevicePolicyManager對象,通過getSystemService(DEVICE_POLICY_MANAGER),設備策略管理器 調用DevicePolicyManager對象的lockNow()方法,鎖定,此時會報 安全異常 新建一個類MyA ...
  • 在整型信號量機制中,信號量被定義為一個整形變數。除初始化外,僅能通過兩個標準的原子操作Wait(S)和Signal(S)來訪問。其通常分別被稱為P、V操作。 描述如下: P操作:S=S-1;如果S小於0,則進程進入等待狀態,否則繼續執行。 V操作:S=S+1;如果S>=0,則喚醒等待隊列中的一個等待 ...
  • 首先在開始正文之前先介紹最簡單的獲取進程/線程句柄方法。那就是可以在創建進程/線程時獲取句柄。 創建進程/線程是獲取句柄。 //進程創建函數 BOOL CreateProcess( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURITY_... ...
  • 第一、檢查硬碟設備是否有數據盤 第二、數據硬碟分區 第三、ext3格式化分區 第四、掛載新分區 A - 新建目錄[任意創建] B - 掛載分區 第五、寫入fstab 設置開機自動掛載 第六、檢查是否掛載成功(df -h ) ...
  • bmp.c:8: warning: malformed '#pragma pack(push[, id], <n>)' - ignored bmp.c:33: warning: #pragma pack (pop) encountered without matching #pragma pack ...
  • 反射的定義:審查元數據並收集關於它的類型信息的能力。元數據(編譯以後的最基本數據單元)就是一大堆的表,當編譯程式集或者模塊時,編譯器會創建一個類定義表,一個欄位定義表,和一個方法定義表等。System.reflection命名空間包含的幾個類,允許你反射(解析)這些元數據表的代碼 System.Re ...
  • 在ASP.NET中,頁面間數據傳遞的方法有很多。下麵為大家總結一下,頁面間數據傳遞的方法。 Web頁面是無狀態的,伺服器對每一次請求都認為來自不同用戶,因此,變數的狀態在連續對同一頁面的多次請求之間或在頁面跳轉時不會被保留。在 用ASP.NET 設計開發一個Web系統時, 遇到一個重要的問題是如何保 ...
  • 前言 作為一名.NET程式員,很多時候都會被什麼拖控制項、跨平臺等字眼所鄙視過,但是在我的的內心還是沒有把自己看低過。因為說到底,平臺和語言只是我們吃飯的工具。很多時候公司的發展是取決於商業競爭的,微軟也不例外。在大環境下,我們終於看到了微軟給我們帶來的跨平臺的驚喜。儘管這隻是剛剛開始,但我相信在不久 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...