<smtp deliveryMethod="Network" from="xxx"> <network host="smtp.gmail.com" password="yyy" port="587" userName="zzz" enableSsl="true" /> </smtp>
معرفی کتابخانه Postal برای ASP.NET MVC
<smtp deliveryMethod="Network" from="xxx@gmail.com"> <network host="smtp.gmail.com" port="587" enableSsl="true" userName="xxx@gmail.com" password="xxx" /> </smtp>
Top 3 Open Source ASP.NET Core based e-commerce web applications
nopCommerce
SimplCommerce
grandnode ( Powered By nopCommerce) :It’s an open source, free, cross-platform e-commerce software based on ASP.NET Core 2.2 and MongoDB — NoSQL database. You can run it on Linux, Windows, and MacOS easily. GrandNode also supports Docker, so you are able to install it just in seconds with Docker.
متدهای async تقلبی
device.connect(ip,port)
Ionic , react native , flutter , xamarin ….
مزایای نوشتن یک اپلیکیشن با فریم ورکها:
1- نوشتن کد به مراتب آسانتر است.
۲- چون اکثر فریم ورکها، فریم ورکهای جاوا اسکریپتی هستند، سرعت بالایی هنگام run کردن برنامه دارند ولی در build آخر و خروجی نهایی بر روی پلتفرم، این سرعت کندتر میشود.
۳- cossplatform بودن. با طراحی یک اپلیکیشن برای یک پلتفرم میتوان همزمان برای پلتفرمهای دیگر خروجی گرفت.
۱- برنامه نویس را محدود میکند.
۲- سرعت اجرای پایینی دارد.
۳- حجم برنامه به مراتب بالاتر میباشد.
۴- از منابع سخت افزاری بیشتری استفاده میکند.
اگر شما هم میخواهید از فریم ورکها برای طراحی اپلیکیشن استفاده کنید در اینجا میتوانید اطلاعات بیشتری را درباره هر کدام از فریم ورکها ببینید. هر کدام از این فریم ورکها دارای مزایا معایب و همچنین رزومه کاری خوب میباشند. بیشتر فریم ورکهای بالا در رندر آخر، همان کد native را تولید میکنند؛ مثلا اگر برنامهای را با react native بنویسید، میتوانید همان برنامه را بر روی اندروید استودیو و کد native بالا بیارید. توضیحات بالا مقایسه فریم ورکهای Cross Platform با زبانهای native بود. اما در این مقاله قصد آشنایی با تکنولوژی جدیدی را داریم که شما را قادر میسازد یک وب اپلیکیشن را با آن طراحی کنید.
pwa مخفف Progressive Web Apps است و یک تکنولوژی برای طراحی وب اپلیکیشنهای تحت مرورگر میباشد. شما با pwa میتوانید اپلیکیشن خود را بر روی پلتفرمهای مختلفی اجرا کنید، طوری که کاربران متوجه نشوند با یک صفحهی وبی دارند کار میکنند. شاید شما هم فکر کنید این کار را هم میتوان با html ,css و responsive کردن صفحه انجام داد! ولی اگر بخواهید کاربر متوجه استفادهی از یک صفحهی وبی نشود، باید حتما از pwa استفاده کنید! برای مثال یک صفحهی وبی معمولی حتما باید در بستر اینترنت اجرا شود، ولی با pwa با یکبار وصل شدن به اینترنت و کش کردن دادهها، برای بار دوم دیگر نیازی به اینترنت ندارد و میتواند به صورت offline کار کند. شما حتی با pwa میتوانید اپلیکیشن را در background اجرا کنید و notification ارسال کنید.
۱- یکی از مزیتهای مهم pwa، حالت offline آن میباشد که حتی با قطع اینترنت، شما میتوانید همچنان با اپلیکیشن کار کنید.
۲- با توجه به اینکه شما در حقیقت با یک صفحهی وبی کار میکنید، دیگر نیازی به دانلود و نصب ندارید.
۳- امکان بهروز رسانی کردن، بدون اعلام کردن نسخه جدید.
۴- از سرعت بسیار زیادی برخوردار است.
۵- چون pwa از پروتکل https استفاده میکند، دارای امنیت بالایی میباشد.
۱- محدود به مرورگر میباشد.
۲- هرچند امروزه اکثر مرورگرها pwa را پشتیبانی میکنند، ولی در بعضی از مرورگرها و مرورگرهای با ورژن پایین، pwa پشتیبانی نمیشود.
3- نمیتوان یک برنامهی مبتنی بر os را نوشت و محدود به مرورگر میباشد
1- برای pwa لزومی ندارد حتما از فریم ورکهای spa استفاده کنید. شما از هر فریم ورک Client Side ای میتوانید استفاده کنید.
۲- چون صفحات شما در پلتفرمهای مختلف و با صفحه نمایشهای مختلفی اجرا میشود، باید صفحات به صورت کاملا responsive شده طراحی شوند.
۳- باید از پروتکل https استفاده کنید.
ما در این مقاله از فریم ورک angular استفاده خواهیم کرد.
قبل از شروع، با شیوه کار pwa آشنا خواهیم شد. یکی از قسمتهای مهم Service Worker ،pwa میباشد که از جمله کش کردن، notification فرستادن و اجرای پردازشها در پس زمینه را بر عهده دارد.
چند نکته در رابطه با Service Worker
- نباید برای نگهداری داده global از Service Worker استفاد کرد. برای استفاده از دادههای Global میتوان از Local Storage یا IndexedDB استفاده کرد.
- service worker به dom دسترسی ندارند.
قبل از شروع، سناریوی پروژه را تشریح خواهیم کرد. رکن اصلی یک برنامهی وب، UI آن میباشد و قصد داریم کاربران را متوجه کار با یک صفحهی وبی نکنیم. قالبی که ما در این مثال در نظر گرفتیم خیلی شبیه به یک اپلیکیشن پلتفرم اندرویدی میباشد. یک کاربر با کشیدن منوی کشویی میتواند گزینههای خود را انتخاب نمایند. اولین گزینهای که قصد پیاده سازی آن را داریم، ثبت کاربران میباشد. بعد از ثبت کاربران در یک Component جدا، کاربران را در یک جدول نمایش خواهیم داد.
1- سرویس crud را به صورت کامل در پروژه قرار خواهیم داد، ولی چون از حوصلهی مقاله خارج است، فقط ثبت کاربران و نمایش کاربران را پیاده سازی خواهیم کرد.
شروع به کار
پیش نیازهای یک پروژهی انگیولاری را بر روی سیستم خود فراهم کنید. ما در این مثال از یک template آماده انگیولاری استفاده خواهیم کرد. پس برای اینکه با جزئیات و طراحی ui درگیر نشویم، از لینک github پروژه را دریافت کنید.
سپس وارد root پروژه شوید و با دستور زیر پکیجهای پروژه را نصب کنید:
npm install
قبل از اینکه کاری را انجام دهید، چند بار صفحه را refresh کنید! صفحه بدون هیچ تغییری refresh میشود. اینبار گزینهی offline را فعال کنید و مجددا صفحه را refresh کنید.
نصب pwa بر روی پروژه
برای اضافه کردن pwa به پروژه وارد ریشهی پروژه شوید و دستور زیر را وارد کنید:
ng add @angular/PWA
Manifest.json : اگر محتویات فایل را مشاهده کرده باشید، شامل تنظیمات فنی وب اپلیکیشن میباشد؛ از جمله Home Screen Icon و نام وب اپلیکیشن و سایر تنظیمات دیگر.
Nsgw-config.json : این فایل نسبت به فایل manifest فنیتر میباشد و بیشتر به کانفیگ مد آفلاین و کش کردن مرتبط میشود. در ادامه با این فایل بیشتر کار داریم.
اجرا کردن وب اپلیکیشن
برای اجرا کردن و نمایش خروجی از وب اپلیکیشن، ابتدا باید از پروژه build گرفت. با استفاده از دستور زیر از پروژه خود build بگیرید:
ng build -- prod
cd dist/Web Application Pwa
Http-server -o
npm i http-server
برسی فایل Nsgw-config.json
وارد فایل Nsgw-config.json شوید:
"$schema": "./node_modules/@angular/service-worker/config/schema.json", "index": "/index.html", "assetGroups": [ { "name": "app", "installMode": "prefetch", "resources": { "files": [ "/favicon.ico", "/index.html", "/*.css", "/*.js" ] } }, { "name": "assets", "installMode": "lazy", "updateMode": "prefetch", "resources": { "files": [ "/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)" ] } } ], "dataGroups": [ { "name": "api-performance", "urls": [ "https://api/**" ], "cacheConfig": { "strategy": "performance", "maxSize": 100, "maxAge": "3d" } } ] }
۱- assetGroups : کش کردن اطلاعات مربوط به اپلیکیشن
۲- Index : کش کردن فایل مربوط به index.html
۳- assetGroups : کش کردن فایلهای مربوط به asset، شامل فایلهای js، css و غیره
۴- dataGroups : این object مربوط به وقتی است که برنامه در حال اجرا است. میتوان دادههای در حال اجرای اپلیکیشن را کش کرد. دادهی در حال اجرا میتواند شامل فراخوانی apiها باشد. برای مثال فرض کنید شما در حالت کار کردن online با اپلیکیشن، لیستی از اسامی کاربران را از api گرفته و نمایش میدهید. وقتی دفعهی بعد در حالت offline اپلیکیشن را باز کنیم، اگر api را کش کرده باشیم، اپلیکیشن دادهها را از کش فراخوانی میکند. این عمل درباره post کردن دادهها هم صدق میکند.
خود dataGroups شامل چند object زیر میباشد:
۱- name : یک نام انتخابی برای Groups میباشد.
۲- urls : شامل آرایهای از آدرسها میباشد. میتوان آدرس یک دومین را همراه با کل apiها به صورت زیر کش کرد:
"https://api/**"
۱- maxSize : حداکثر تعداد کشهای مربوط به Groups .
۲- maxAge : حداکثر lifetime مربوط به کش.
۳- strategy : که میتواند یکی از مقادیر freshness به معنی Network-First یا performance به معنی Cache-First باشد.
پیاده سازی پیغام نمایش بهروزرسانی جدید وب اپلیکیشن
در اپلیکیشنهای native وقتی بهروزرسانی جدیدی برای app اعلام میشود، در فروشگاهای اینترنتی پیغامی مبنی بر بهروزرسانی جدید app برای کاربران ارسال میشود که کاربران میتوانند app خود را بهروزرسانی کنند. ولی در pwa تنها با یک رفرش صفحه میتوان اپلیکیشن را به جدیدترین امکانات بهروزرسانی کرد! برای اینکه بتوانیم با هر تغییر، پیغامی را جهت بهروزرسانی نسخه یا هر پیغامی دیگری را نمایش دهیم، از کد زیر استفاده میکنم:
if(this.swUpdate.isEnabled) { this.swUpdate.available.subscribe(()=> { if(confirm("New Version available.Load New Version?")){ window.location.reload(); } }) }
در منوی سمت چپ، بر روی database کلیک کنید و یک دیتابیس را در حالت test mode ایجاد نماید. سپس یک collection را به نام user ایجاد کرده و فیلدهای زیر را به آن اضافه کنید:
Age :number Fullname :string Mobile : string
npm install --save firebase @angular/fire
@NgModule({ declarations: [AppComponent, RegisterComponent,AboutComponent, UserListComponent], imports: [ BrowserModule, FormsModule, HttpClientModule, HttpClientModule, SharedModule, AppRoutingModule, AngularFireModule.initializeApp(environmentFirebase.firebase), AngularFireDatabaseModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }), ], providers: [FirebaseService], bootstrap: [AppComponent] }) export class AppModule {}
export const environment ={ production: true, firebase: { apiKey: "AIz×××××××××××××××××××××××××××××××××8", authDomain: "pwaangular-6c041.firebaseapp.com", databaseURL: "https://pwaangular-6c041.firebaseio.com", projectId: "pwaangular-6c041", storageBucket: "pwaangular-6c041.appspot.com", messagingSenderId: "545522081966" } }
FirebaseService در قسمت providers مربوط به سرویس crud میباشد. اگر وارد فایل مربوطه شوید، چند عمل اصلی به صورت زیر در آن پیاده سازی شده است:
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import * as firebase from 'firebase'; import { AngularFireDatabase } from '@angular/fire/database'; import { HttpClient } from '@angular/common/http'; import { map } from 'rxjs/operators'; import { ThrowStmt } from '@angular/compiler'; @Injectable({ providedIn: 'root' }) export class FirebaseService { ref = firebase.firestore().collection('users'); constructor(public db: AngularFireDatabase,public _http:HttpClient) { } getUsers(): Observable<any> { return new Observable((observer) => { this.ref.onSnapshot((querySnapshot) => { let User = []; querySnapshot.forEach((doc) => { let data = doc.data(); User.push({ key: doc.id, fullname: data.fullname, age: data.age, mobile: data.mobile }); }); observer.next(User); }); }); } getUser(id: string): Observable<any> { return new Observable((observer) => { this.ref.doc(id).get().then((doc) => { let data = doc.data(); observer.next({ key: doc.id, title: data.title, description: data.description, author: data.author }); }); }); } postUser(user): Observable<any> { return new Observable((observer) => { this.ref.add(user).then((doc) => { observer.next({ key: doc.id, }); }); }); } updateUser(id: string, data): Observable<any> { return new Observable((observer) => { this.ref.doc(id).set(data).then(() => { observer.next(); }); }); } deleteUser(id: string): Observable<{}> { return new Observable((observer) => { this.ref.doc(id).delete().then(() => { observer.next(); }); }); } getDataOnApi(){ return this._http.get('https://site.com/api/General/Getprovince') .pipe( map((res: Response) => { return res; }) ); } getOnApi(){ return this._http.get("https://site.com/api/General/Getprovince",).pipe( map((response:any) => { return response } ) ); } }
با دستورات زیر میتوانید مجددا پروژه را اجرا کنید:
ng build --prod cd dist/Pwa-WepApp Http-server -o
تست وب اپلیکیشن بر روی پلتفرمهای مختلف
برای اینکه بتوانیم خروجی وب اپلیکیشن را بر روی پلتفرمهای مختلفی تست کنیم، میتوانیم آن را آپلود کرده و مثل یک سایت اینترنتی، با وارد کردن دومین، وارده پروژه شد. ولی کم هزینهترین راه، استفاده از ابزار ngrok میباشد. میتوانید توسط این مقاله پروژه خودتان در لوکال بر روی https سوار کنید.
نکته! توجه کنید apiهای مربوط به firebase را نمیتوان کش کرد.
کدهای مربوط به این قسمت را میتوانید از این repository دریافت کنید .
کتاب رایگان MongoDB 3 Succinctly
MongoDB is one of the biggest players in the NoSQL database market, providing high performance, high availability, and automatic scaling. It’s an open-source document database written in C++ and hosted on GitHub. Zoran Maksimovic’s MongoDB 3 Succinctly touches on the most important aspects of the MongoDB database that application developers should be aware of—from installation and the usage of the Mongo Shell, to examples of the MongoDB C# driver APIs for Microsoft .NET Framework.
Table of Contents
- MongoDB Overview
- MongoDB Installation
- The Mongo Shell
- Manipulating Documents
- Data Retrieval
- Basic MongoDB with C#
- Data Handling in C#
- Inserting Data in C#
- Find (Query) Data in C#
- Binary Data (File Handling) in C#
- Back Up and Restore
using(var client = new HttpClient()) { // do something with http client }
Unable to connect to the remote server System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.
HttpClient خود را Dispose نکنید
کلاس HttpClient اینترفیس IDisposable را پیاده سازی میکند. بنابراین روش استفادهی اصولی آن باید به صورت ذیل و با پیاده سازی خودکار رهاسازی منابع مرتبط با آن باشد:
using (var client = new HttpClient()) { var result = await client.GetAsync("http://example.com/"); }
for (int i = 0; i < 10; i++) { using (var client = new HttpClient()) { var result = await client.GetAsync("http://example.com/"); Console.WriteLine(result.StatusCode); } }
TCP 192.168.1.6:13996 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:13997 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:13998 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:13999 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14000 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14001 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14002 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14003 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14004 93.184.216.34:http TIME_WAIT TCP 192.168.1.6:14005 93.184.216.34:http TIME_WAIT
بنابراین اگر برنامهی شما تعداد زیادی کاربر دارد و یا تعداد زیادی درخواست را به روش فوق ارسال میکند، سیستم عامل به حد اشباع ایجاد سوکتهای جدید خواهد رسید.
این مشکل نیز ارتباطی به طراحی این کلاس و یا زبان #C و حتی استفادهی از using نیز ندارد. این رفتار، رفتار معمول سیستم عامل، با سوکتهای ایجاد شدهاست. TIME_WAIT ایی را که در اینجا ملاحظه میکنید، به معنای بسته شدن اتصال از طرف برنامهی ما است؛ اما سیستم عامل هنوز منتظر نتیجهی نهایی، از طرف دیگر اتصال است که آیا قرار است بستهی TCP ایی را دریافت کند یا خیر و یا شاید در بین راه تاخیری وجود داشتهاست. برای نمونه ویندوز به مدت 240 ثانیه یک اتصال را در این حالت حفظ خواهد کرد، که مقدار آن نیز در اینجا تنظیم میشود:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay]
بنابراین روش توصیه شدهی کار با HttpClient، داشتن یک وهلهی سراسری از آن در برنامه و عدم Dispose آن است. HttpClient نیز thread-safe طراحی شدهاست و دسترسی به یک شیء سراسری آن در برنامههای چند ریسمانی مشکلی را ایجاد نمیکند. همچنین Dispose آن نیز غیرضروری است و پس از پایان برنامه به صورت خودکار توسط سیستم عامل انجام خواهد شد.
تمام اجزای HttpClient به صورت Thread-safe طراحی نشدهاند
تا اینجا به این نتیجه رسیدیم که روش صحیح کار کردن با HttpClient، نیاز به داشتن یک وهلهی Singleton از آنرا در سراسر برنامه دارد و Dispose صریح آن، بجز اشباع سوکتهای سیستم عامل و ناپایدار کردن تمام برنامههایی که از آن سرویس میگیرند، حاصلی را به همراه نخواهد داشت. در این بین مطابق مستندات HttpClient، استفادهی از متدهای ذیل این کلاس thread-safe هستند:
CancelPendingRequests DeleteAsync GetAsync GetByteArrayAsync GetStreamAsync GetStringAsync PostAsync PutAsync SendAsync
BaseAddress DefaultRequestHeaders MaxResponseContentBufferSize Timeout
استفادهی سراسری و مجدد از HttpClient، تغییرات DNS را متوجه نمیشود
با طراحی یک کلاس مدیریت کنندهی سراسری HttpClient با طول عمر Singelton، به یک مشکل دیگر نیز برخواهیم خورد: چون در اینجا از اتصالات، استفادهی مجدد میشوند، دیگر تغییرات DNS را لحاظ نخواهند کرد.
برای حل این مشکل، در زمان ایجاد یک HttpClient سراسری، به ازای یک BaseAddress مشخص، باید از ServicePointManager کوئری گرفته و زمان اجارهی اتصال آنرا دقیقا مشخص کنیم:
var sp = ServicePointManager.FindServicePoint(new Uri("http://thisisasample.com")); sp.ConnectionLeaseTimeout = 60*1000; //In milliseconds
طراحی یک کلاس، برای مدیریت سراسری وهلههای HttpClient
تا اینجا به صورت خلاصه به نکات ذیل رسیدیم:
- HttpClient باید به صورت یک وهلهی سراسری Singleton مورد استفاده قرار گیرد. هر وهله سازی مجدد آن 35ms زمان میبرد.
- Dispose یک HttpClient غیرضروری است.
- HttpClient تقریبا thread safe طراحی شدهاست؛ اما تعدادی از خواص آن مانند BaseAddress اینگونه نیستند.
- برای رفع مشکل اتصالات چسبنده (اتصالاتی که هیچگاه پایان نمییابند)، نیاز است timeout آنرا تنظیم کرد.
بنابراین بهتر است این نکات را در یک کلاس به صورت ذیل کپسوله کنیم:
using System; using System.Collections.Generic; using System.Net.Http; namespace HttpClientTips { public interface IHttpClientFactory : IDisposable { HttpClient GetOrCreate( Uri baseAddress, IDictionary<string, string> defaultRequestHeaders = null, TimeSpan? timeout = null, long? maxResponseContentBufferSize = null, HttpMessageHandler handler = null); } }
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Threading; namespace HttpClientTips { /// <summary> /// Lifetime of this class should be set to `Singleton`. /// </summary> public class HttpClientFactory : IHttpClientFactory { // 'GetOrAdd' call on the dictionary is not thread safe and we might end up creating the HttpClient more than // once. To prevent this Lazy<> is used. In the worst case multiple Lazy<> objects are created for multiple // threads but only one of the objects succeeds in creating the HttpClient. private readonly ConcurrentDictionary<Uri, Lazy<HttpClient>> _httpClients = new ConcurrentDictionary<Uri, Lazy<HttpClient>>(); private const int ConnectionLeaseTimeout = 60 * 1000; // 1 minute public HttpClientFactory() { // Default is 2 minutes: https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.dnsrefreshtimeout(v=vs.110).aspx ServicePointManager.DnsRefreshTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; // Increases the concurrent outbound connections ServicePointManager.DefaultConnectionLimit = 1024; } public HttpClient GetOrCreate( Uri baseAddress, IDictionary<string, string> defaultRequestHeaders = null, TimeSpan? timeout = null, long? maxResponseContentBufferSize = null, HttpMessageHandler handler = null) { return _httpClients.GetOrAdd(baseAddress, uri => new Lazy<HttpClient>(() => { // Reusing a single HttpClient instance across a multi-threaded application means // you can't change the values of the stateful properties (which are not thread safe), // like BaseAddress, DefaultRequestHeaders, MaxResponseContentBufferSize and Timeout. // So you can only use them if they are constant across your application and need their own instance if being varied. var client = handler == null ? new HttpClient { BaseAddress = baseAddress } : new HttpClient(handler, disposeHandler: false) { BaseAddress = baseAddress }; setRequestTimeout(timeout, client); setMaxResponseBufferSize(maxResponseContentBufferSize, client); setDefaultHeaders(defaultRequestHeaders, client); setConnectionLeaseTimeout(baseAddress, client); return client; }, LazyThreadSafetyMode.ExecutionAndPublication)).Value; } public void Dispose() { foreach (var httpClient in _httpClients.Values) { httpClient.Value.Dispose(); } } private static void setConnectionLeaseTimeout(Uri baseAddress, HttpClient client) { // This ensures connections are used efficiently but not indefinitely. client.DefaultRequestHeaders.ConnectionClose = false; // keeps the connection open -> more efficient use of the client ServicePointManager.FindServicePoint(baseAddress).ConnectionLeaseTimeout = ConnectionLeaseTimeout; // ensures connections are not used indefinitely. } private static void setDefaultHeaders(IDictionary<string, string> defaultRequestHeaders, HttpClient client) { if (defaultRequestHeaders == null) { return; } foreach (var item in defaultRequestHeaders) { client.DefaultRequestHeaders.Add(item.Key, item.Value); } } private static void setMaxResponseBufferSize(long? maxResponseContentBufferSize, HttpClient client) { if (maxResponseContentBufferSize.HasValue) { client.MaxResponseContentBufferSize = maxResponseContentBufferSize.Value; } } private static void setRequestTimeout(TimeSpan? timeout, HttpClient client) { if (timeout.HasValue) { client.Timeout = timeout.Value; } } } }
پس از تدارک این کلاس، نحوهی معرفی آن به سیستم باید به صورت Singleton باشد. برای مثال اگر از ASP.NET Core استفاده میکنید، آنرا به صورت ذیل ثبت کنید:
namespace HttpClientTips.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpClientFactory, HttpClientFactory>(); services.AddMvc(); }
اکنون، یک نمونه، نحوهی استفادهی از اینترفیس IHttpClientFactory تزریقی به صورت ذیل میباشد:
namespace HttpClientTips.Web.Controllers { public class HomeController : Controller { private readonly IHttpClientFactory _httpClientFactory; public HomeController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<IActionResult> Index() { var host = new Uri("http://localhost:5000"); var httpClient = _httpClientFactory.GetOrCreate(host); var responseMessage = await httpClient.GetAsync("home/about").ConfigureAwait(false); var responseContent = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); return Content(responseContent); }
برای مطالعهی بیشتر
You're using HttpClient wrong and it is destabilizing your software
Disposable, Finalizers, and HttpClient
Using HttpClient as it was intended (because you’re not)
Singleton HttpClient? Beware of this serious behaviour and how to fix it
Beware of the .NET HttpClient
Effectively Using HttpClient
بازنویسی سطح دوم کش برای Entity framework 6
پیاده سازی معماری میکروسرویس در دات نت با استفاده از ابزار های
Ocelot For Api Getway
RabbitMQ For Message Broker
JWT Token For Authentication And Authorization
SQL Server And MongoDB For Databases
ASP Core Web Api For Our Rest Api And Swagger As Open API
Google RPC (GRPC) For Transfer Data Between Microservice
Docker For Run Database Services ( SQL Server , MongoDB ) And Message Broker ( RabbitMQ )
دوره کامل Docker
Complete Docker Course - From BEGINNER to PRO! (Learn Containers)
Learn Docker and containers to improve your software systems! 🐳 📦
This course covers everything from getting started all the way through building a containerized web application and deploying it to the cloud!
Timestamps:
00:00 - Introduction
04:40 - History and motivation
30:27 - Technology overview
40:30 - Installation and set up
47:15 - Using 3rd party container images
48:06 - Understanding container data and docker volumes
1:13:00 - Demo application
1:28:37 - Building container images
2:23:46 - Container registries
2:33:45 - Running containers
3:02:36 - Container security
3:06:58 - Interacting with Docker objects
3:18:36 - Development workflow
3:52:05 - Ephemeral environments with Shipyard
4:07:17 - Deploying containers
4:42:59 - Final wrap up