1. 程式人生 > >Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之驗證碼

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之驗證碼

驗證碼這東西,有人喜歡有人不喜歡。對於WebApi是否需要驗證碼,沒去研究過,只是原來的SimpleCMS有,就加上吧。

在WeiApi上使用驗證碼,關鍵的地方在於WeiApi是沒有狀態的,也就是說,不能使用Session來儲存驗證碼。因而,在WebApi上使用驗證碼。首先需要解決的是儲存的問題。剛開始先測試AbpSession了,但發現機制和習慣的不同,無法使用,那就只能儲存到資料庫了。儲存到資料庫最大的麻煩是如何判斷當前使用者對應的驗證碼是那個,也就是需要一個唯一值來尋找驗證碼,而且這個唯一值必須在客戶端重新整理圖片的時候一起返回到客戶端,以便提交時,將該值一併提交到伺服器。要將圖片和唯一值一起返回客戶端,也就是說不能以圖片方式返回,不然不好新增唯一值。沿著這個思路想到了將圖片轉換為BASE64程式碼再返回這方式,這樣,返回的就是字串,可以攜帶其他資訊返回了。後來,再想想,居然都已經轉換為字串了,何不直接將圖片字串做個MD5提交到伺服器,然後把這個MD5作為搜尋值,這樣也省了處理多個數值的問題。使用MD5作為唯一值,唯一的思慮是,能確保圖片都是唯一的麼?對於這個問題,筆者覺得,能同時出現相同的圖片,幾乎比中彩票還難,26個字母加上10個數字的6位數排列已經是上十億的可能,再加上字型、燥點和字型顏色等因素,真的中了,那你不是買彩票都對不起自己了。

思路明確後就可以開始工作了。先在Core專案建立VerifyCode的實體,程式碼如下:

    [Table("AppVerifyCodes")]
    public class VerifyCode :Entity<long>
    {
        public const int MaxCodeLength = 6;
        public const int MaxMd5KeyLength = 32;

        [Required]
        [MaxLength(MaxMd5KeyLength)]
        public  string
Md5Key { get; set; } [Required] [MaxLength(MaxCodeLength)] public string Code { get; set; } [Required] public DateTime Expired { get; set; } }

在實體中新增Expired屬性的作用是為驗證碼設定一個過期時間,以避免這個驗證碼比重複利用。在練習中,我將過期時間設定為了10分鐘,在實際使用時,可以設定為30秒或者更小,不行就讓使用者重新整理驗證碼就行。

建立實體後,將它新增到SimpleCmsWithAbpDbContext,然後就可執行Add-Migration

Update-Database命令在資料庫新增實體對應的表了。

有了實體後,就要新增服務,以便將圖片返回客戶端。一般情況下,通過繼承CrudAppServiceAsyncCrudAppService類就可以很簡單的實現一個實體的CRUD操作,在沒有特殊操作的情況下,基本不需要編寫任何程式碼就能實現實體的CRUD操作了。由於驗證碼不需要完整的CRUD操作,只需要一個返回圖片的操作,因而可以從IApplicationService介面、ApplicationService類或模版提供的SimpleCmsWithAbpAppServiceBase類等繼承。SimpleCmsWithAbpAppServiceBase類是在ApplicationService的基礎上添加了GetCurrentUserAsync方法用來返回當前使用者,添加了GetCurrentTenantAsync方法用來返回當前租戶。如果不需要這兩方法,可以直接從ApplicationService基礎。

瞭解瞭如何新增服務後,先在Application專案新增一個名為VerifyCodes的資料夾,並在該資料夾下建立一個名為Dto的資料夾。在Dto資料夾下, 先建立一個名為GetVerifyCodeOutput的類,程式碼如下:

    public class GetVerifyCodeOutput
    {
        public string Image { get; set; }
    }

GetVerifyCodeOutput類將作為驗證碼的Get服務的返回物件。

在VerifyCodes資料夾下,建立一個名為IVerifyCodeAppService的介面,程式碼如下:

    public interface IVerifyCodeAppService : IApplicationService
    {
        Task<GetVerifyCodeOutput> Get();
    }

還要建立一個名為VerifyCodeAppService的類,程式碼如下:

    public class VerifyCodeAppService:SimpleCmsWithAbpAppServiceBase,IVerifyCodeAppService
    {
        private readonly IRepository<VerifyCode, long> _repository;

        public VerifyCodeAppService(IRepository<VerifyCode, long> repository)
        {
            _repository = repository;
        }

        public async Task<GetVerifyCodeOutput> Get()
        {
            var v = new VerifyCodeCore();
            var code = v.CreateVerifyCode();                //取隨機碼
            v.Padding = 10;
            var bytes = v.CreateImage(code);
            var image = $"data:{MimeTypeNames.ImageJpeg};base64,{Convert.ToBase64String(bytes)}";
            var verifyCode = new VerifyCode()
            {
                Md5Key = GetMd5Key(image),
                Code = code,
                Expired = Clock.Now.AddMinutes(10)
            };
            await _repository.InsertAsync(verifyCode);
            var output = new GetVerifyCodeOutput()
            {
                Image = image
            };
            return output;
        }

        private static string GetMd5Key(string input)
        {
            var md5 = new MD5CryptoServiceProvider();
            var inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            var hashBytes = md5.ComputeHash(inputBytes);

            // Convert the byte array to hexadecimal string
            var sb = new StringBuilder();
            foreach (var t in hashBytes)
            {
                sb.Append(t.ToString("X2"));
            }
            return sb.ToString();
        }
    }

Get方法內,先呼叫VerifyCodeCoreCreateVerifyCode方法建立驗證碼,再呼叫CreateImage方法建立影象的二進位制程式碼,並將二進位制程式碼轉換為BASE64程式碼。接下來是建立一個VerifyCode實體並通過儲存的InsertAsync方法將實體新增到資料庫。在這裡呼叫了GetMd5Key方法將圖片字串轉換為了MD5字串。最後,建立GetVerifyCodeOutput的實體並返回。

在這裡要注意的是,由於在.net core 2中並不包含System.Drawing物件,不能處理Bitmap物件,在使用VerifyCodeCore類的時候會出錯,因而,需要在Application專案中新增System.Drawing.Common包,這個包目前還是預覽版狀態,需要在NuGet管理頁中將包括預發行版選上才能找到。

重新生成解決方案,就可在swagger頁的底部看到VerifyCode服務了,開啟訪問地址並單擊Try it out!按鈕就可看到以下的返回資料:

