Heim >Backend-Entwicklung >C#.Net-Tutorial >.Net Core verteiltes Mailsystem

.Net Core verteiltes Mailsystem

大家讲道理
大家讲道理Original
2018-05-30 15:24:114250Durchsuche

Dieser Artikel teilt ein verteiltes E-Mail-System, das hauptsächlich von NetCores API und Konsolenanwendung verwendet wird Ich kann nur die Konstruktionszeichnungen und einige Klassen oder Methoden teilen, die nicht für Unternehmen konzipiert sind.

Warum ist es das erste Mal im Unternehmen, dass NetCore für die Entwicklung verwendet wird?

Warum ist es das erste Mal? Sind einige Netcore-APIs nicht umfassend genug, wenn Sie NetCore für die Entwicklung verwenden? Trauen Sie sich, sie auszuprobieren? Ich fürchte, jemand wird mich das fragen. Ich kann Ihnen nur sagen, dass NetCore bereits Version 2.0 veröffentlicht hat. Darüber hinaus liegt der Schwerpunkt auf dem MVC-Modus Entwickeln Sie Systeme effizient und unterstützen Sie auch viele Core-Nuget-Pakete. Was ist, wenn einige Dinge nicht unterstützt werden? Sie können die Schnittstelle verwenden, um eine Verbindung herzustellen es von anderen Orten. Eine schöne Lösung. Um diese hervorragende Sprache C# weit verbreitet zu machen, arbeite ich im Stillen hart.

Die Artikel, die ich gerade über NetCore schreibe

AspNetCore - MVC Practical Series Inhaltsverzeichnis

.NetCore Mehrere Beispiele für das Hochladen mehrerer Dateien

Open Source ein plattformübergreifendes Service-Plug-in – TaskCore.MainFürm

NET Core-Study Notes

Asp.NetCore1.1-Version Projekt ist weg .json, um ein plattformübergreifendes Paket zu generieren

Hauptvideolink - Verteiltes E-Mail-Systemdesign Diagramm

Beschreibung des verteilten E-Mail-Systems

Tatsächlich verwende ich hier, wie Sie auf dem Bild oben sehen können, hauptsächlich das Api+-Dienstmodell, was auch der Fall ist eine Standardkombination, die heutzutage häufig von Internetunternehmen verwendet wird; Verwenden Sie die API, um Anfragen anzunehmen und zu sendende E-Mailsin die Warteschlange und in die Lagerhaltung einzufügen, und stellen Sie dann mehrere NetCore-übergreifende E-Mails bereit. Plattformdienste (Dienste beziehen sich hier auf: Konsolenanwendungen) Um verteilte Verarbeitungsvorgänge durchzuführen, Plattformübergreifender DienstDie Hauptvorgänge sind:

E-Mail-Versand

Benachrichtigung über den Status des E-Mail-Versands (Wenn das Unterunternehmen benachrichtigt werden muss, muss die Geschäftspartei über den Status informiert werden E-Mail-Versand)

Benachrichtigungsfehlerverarbeitung (automatische Bindung) Senden Sie eine E-Mail an die angegebene verantwortliche Person)

Füllen Sie die Warteschlange (falls vorhanden). Die Daten der ausgehenden E-Mail-Warteschlange oder der Benachrichtigungswarteschlange sind unvollständig, die Warteschlangendaten müssen repariert werden)

Einheitlicher Überprüfungseingang der API-Schnittstelle

Hier verwende ich die einfachste Methode,

Erben

Der Controller kapselt einen übergeordneten BaseController, damit der Controller jeder API die Authentifizierung auf einheitliche Weise durchführen kann. Schauen wir uns den Verifizierungscode zum Umschreiben von öffentlich Überschreibung an void OnActionExecuting(ActionExecutingContext context):