{
  "result": {
    "image": "data:image/jpeg;base64,此處省略圖片輸出"
  },
  "targetUrl": null,
  "success": true,
  "error": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

這說明返回驗證碼沒有問題了。下面要修改驗證碼的驗證問題了。切換到Web.Core專案,在Models資料夾下,開啟AuthenticateModel.cs檔案,並將程式碼修改為以下程式碼:

    public class AuthenticateModel : ICustomValidate
    {
        [Required]
        [StringLength(AbpUserBase.MaxEmailAddressLength)]
        public string UserNameOrEmailAddress { get; set; }

        [Required]
        [StringLength(AbpUserBase.MaxPlainPasswordLength)]
        public string Password { get; set; }

        [Required]
        [StringLength(6)]
        public string VerifyCode { get; set; }

        [Required]
        [StringLength(32)]
        public  string Key { get; set; }

        public bool RememberClient { get; set; }

        public void AddValidationErrors(CustomValidationContext context)
        {
            var verifyCodeRepository =  context.IocResolver.Resolve<IRepository<VerifyCode, long>>();
            var localizationManager = context.IocResolver.Resolve<ILocalizationManager>();
            var record = verifyCodeRepository.FirstOrDefault(m =>m.Md5Key == Key.ToUpper());
            if (record == null || (record.Code.ToUpper() != VerifyCode.ToUpper() || record.Expired < Clock.Now))
            {
                context.Results.Add(new ValidationResult(
                    localizationManager.GetString(SimpleCmsWithAbpConsts.LocalizationSourceName, "verifyCodeInvalid"),
                    new List<string>() {"VerifyCode"}));
            }
            else
            {
                verifyCodeRepository.Delete(record);
            }
        }
    }

AuthenticateModel類是登入時用來接收登入資料的模型類。在該類中,添加了VerifyCodeKey兩個屬性用來接收驗證碼和與驗證碼相關的搜尋值,並添加了自定義驗證的AddValidationErrors方法來驗證驗證碼。在AddValidationErrors內,先通過Resolve方法獲取到VerifyCode實體的儲存和本地化資源管理介面ILocalizationManager,再呼叫儲存的FirstOrDefault方法來獲取與驗證碼相關的實體,然後進行驗證。如果記錄不存在,或者記錄的驗證碼不對,或者已經超時,就返回驗證錯誤,否則刪除實體,並繼續執行後續的驗證的操作。

在實現這個的時候,經歷了一些波折,在剛開始的時候,筆者習慣使用Equals方法來驗證欄位與提交值是否相等,但得到的都是錯誤的結果,這就奇怪了。於是,筆者就檢視日誌到底是怎麼回事,但是日誌並沒有記錄查詢時的SQL語句,這就麻煩了。在沒有使用ABP框架時,要記錄實體查詢時的SQL語句很簡單,只要呼叫UseLoggerFactory方法添加工廠類就行了,但是經過搜尋,發現ABP框架使用的日誌包castle.windsor並沒有跟上時代的步伐,為這提供相應的支援,為此,ABP框架的人還去GitHub和castle.windsor的專案負責人進行了交流,最後也沒啥結果。沒辦法,只能自己來解決這個問題了。先在EntityFrameworkCore包新增Microsoft.Extensions.Logging.Log4Net.AspNetCore包,然後開啟SimpleCmsWithAbpDbContextConfigurer.cs檔案,並將程式碼修改為以下程式碼:

    public static class SimpleCmsWithAbpDbContextConfigurer
    {

        public static readonly LoggerFactory MyLoggerFactory
            = new LoggerFactory(new[]
            {
                new Log4NetProvider("log4net.config",new Func<object, Exception, string>((o, exception) =>exception.Message )) 
            });
        public static void Configure(DbContextOptionsBuilder<SimpleCmsWithAbpDbContext> builder, string connectionString)
        {
            //builder.UseSqlServer(connectionString);
            builder.UseLoggerFactory(MyLoggerFactory).UseMySql(connectionString);
        }

        public static void Configure(DbContextOptionsBuilder<SimpleCmsWithAbpDbContext> builder, DbConnection connection)
        {
            //builder.UseSqlServer(connection);
            builder.UseLoggerFactory(MyLoggerFactory).UseMySql(connection);
        }
    }

程式碼主要添加了一個LoggerFactory例項,用於記錄實體的操作日誌。程式碼裡一定要將UseLoggerFactory方法放在UseMySql的前面,不然不起任何作用。好了,現在可以在日誌中記錄SQL 語句了。通過檢視日誌,發現使用Equals方法不能將查詢值傳遞給SQL語句,這就奇怪了,不知道是ABP問題還是Entity Framework Core的問題了。不管了,還成==就沒問題了。

使用帶有 module-zero的模版,本地化資訊可儲存在資料庫,也可儲存在XML檔案中。筆者是將資訊儲存在資料庫中,例如AddValidationErrors使用到的verifyCodeInvalid資訊,可在abplanguagetexts表中新增一條記錄,記錄的內容如下:
- Key:verifyCodeInvalid
- LanguageName:zh-CN
- Source:SimpleCmsWithAbp
- Value:驗證碼錯誤

這裡要注意的是CreationTime欄位的值不能為0,不然會出現錯誤,隨便添加個時間就行了。還有就是關於Source的值,如果要自定義源的話,需要將源新增到本地化管理中,不然會提示找不到源。為了簡便起見,使用SimpleCmsWithAbpConsts.LocalizationSourceName常數指定的源挺好,在本專案裡,LocalizationSourceName的值是SimpleCmsWithAbp,因而Source的值為SimpleCmsWithAbp

重新生成解決方案,驗證碼驗證功能就已經可用了。最後要修改的是客戶端。

由於預設的服務訪問介面都有字首api/services/app,為了能方便處理這種情況,需要先修改SimpleCMS.util.Url類,將get方法修改成以下程式碼:

    defaultPath: '/api/services/app',

    get: function(controller, action, notDefaultPath) {
        var me = this;
        if (!Ext.isString(controller) || Ext.isEmpty(controller)) Ext.raise('非法的控制器名稱');
        if (!Ext.isString(action) && !Ext.isNumber(action)) Ext.raise('非法的操作名稱');
        return Ext.String.format(me.urlFormat, ROOTPATH + (notDefaultPath ? '' : me.defaultPath), controller, me.defaultActions[action] || me.actions[action] || action);
    },

方法主要添加了一個notDefaultPath引數,用來指定是否新增預設路徑,如果不設定該值,則新增,否則就不新增。

在客戶端需要一個MD5類用來將圖片的字串轉換為MD5字串,在Sencha官方論壇找到了這個類,具體地址為Ext.util.MD5 。類下載後,在app\util\資料夾下新增一個名為MD5.js的檔案,然後將下載的程式碼貼上到類裡,將類名修改為SimpleCMS.util.MD5 ,並在app.js中新增對它的引用,build一次就能用了。

使用WebApi,表單就不能直接提交了,需要將表單內的資料轉換為JSON格式提交,而要實現這個,只要在表單中將jsonSubmit設定為true就行了,但是每次都要設定就太麻煩了,通過重寫方式可一勞永逸的解決這個問題,但嘗試重寫Ext.form.Basic發現不起作用,重寫Ext.form.action.Submit才行。

資料是能以JSON提交,但發現WebApi在驗證錯誤的時候,返回的是400錯誤,而登入失敗返回的是500錯誤,而且,驗證錯誤的返回格式與Ext JS的預設格式也不同,這些都需要通過重寫Ext.form.action.Submit來實現,完成的後代碼如下:

Ext.define('Overrides.form.action.Submit', {
    override: "Ext.form.action.Submit",

    jsonSubmit: true,

    onFailure: function(response) {
        var me = this,
            form = me.form,
            formActive = form && !form.destroying && !form.destroyed,
            result;

        me.response = response;
        //this.failureType = Ext.form.action.Action.CONNECT_FAILURE;

        if (response.status === 400) {
            result = me.processResponse(response);
            if (result.error.validationErrors) {
                me.form.markInvalid(me.processValidationErrors(result.error.validationErrors));
                me.failureType = "validationErrors";
            }
        } else {
            me.failureType = Ext.form.Action.CONNECT_FAILURE;
        }


        if (formActive) {
            form.afterAction(me, false);
        }
    },

    processValidationErrors: function(errors) {
        var result = {},
            ln = errors.length,
            i = 0,
            error, j, jn, fields, field;
        for (i; i < ln; i++) {
            error = errors[i];
            fields = error.members;
            jn = fields.length;
            for (j = 0; j < jn; j++) {
                field = result[fields[j]];
                if (!field) field = result[fields[j]] = [];
                field.push(error['message']);
            }
        }
        return result;
    }


});

以上的程式碼參考了Sencha官方論壇的Aren’t Http Status Codes enough? 這個帖子,不過,帖子中重寫的是failure方法,不起左右,要重寫onFailure方法才行。

onFailure方法內,如果返回的狀態碼是400,則判斷是否存在error.validationErrors的資料,如果存在,是否是驗證錯誤,需要從error.validationErrors中,將資料提取出來,將資料轉換為Ext JS認識的錯誤格式。轉換過程主要是從返回的每個錯誤中的members中獲取欄位名稱,在新的物件中以欄位名稱作為屬性名稱,message的值作為錯誤資訊陣列中的一個值。

重寫類寫好以後,需要build一次以載入重寫類。完成build後,開啟登入檢視app\view\authentication\Login.js,將裡面的欄位的name都修改為與AuthenticateModel類中屬性對應的名稱。修改完name後,開啟app\view\authentication\AuthenticationController.js檔案,修改verifyCodeUrl屬性、onLoginButton方法和onRefrestVcode方法,具體程式碼如下:

    onLoginButton: function () {
        var me = this,
            view = me.getView(),
            f = view.getForm(),
            src = view.down('image').getSrc();
        if (f.isValid()) {
            f.submit({
                //jsonSubmit:true,
                params:{key: SimpleCMS.util.MD5(src)},
                url: URI.get('api/TokenAuth', 'Authenticate', true),
                waitMsg: I18N.LoginSubmitWaitMsg,
                waitTitle: I18N.LoginSubmitWaitTitle,
                success: function (form, action) {
                    window.location.reload();
                },
                failure: function(form,action){
                    this.onRefrestVcode();
                    FAILED.form(form,action);
                },
                scope: me
            });
        }
    },

    verifyCodeUrl: URI.get('VerifyCode', 'Get'),
    onRefrestVcode: function () {
        var me = this,
            view = me.getView(),
            img = view.down('image');
        Ext.Ajax.request({
            url: me.verifyCodeUrl,
            scope: me,
            success: function(response, opts) {
                var obj = Ext.decode(response.responseText),
                    view = this.getView();
                if(view && obj.success && obj.result && obj.result.image){
                    view.down('image').setSrc(obj.result.image);
                }
            },       
            failure: function(response, opts) {
                TOAST.toast('獲取驗證碼失敗', this.getView().el, 'bl' );
            }            
        })    
    },

在onLoginButton方法中,主要修改的地方是在提交前,先獲取Ext.Img元件的src屬性的值,呼叫SimpleCMS.util.MD5方法將圖片字串轉換為MD5字元,並作為Key值提交到伺服器。由於提交地址為/api/TokenAuth/Authenticate,不是預設的WebApi提交地址,因而需要在呼叫get方法時新增第3個引數。在failure的回撥中,只有出現錯誤,就重新整理一次驗證碼,不能再使用舊的驗證碼,因為舊的驗證碼已經刪除了。

onRefrestVcode方法中,主要修改的地方就是需要通過Ajax的方式來獲取驗證碼,而不能直接使用修改訪問地址的方式來重新整理驗證碼。在獲取到驗證碼後,將返回的字串值作為圖片的src值就行了。

由於登入失敗都是以500錯誤返回的,因而需要修改SimpleCMS.util.Failed以處理這種情況,具體修改程式碼如下:

    form: function(form, action) {
        if (action.failureType === 'validationErrors') return;
        if (action.response.status === 500) {
            var result = Ext.decode(action.response.responseText);
            if (result.error && result.error.message) {
                TOAST.toast(
                    result.error.message + (result.error.details ? result.error.details : ''),
                    form.owner.el,
                    'bl'
                );
            }
            return;
        }
        FAILED.ajax(action.response);
    }

程式碼先判斷failureType是否為驗證錯誤,如果是,說明已經處理過了,不用處理,直接返回。如果狀態碼為500,就判斷結果是否包含errorerror.message兩個資料,如果包含,說明有錯誤資訊,就在視窗上使用Ext.window.Toast來輸出資訊。如果是其他情況,呼叫ajax方法來處理錯誤資訊。

在最後,還需要開啟application.js檔案,在onAjaxBeforeRequest方法中,將options.jsonData = true;這句刪除,不然表單提交的時候不會提交任何資料。

至此,驗證碼功能已經實現了。

相關推薦

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS驗證

驗證碼這東西,有人喜歡有人不喜歡。對於WebApi是否需要驗證碼,沒去研究過,只是原來的SimpleCMS有,就加上吧。 在WeiApi上使用驗證碼,關鍵的地方在於WeiApi是沒有狀態的,也就是說,不能使用Session來儲存驗證碼。因而,在WebApi

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS配置IdentityServer

上一篇文章把專案建好了,現在要進行一些必要配置。由於IdentityServer4需要使用到3.2.5的包,而專案預設使用的是3.2.4的包,因而,我們需要先升級一下解決方案的包。在解決方案上單擊右鍵,在右鍵選單中選擇管理解決方案的NuGet包。在NuGet

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS文章管理

登入完成後,我們繼續來完成餘下的功能。本文要完成的是文章管理功能,主要包括後臺應用層服務以及客戶端儲存(Store)的資料訪問調整。 由於本文涉及的類很多,因而,只挑了一些比較有代表性的類來講解,其餘的,有興趣可以自行下載程式碼來研究,或者發私信、評論

ASP.NET Core 2.0 支付寶當面付支付

前言 自從微軟更換了CEO以後,微軟的戰略方向有了相當大的變化,不再是那麼封閉,開源了許多東西,擁抱開源社群,.NET實現跨平臺,收購xamarin並免費提供給開發者等等。我本人是很喜歡.net的,並希望.net core能夠崛起。我是從.net core 1.1的時候開始

ASP.net Core 2.0 EF (mysql) 遷移 正確姿勢

com update reat .com ttr 數據庫 pda creat mic 用於進行遷移的 Entity Framework Core NuGet 包 註意:必須通過編輯 .csproj 文件來安裝此包;不能使用 install-package 命令或程序包管理器

使用 ASP.NET Core Identity 的 IdentityServer4 授權服務器(二)

length 字段 dbm dconf logs 字段長度 database asp using 在 使用 ASP.NET Core Identity 的 IdentityServer4 授權服務器(1) 中,IdentityServer4 使用的是內存數據,不方便靈活,這

asp.net core 2.1 DBfirst MySQL 執行命令出錯

Scaffold-DbContext "Data Source=localhost;Initial Catalog=FriendSourceDB;User ID=root;Password=;" Pomelo.EntityFrameworkCore.MySql -OutputDir EFModel

ASP.NET Core 入門教程 2、使用ASP.NET Core MVC框架構建Web應用

一、前言 1、本文主要內容 使用dotnet cli建立基於解決方案(sln+csproj)的專案 使用Visual Studio Code開發基於解決方案(sln+csproj)的專案 Visual Studio Code Solution外掛( vscode-solution-explorer)基礎使用

ASP.NET CORE API Swagger+IdentityServer4授權驗證

簡介 本來不想寫這篇博文,但在網上找到的文章部落格都沒有完整配置資訊,所以這裡記錄下。 不瞭解IdentityServer4的可以看看我之前寫的入門博文 Swagger 官方演示地址 原始碼地址 配置IdentityServer4服務端 首先建立一個新的ASP.NET Core專案。 &nb

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [上篇]

微軟在千禧年推出 .NET戰略,並在兩年後推出第一個版本的.NET Framework和IDE(Visual Studio.NET 2002,後來改名為Visual Studio),如果你是一個資深的.NET程式設計師,相信傳統的.NET應用的開發方式已經深深地烙印在你的腦子裡面。.NET Core帶來了全新

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [中篇]

我們在《上篇》利用dotnet new命令建立了一個簡單的控制檯程式,接下來我們將它改造成一個ASP.NET Core應用。一個ASP.NET Core應用構建在ASP.NET Core框架之上,ASP.NET Core框架利用一個訊息處理管道完成對HTTP請求的監聽、接收、處理和最終的響應。ASP.NET

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [下篇]

由於ASP.NET Core框架在本質上就是由伺服器和中介軟體構建的訊息處理管道,所以在它上面構建的應用開發框架都是建立在某種型別的中介軟體上,整個ASP.NET Core MVC開發框架就是建立在用來實現路由的EndpointRoutingMiddleware和EndpointMiddleware中介軟體上

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Mac OS

除了微軟自家的Windows平臺, .NET Core針對Mac OS以及各種Linux Distribution(RHEL、Ubuntu、Debian、Fedora、CentOS和SUSE等)都提供了很好的支援。我們先來體驗一下使用Mac來開發.NET Core應用,在這之前我們照例先得在Mac OS上構建

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Linux

如果想體驗Linux環境下開發.NET Core應用,我們有多種選擇。一種就是在一臺物理機上安裝原生的Linux,我們可以根據自身的喜好選擇某種Linux Distribution,目前來說像RHEL、Ubuntu、Debian、Fedora、CentOS和SUSE這些主流的Distribution都是支援的

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Docker

對於一個 .NET Core開發人員,你可能沒有使用過Docker,但是你不可能沒有聽說過Docker。Docker是Github上最受歡迎的開源專案之一,它號稱要成為所有云應用的基石,並把網際網路升級到下一代。Docker是dotCloud公司開源的一款產品,從其誕生那一刻算起,在短短兩三年時間裡就成為了開

[ASP.NET Core 3框架揭祕] 依賴注入:控制反轉

ASP.NET Core框架建立在一些核心的基礎框架之上,這些基礎框架包括依賴注入、檔案系統、配置選項和診斷日誌等。這些框架不僅僅是支撐ASP.NET Core框架的基礎,我們在進行應用開發的時候同樣會頻繁地使用到它們。對於這裡提到的這幾個基礎框架,依賴注入尤為重要。ASP.NET Core應用在啟動以及後續

[ASP.NET Core 3框架揭祕] 依賴注入:IoC模式

正如我們在《依賴注入:控制反轉》提到過的,很多人將IoC理解為一種“面向物件的設計模式”,實際上IoC不僅與面向物件沒有必然的聯絡,它自身甚至算不上是一種設計模式。一般來講,設計模式提供了一種解決某種具體問題的方案,但是IoC既沒有一個針對性的問題領域,其自身也沒有提供一種可操作性的解

[ASP.NET Core 3框架揭祕] 依賴注入:依賴注入模式

IoC主要體現了這樣一種設計思想:通過將一組通用流程的控制權從應用轉移到框架之中以實現對流程的複用,並按照“好萊塢法則”實現應用程式的程式碼與框架之間的互動。我們可以採用若干設計模式以不同的方式實現IoC,比如我們在前面介紹的模板方法、工廠方法和抽象工廠,接下來我們介紹一種更有價值的I

[ASP.NET Core 3框架揭祕] 依賴注入:一個Mini版的依賴注入框架

在前面的章節中,我們從純理論的角度對依賴注入進行了深入論述,我們接下來會對.NET Core依賴注入框架進行單獨介紹。為了讓讀者朋友能夠更好地理解.NET Core依賴注入框架的設計與實現,我們按照類似的原理建立了一個簡易版本的依賴注入框架,也就是我們在前面多次提及的Cat。原始碼下載普通服務的註冊與消費泛型

[ASP.NET Core 3框架揭祕] 依賴注入[5]: 利用容器提供服務

毫不誇張地說,整個ASP.NET Core框架是建立在依賴注入框架之上的。ASP.NET Core應用在啟動時構建管道以及利用該管道處理每個請求過程中使用到的服務物件均來源於依賴注入容器。該依賴注入容器不僅為ASP.NET Core框架自身提供必要的服務,同時也是應用程式的服務提供者,依賴注入已經成為了ASP