E-Mail-Anfrage an übergeordnete Entität:
 1 public override void OnActionExecuting(ActionExecutingContext context) 
 2         { 
 3             base.OnActionExecuting(context); 
 4  
 5             var moResponse = new MoBaseRp(); 
 6             try 
 7             { 
 8  
 9                 #region 安全性验证
 10 
 11                 var key = "request";
 12                 if (!context.ActionArguments.ContainsKey(key)) { moResponse.Msg = "请求方式不正确"; return; }
 13                 var request = context.ActionArguments[key];
 14                 var baseRq = request as MoBaseRq;
 15                 //暂时不验证登录账号密码
 16                 if (string.IsNullOrWhiteSpace(baseRq.UserName) || string.IsNullOrWhiteSpace(baseRq.UserPwd)) { moResponse.Msg = "登录账号或密码不能为空"; return; }
 17                 else if (baseRq.AccId <= 0) { moResponse.Msg = "发送者Id无效"; return; }
 18                 else if (string.IsNullOrWhiteSpace(baseRq.FuncName)) { moResponse.Msg = "业务方法名不正确"; return; }
 19 
 20                 //token验证
 21                 var strToken = PublicClass._Md5($"{baseRq.UserName}{baseRq.AccId}", "");
 22                 if (!strToken.Equals(baseRq.Token, StringComparison.OrdinalIgnoreCase)) { moResponse.Msg = "Token验证失败"; return; }
 23 
 24                 //验证发送者Id
 25                 if (string.IsNullOrWhiteSpace(baseRq.Ip))
 26                 {
 27                     var account = _db.EmailAccount.SingleOrDefault(b => b.Id == baseRq.AccId);
 28                     if (account == null) { moResponse.Msg = "发送者Id无效。"; return; }
 29                     else
 30                     {
 31                         if (account.Status != (int)EnumHelper.EmStatus.启用)
 32                         {
 33                             moResponse.Msg = "发送者Id已禁用"; return;
 34                         }
 35 
 36                         //验证ip
 37                         var ipArr = account.AllowIps.Split(new char[] { &#39;,&#39; }, StringSplitOptions.RemoveEmptyEntries);
 38                         //当前请求的Ip
 39                         var nowIp = this.GetUserIp();
 40                         baseRq.Ip = nowIp;
 41                         //默认*为所有ip , 匹配ip
 42                         if (!ipArr.Any(b => b.Equals("*")) && !ipArr.Any(b => b.Equals(nowIp)))
 43                         {
 44                             moResponse.Msg = "请求IP为授权"; return;
 45                         }
 46                     }
 47                 }
 48                 else
 49                 {
 50                     var account = _db.EmailAccount.SingleOrDefault(b => b.Id == baseRq.AccId && b.AllowIps.Any(bb => bb.Equals(baseRq.Ip)));
 51                     if (account == null) { moResponse.Msg = "发送者未授权"; return; }
 52                     else if (account.Status != (int)EnumHelper.EmStatus.启用)
 53                     {
 54                         moResponse.Msg = "发送者Id已禁用"; return;
 55                     }
 56                 }
 57 
 58                 //内容非空,格式验证
 59                 if (!context.ModelState.IsValid)
 60                 {
 61                     var values = context.ModelState.Values.Where(b => b.Errors.Count > 0);
 62                     if (values.Count() > 0)
 63                     {
 64                         moResponse.Msg = values.First().Errors.First().ErrorMessage;
 65                         return;
 66                     }
 67                 }
 68 
 69                 #endregion
 70 
 71                 moResponse.Status = 1;
 72             }
 73             catch (Exception ex)
 74             {
 75                 moResponse.Msg = "O No请求信息错误";
 76             }
 77             finally
 78             {
 79                 if (moResponse.Status == 0) { context.Result = Json(moResponse); }
 80             }
 81         }
 1 /// <summary> 
 2     /// 邮件请求父类 
 3     /// </summary> 
 4     public class MoBaseRq 
 5     { 
 6  
 7         public string UserName { get; set; } 
 8  
 9         public string UserPwd { get; set; }
 10 
 11         /// <summary>
 12         /// 验证token(Md5(账号+配置发送者账号信息的Id+Ip))   必填
 13         /// </summary>
 14         public string Token { get; set; }
 15 
 16         /// <summary>
 17         /// 配置发送者账号信息的Id  必填
 18         /// </summary>
 19         public int AccId { get; set; }
 20 
 21         /// <summary>
 22         /// 业务方法名称
 23         /// </summary>
 24         public string FuncName { get; set; }
 25 
 26         /// <summary>
 27         /// 请求者Ip,如果客户端没赋值,默认服务端获取
 28         /// </summary>
 29         public string Ip { get; set; }
 30 
 31     }

第三方Nuget包的便利

此邮件系统使用到了第三方包,这也能够看出有很多朋友正为开源,便利,NetCore的推广努力着;

首先看看MailKit(邮件发送)包,通过安装下载命令: Install-Package MailKit 能够下载最新包,然后你不需要做太花哨的分装,只需要正对于邮件发送的服务器,端口,账号,密码做一些设置基本就行了,如果可以您可以直接使用我的代码:

 1 /// 631fb227578dfffda61e1fa4d04b7d25 
 2         /// 发送邮件 
 3         /// 039f3e95db2a684c7b74365531eb6044 
 4         /// 99b66721bb716c6eb6248858e6afabfd8bb7487ae6a16a43571bc14c7fcf93c2 
 5         /// 0650a652733f77474d453f9eb9a48d388bb7487ae6a16a43571bc14c7fcf93c2 
 6         /// 1c385df0e091b792f8bbe6e914c8e6778bb7487ae6a16a43571bc14c7fcf93c2 
 7         /// 77f0c99f65057d8cbdf7a816a81405a98bb7487ae6a16a43571bc14c7fcf93c2 
 8         /// 1e8c6117c440c6fca484f2c6d869a8108bb7487ae6a16a43571bc14c7fcf93c2 
 9         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
 10         public static bool _SendEmail(
 11             Dictionary1c31b2bed3c3ee28739bab1dbc9f292f dicToEmail,
 12             string title, string content,
 13             string name = "爱留图网", string fromEmail = "841202396@qq.com",
 14             string host = "smtp.qq.com", int port = 587,
 15             string userName = "841202396@qq.com", string userPwd = "123123")
 16         {
 17             var isOk = false;
 18             try
 19             {
 20                 if (string.IsNullOrWhiteSpace(title) || string.IsNullOrWhiteSpace(content)) { return isOk; }
 21 
 22                 //设置基本信息
 23                 var message = new MimeMessage();
 24                 message.From.Add(new MailboxAddress(name, fromEmail));
 25                 foreach (var item in dicToEmail.Keys)
 26                 {
 27                     message.To.Add(new MailboxAddress(item, dicToEmail[item]));
 28                 }
 29                 message.Subject = title;
 30                 message.Body = new TextPart("html")
 31                 {
 32                     Text = content
 33                 };
 34 
 35                 //链接发送
 36                 using (var client = new SmtpClient())
 37                 {
 38                     // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
 39                     client.ServerCertificateValidationCallback = (s, c, h, e) => true;
 40 
 41                     //采用qq邮箱服务器发送邮件
 42                     client.Connect(host, port, false);
 43 
 44                     // Note: since we don't have an OAuth2 token, disable
 45                     // the XOAUTH2 authentication mechanism.
 46                     client.AuthenticationMechanisms.Remove("XOAUTH2");
 47 
 48                     //qq邮箱,密码(安全设置短信获取后的密码)  ufiaszkkulbabejh
 49                     client.Authenticate(userName, userPwd);
 50 
 51                     client.Send(message);
 52                     client.Disconnect(true);
 53                 }
 54                 isOk = true;
 55             }
 56             catch (Exception ex)
 57             {
 58 
 59             }
 60             return isOk;
 61         }

Redis方面的操作包StackExchange.Redis,现在NetCore支持很多数据库驱动(例如:Sqlserver,mysql,postgressql,db2等)这么用可以参考下这篇文章AspNetCore - MVC实战系列(一)之Sqlserver表映射实体模型,不仅如此还支持很多缓存服务(如:Memorycach,Redis),这里讲到的就是Redis,我利用Redis的list的队列特性来做分布式任务存储,尽管目前我用到的只有一个主Redis服务还没有业务场景需要用到主从复制等功能;这里分享的代码是基于StackExchange.Redis基础上封装对于string,list的操作:

  1   public class StackRedis : IDisposable  
  2     {  
  3         #region 配置属性   基于 StackExchange.Redis 封装  
  4         //连接串 (注:IP:端口,属性=,属性=)  
  5         public string _ConnectionString = "127.0.0.1:6377,password=shenniubuxing3";  
  6         //操作的库(注:默认0库)  
  7         public int _Db = 0;  
  8         #endregion  
  9  
  10         #region 管理器对象 
  11  
  12         /// 631fb227578dfffda61e1fa4d04b7d25 
  13         /// 获取redis操作类对象 
  14         /// 039f3e95db2a684c7b74365531eb6044 
  15         private static StackRedis _StackRedis; 
  16         private static object _locker_StackRedis = new object(); 
  17         public static StackRedis Current 
  18         { 
  19             get 
  20             { 
  21                 if (_StackRedis == null) 
  22                 { 
  23                     lock (_locker_StackRedis) 
  24                     { 
  25                         _StackRedis = _StackRedis ?? new StackRedis(); 
  26                         return _StackRedis; 
  27                     } 
  28                 } 
  29  
  30                 return _StackRedis; 
  31             } 
  32         } 
  33  
  34         /// 631fb227578dfffda61e1fa4d04b7d25 
  35         /// 获取并发链接管理器对象 
  36         /// 039f3e95db2a684c7b74365531eb6044 
  37         private static ConnectionMultiplexer _redis; 
  38         private static object _locker = new object(); 
  39         public ConnectionMultiplexer Manager 
  40         { 
  41             get 
  42             { 
  43                 if (_redis == null) 
  44                 { 
  45                     lock (_locker) 
  46                     { 
  47                         _redis = _redis ?? GetManager(this._ConnectionString); 
  48                         return _redis; 
  49                     } 
  50                 } 
  51  
  52                 return _redis; 
  53             } 
  54         } 
  55  
  56         /// 631fb227578dfffda61e1fa4d04b7d25 
  57         /// 获取链接管理器 58         /// 039f3e95db2a684c7b74365531eb6044 
  59         /// 907b64d6f55b544ebfbd0f523985dc218bb7487ae6a16a43571bc14c7fcf93c2 
  60         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 
  61         public ConnectionMultiplexer GetManager(string connectionString) 
  62         { 
  63             return ConnectionMultiplexer.Connect(connectionString); 
  64         } 
  65  
  66         /// 631fb227578dfffda61e1fa4d04b7d25 
  67         /// 获取操作数据库对象 
  68         /// 039f3e95db2a684c7b74365531eb6044 
  69         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 
  70         public IDatabase GetDb() 
  71         { 
  72             return Manager.GetDatabase(_Db); 
  73         } 
  74         #endregion 
  75  
  76         #region 操作方法 
  77  
  78         #region string 操作 
  79  
  80         /// 631fb227578dfffda61e1fa4d04b7d25 
  81         /// 根据Key移除 
  82         /// 039f3e95db2a684c7b74365531eb6044 
  83         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2 
  84         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 
  85         public async Task9eac9cfd9e022188a134e2cbc39820d5 Remove(string key) 
  86         { 
  87             var db = this.GetDb(); 
  88  
  89             return await db.KeyDeleteAsync(key); 
  90         } 
  91  
  92         /// 631fb227578dfffda61e1fa4d04b7d25 
  93         /// 根据key获取string结果 
  94         /// 039f3e95db2a684c7b74365531eb6044 
  95         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2 
  96         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 
  97         public async Task98c455a79ddfebb79781bff588e7b37e Get(string key) 
  98         { 
  99             var db = this.GetDb();
  100             return await db.StringGetAsync(key);
  101         }
  102 
  103         /// 631fb227578dfffda61e1fa4d04b7d25
  104         /// 根据key获取string中的对象
  105         /// 039f3e95db2a684c7b74365531eb6044
  106         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  107         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  108         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  109         public async Task8742468051c85b06f0a0af9e3e506b5c Get8742468051c85b06f0a0af9e3e506b5c(string key)
  110         {
  111             var t = default(T);
  112             try
  113             {
  114                 var _str = await this.Get(key);
  115                 if (string.IsNullOrWhiteSpace(_str)) { return t; }
  116 
  117                 t = JsonConvert.DeserializeObject8742468051c85b06f0a0af9e3e506b5c(_str);
  118             }
  119             catch (Exception ex) { }
  120             return t;
  121         }
  122 
  123         /// 631fb227578dfffda61e1fa4d04b7d25
  124         /// 存储string数据
  125         /// 039f3e95db2a684c7b74365531eb6044
  126         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  127         /// baf7518bd06a20614696879534a64e8e8bb7487ae6a16a43571bc14c7fcf93c2
  128         /// 52d2b40b4cb5f9a554e9da01ad3fff218bb7487ae6a16a43571bc14c7fcf93c2
  129         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  130         public async Task9eac9cfd9e022188a134e2cbc39820d5 Set(string key, string value, int expireMinutes = 0)
  131         {
  132             var db = this.GetDb();
  133             if (expireMinutes > 0)
  134             {
  135                 return db.StringSet(key, value, TimeSpan.FromMinutes(expireMinutes));
  136             }
  137             return await db.StringSetAsync(key, value);
  138         }
  139 
  140         /// 631fb227578dfffda61e1fa4d04b7d25
  141         /// 存储对象数据到string
  142         /// 039f3e95db2a684c7b74365531eb6044
  143         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  144         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  145         /// baf7518bd06a20614696879534a64e8e8bb7487ae6a16a43571bc14c7fcf93c2
  146         /// 52d2b40b4cb5f9a554e9da01ad3fff218bb7487ae6a16a43571bc14c7fcf93c2
  147         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  148         public async Task9eac9cfd9e022188a134e2cbc39820d5 Set8742468051c85b06f0a0af9e3e506b5c(string key, T value, int expireMinutes = 0)
  149         {
  150             try
  151             {
  152                 var jsonOption = new JsonSerializerSettings()
  153                 {
  154                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore
  155                 };
  156                 var _str = JsonConvert.SerializeObject(value, jsonOption);
  157                 if (string.IsNullOrWhiteSpace(_str)) { return false; }
  158 
  159                 return await this.Set(key, _str, expireMinutes);
  160             }
  161             catch (Exception ex) { }
  162             return false;
  163         }
  164         #endregion
  165 
  166         #region List操作(注:可以当做队列使用)
  167 
  168         /// 631fb227578dfffda61e1fa4d04b7d25
  169         /// list长度
  170         /// 039f3e95db2a684c7b74365531eb6044
  171         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  172         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  173         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  174         public async Task4db15037c2d45d75b28ec2b6a696f099 GetListLen8742468051c85b06f0a0af9e3e506b5c(string key)
  175         {
  176             try
  177             {
  178                 var db = this.GetDb();
  179                 return await db.ListLengthAsync(key);
  180             }
  181             catch (Exception ex) { }
  182             return 0;
  183         }
  184 
  185         /// 631fb227578dfffda61e1fa4d04b7d25
  186         /// 获取队列出口数据并移除
  187         /// 039f3e95db2a684c7b74365531eb6044
  188         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  189         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  190         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  191         public async Task8742468051c85b06f0a0af9e3e506b5c GetListAndPop8742468051c85b06f0a0af9e3e506b5c(string key)
  192         {
  193             var t = default(T);
  194             try
  195             {
  196                 var db = this.GetDb();
  197                 var _str = await db.ListRightPopAsync(key);
  198                 if (string.IsNullOrWhiteSpace(_str)) { return t; }
  199                 t = JsonConvert.DeserializeObject8742468051c85b06f0a0af9e3e506b5c(_str);
  200             }
  201             catch (Exception ex) { }
  202             return t;
  203         }
  204 
  205         /// 631fb227578dfffda61e1fa4d04b7d25
  206         /// 集合对象添加到list左边
  207         /// 039f3e95db2a684c7b74365531eb6044
  208         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  209         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  210         /// 3c7bf1722eecc8ca7bc30043734f11978bb7487ae6a16a43571bc14c7fcf93c2
  211         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  212         public async Task4db15037c2d45d75b28ec2b6a696f099 SetLists8742468051c85b06f0a0af9e3e506b5c(string key, List8742468051c85b06f0a0af9e3e506b5c values)
  213         {
  214             var result = 0L;
  215             try
  216             {
  217                 var jsonOption = new JsonSerializerSettings()
  218                 {
  219                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore
  220                 };
  221                 var db = this.GetDb();
  222                 foreach (var item in values)
  223                 {
  224                     var _str = JsonConvert.SerializeObject(item, jsonOption);
  225                     result += await db.ListLeftPushAsync(key, _str);
  226                 }
  227                 return result;
  228             }
  229             catch (Exception ex) { }
  230             return result;
  231         }
  232 
  233         /// 631fb227578dfffda61e1fa4d04b7d25
  234         /// 单个对象添加到list左边
  235         /// 039f3e95db2a684c7b74365531eb6044
  236         /// d65706098b2250eee2f48a758c9680c88ed7e392d75469626ca6a252f320a704
  237         /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2
  238         /// baf7518bd06a20614696879534a64e8e8bb7487ae6a16a43571bc14c7fcf93c2
  239         /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
  240         public async Task4db15037c2d45d75b28ec2b6a696f099 SetList8742468051c85b06f0a0af9e3e506b5c(string key, T value)
  241         {
  242             var result = 0L;
  243             try
  244             {
  245                 result = await this.SetLists(key, new List8742468051c85b06f0a0af9e3e506b5c { value });
  246             }
  247             catch (Exception ex) { }
  248             return result;
  249         }
  250 
  251 
  252         #endregion
  253 
  254         #region 额外扩展
  255 
  256         /// 631fb227578dfffda61e1fa4d04b7d25
  257         /// 手动回收管理器对象
  258         /// 039f3e95db2a684c7b74365531eb6044
  259         public void Dispose()
  260         {
  261             this.Dispose(_redis);
  262         }
  263 
  264         public void Dispose(ConnectionMultiplexer con)
  265         {
  266             if (con != null)
  267             {
  268                 con.Close();
  269                 con.Dispose();
  270             }
  271         }
  272 
  273         #endregion
  274 
  275         #endregion
  276     }

用到Redis的那些操作就添加哪些就行了,也不用太花哨能用就行;

如何生成跨平台的api服务和应用程序服务

这小节的内容最重要,由于之前有相关的文章,这里就不用再赘述了,来这里看看:Asp.NetCore1.1版本没了project.json,这样来生成跨平台包

Das obige ist der detaillierte Inhalt von.Net Core verteiltes Mailsystem. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn