مطالب
راه‌های کم کردن احتمال اسپم شدن ایمیل‌های ارسالی توسط SMTP Client
1. فرستادن ایمیل‌ها با وقفه زمانی
2. نفرستادن پشت سر ایمیل‌ها به یک host خاص
3. استفاده نکردن از کلمه هایی که احتمال اسپم شناخته شدن ایمیل را افزایش می‌دهند در قسمت Subject Email
در  لینک‌های  زیر لیست بعضی از این کلمات را می‌توانید مشاهده کنید:
http://blog.hubspot.com/blog/tabid/6307/bid/30684/The-Ultimate-List-of-Email-SPAM-Trigger-Words.aspx 
http://www.inmotionhosting.com/support/edu/everything-email/spam-prevention-techniques/common-spam-words 

4. فعال نکردن high priority
با فعال شدن این گزینه ایمیل شما مورد بررسی‌های بیشتری قرار می‌گیرد و شانس اسپم شناخته شدن آنرا افزایش می‌دهد.
mailMessage.Priority = MailPriority.High ; //not good

5. Set کردن Encoding  صحیح
mailMessage.BodyEncoding = System.Text.Encoding.GetEncoding(“utf-8″);

6. استفاده از حداکثر سه  image در متن ایمیل
7. اضافه کردن هم htmlview و هم plainview به view  ایمیل ارسالی

با مثال نحوه این کار را نشان می‌دهم:
 System.Net.Mail.AlternateView plainView = System.Net.Mail.AlternateView.CreateAlternateViewFromString
System.Text.RegularExpressions.Regex.Replace(BodyText, @”<(.|\n)*?>”, string.Empty), null, “text/plain”);
System.Net.Mail.AlternateView htmlView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(BodyText, null, “text/html”);
mailMsg.AlternateViews.Add(plainView);
mailMsg.AlternateViews.Add(htmlView);

منابع:
http://stackoverflow.com/questions/5042309/email-messages-going-to-spam-folder 
http://www.andreas-kraus.net/blog/tips-for-avoiding-spam-filters-with-systemnetmail/
 
مطالب
خلاصه اشتراک‌های روز پنج شنبه 28 مهر 1390

  • Roslyn CTP | Kirill Osenkov - MSFT | blogs.msdn.com
  • Windows Server 8 | Bill Laing, Manlio Vecchiet, Max Herrmann, Mike Neil | channel9.msdn.com
مطالب
واکشی اولیه در HTML5 Prefetching - HTML5
در HTML5 قابلیت‌های زیادی برای بهبود در سرعت نمایش و عملکرد سایت‌ها در نظر گرفته شده؛ یکی از این قابلیت‌های جالب، Prefetching  یا واکشی اولیه است. 
خب بزارید سناریو رو اینطور مطرح کنم: فرض کنید یک بازدید کننده به سایت شما مراجعه میکنه "abc.htm" و شما به عنوان یک طراح وب میدونید که بازدید کننده پس از مطالعه این صفحه به صفحه دیگه ای از سایت باید مراجعه کنه، به عنوان مثال "xyz.htm". با استفاده از قابلیت واکشی اولیه میشه مرورگر رو مجبور کرد که در زمانی که کاربر مشغول مشاهده، خواندن و یا گشت و گذار تو صفحه‌ی مورد نظر ماست، بیاد صفحات دیگری که برای اون مشخص میکنیم رو در پس زمینه بارگذاری کنه. با این عمل وقتی که کاربر، صفحه ما رو به سمت صفحات کش شده ترک میکنه، صفحات مورد نظر با سرعت فوق العاده ای نمایش داده میشن؛ دلیلش هم اینه که تمام اطلاعات صفحات کش شده توسط مرورگر دانلود شده و آماده نمایشه.

برای استفاده از این قابلیت باید در بخش head سایتمون یک لینک به صورت زیر به صفحه و یا تصویر مورد نظری که میخوایم کش بشه، قرار بدیم:
<link rel="prefetch" href="http://www.example.com/page2.aspx"> <!-- Firefox -->
<link rel="prerender" href="http://www.example.com/page2.aspx"> <!-- Chrome -->

یا

<link rel="prefetch" href="http://www.example.com/picture.jpg"> <!-- Firefox -->
<link rel="prerender" href="http://www.example.com/picture.jpg"> <!-- Chrome -->
همونطور که ملاحظه میکنید این قابلیت در حال حاضر فقط توسط دو مرورگر محبوب وب یعنی کروم و فایرفاکس پشتیبانی میشه و مرورگرهای دیگه با رسیدن به این خطوط از کش کردن اون صرف نظر میکنن.

نکته:

و در انتها لازمه به این نکته توجه کنید که وقتی صفحه ای از سایت ما که حاوی لینک های prefetch هست لود میشه، بلافاصله مرورگر شروع به گرفتن لینک‌های مورد نظر میکنه و اگر در سمت سرور در هنگام لود شدن صفحات کدی نوشته باشید اون کد اجرا میشه. توجه به این نکته میتونه از گیج شدن شما  در هنگام کار با متغیر هایی که توی session ذخیره میشن جلوگیری کنه!
مطالب
فراخوانی GraphQL API در یک کلاینت Angular
در قسمت‌های قبل ( ^  ، ^ و  ^ ) GraphQL  را در ASP.Net Core راه اندازی کردیم و در قسمت ( فراخوانی GraphQL API در یک کلاینت ASP.NET Core  ) از GraphQL API  فراهم شده در یک کلاینت ASP Net Core  استفاده کردیم. اکنون می‌خواهیم چگونگی استفاده از GraphQL را در انگیولار، یاد بگیریم.
Apollo Angular، به شما اجازه میدهد داده‌ها را از یک سرور GraphQL دریافت و از آن برای ساختن UI ‌های واکنشی و پیچیده در انگیولار استفاده کنید. وقتی که از Apollo Client استفاده می‌کنیم، نیازی نیست هیچ چیز خاصی را در مورد سینتکس query ‌ها یادبگیریم؛ به دلیل اینکه همه چیز همان استاندارد GraphQL می‌باشد. هر چیزی را که شما در GraphQL query IDE تایپ می‌کنید، می‌توانید آن‌ها را در کد‌های Apollo Client نیز قرار دهید.

Installation with Angular Schematics 
 
بعد از ایجاد یک پروژه انگیولار با دستور زیر
ng new apollo-angular-project
در ترمینال VS Code  دستور زیر را وارد نمایید: 
ng add apollo-angular
تنها کاری که بعد از اجرای دستور بالا نیاز است انجام دهیم، تنظیم آدرس سرور GraphQL می‌باشد. از این رو فایل graphql.module.ts را باز کنید و متغیر uri را مقدار دهی کنید.
const uri = 'https://localhost:5001/graphql';
اکنون همه چیز تمام شده‌است. شما می‌توانید اولین query خود را اجرا کنید. 

Installation without Angular Schematics 

اگر می‌خواهید Apollo را بدون کمک گرفتن از Angular Schematics نصب کنید، در ابتدا کتابخانه‌های زیر را نصب نمائید:
npm install --save apollo-angular \
  apollo-angular-link-http \
  apollo-link \
  apollo-client \
  apollo-cache-inmemory \
  graphql-tag \
  graphql
کتابخانه apollo-client نیازمند AsyncIterable می‌باشد. به همین جهت مطمئن شوید فایل tsconfig.json شما به صورت زیر است:
{
  "compilerOptions": {
    // ...
    "lib": [
      "es2017",
      "dom",
      "esnext.asynciterable"
    ]
  }
}
اکنون شما تمام وابستگی‌های مورد نیاز را دارید. سپس می‌توانید اولین Apollo Client خود را اجرا کنید. 
در ادامه، فایل app.module.ts را باز کرده و آن را مطابق زیر ویرایش کنید:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HttpClientModule } from "@angular/common/http";
import { ApolloModule, APOLLO_OPTIONS } from "apollo-angular";
import { HttpLinkModule, HttpLink } from "apollo-angular-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";


@NgModule({
  declarations:
    [
      AppComponent
    ],
  imports:
    [
      BrowserModule,
      HttpClientModule,
      ApolloModule,
      HttpLinkModule
    ],
  providers:
    [
      {
        provide: APOLLO_OPTIONS,
        useFactory: (httpLink: HttpLink) => {
          return {
            cache: new InMemoryCache(),
            link: httpLink.create({
              uri: "https://localhost:5001/graphql"
            })
          }
        },
        deps:
          [
            HttpLink
          ]
      }],
  bootstrap:
    [
      AppComponent
    ]
})
export class AppModule { }
چه کاری در اینجا انجام شده است:
- با استفاده از سرویس apollo-angular-link-http و HttpLink، کلاینت را به یک سرور GraphQL متصل می‌کنیم. 
- apollo-cache-inmemory و InMemoryCache محلی برای ذخیره سازی داده‌ها می‌باشد. 
- APOLLO_OPTIONS فراهم کننده تنظیمات Apollo Client است.
- HttpLink نیاز به HttpClient دارد. به همین خاطر است که ما از HttpClientModule استفاده کرده‌ایم. 

Links and Cache 
 Apollo Client، یک لایه واسط شبکه قابل تعویض را دارد که به شما اجازه می‌دهد تا تنظیم کنید که چگونه query ‌ها در HTTP ارسال شوند؛ یا کل بخش Network را با چیزی کاملا سفارشی سازی شده جایگزین کنید؛ مثل یک websocket transport.
apollo-angular-link-http : از Http  برای ارسال query ‌ها استفاده می‌کند. 
apollo-cache-inmemory : پیاده سازی کش پیش فرض برای Apollo Client 2.0 می‌باشد. 
 
نکته
 Apollo یک سرویس export شده انگیولار از apollo-angular، برای به اشتراک گذاشتن داده‌های GraphQL با UI شما می‌باشد.

شروع کار
به همان روش که فایل‌های Model را برای کلاینت ASP.NET Core ایجاد کردیم، در اینجا هم ایجاد می‌کنیم. کار را با ایجاد کردن یک پوشه جدید به نام types، شروع می‌کنیم و چند type را در آن تعریف خواهیم کرد ( OwnerInputType ،AccountType  و OwnerType ):
export type OwnerInputType = {
    name: string;
    address: string;
}
export type AccountType = {
    'id': string;
    'description': string;
    'ownerId' : string;
    'type': string;
}
import { AccountType } from './accountType';
 
export type OwnerType = {
    'id': string;
    'name': string;
    'address': string;
    'accounts': AccountType[];
}

سپس یک سرویس را به نام graphql ایجاد می‌کنیم: 
ng g s graphql
و آن را همانند زیر ویرایش می‌کنیم: 
import { Injectable } from '@angular/core';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';

@Injectable({
  providedIn: 'root'
})
export class GraphqlService {

  constructor(private apollo: Apollo) { }
  
}
اکنون همه چیز آماده است تا تعدادی query و mutation را اجرا کنیم ( providedIn ).

بازیابی تمامی Owner ها 
سرویس graphql  را باز می‌کنیم و آن را همانند زیر ویرایش می‌کنیم ( اضافه کردن متد getOwners ):
  public getOwners = () => {
    return this.apollo.query({
      query: gql`query getOwners{
      owners{
        id,
        name,
        address,
        accounts{
          id,
          description,
          type
        }
      }
    }`
    });
  }

سپس فایل app.component.ts را باز کرده و همانند زیر ویرایش می‌کنیم: 
export class AppComponent implements OnInit {

  public owners: OwnerType[];
  public loading = true;

  constructor(private graphQLService: GraphqlService) { }

  ngOnInit() {
    this.graphQLService.getOwners().subscribe(result => {
      this.owners = result.data["owners"] as OwnerType[];
      this.loading = result.loading;
    });
  }
}

و هم چنین app.component.html:
<div>
    <div *ngIf="!this.loading">
        <table>
            <thead>
                <tr>
                    <th>
                        #
                    </th>
                    <th>
                        نام و نام خانوادگی
                    </th>
                    <th>
                        آدرس
                    </th>
                </tr>
            </thead>

            <tbody>
                <ng-container *ngFor="let item of this.owners;let idx=index" [ngTemplateOutlet]="innertable"
                    [ngTemplateOutletContext]="{item:item, index:idx}"></ng-container>
            </tbody>

        </table>
    </div>
    <div *ngIf="this.loading">
        <p>
            در حال بارگذاری لیست ...
        </p>
    </div>
</div>


<ng-template #innertable let-item="item" let-idx="index">
    <tr>
        <td>{{idx+1}}</td>
        <td>{{item.name}}</td>
        <td>{{item.address}}</td>
    </tr>
    <tr *ngIf="this.item.accounts && this.item.accounts.length > 0">
        <td colspan="4">
            <div>
                <p>Accounts</p>
            </div>
            <div>
                <table>
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>نوع</th>
                            <th>توضیحات</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let innerItem of this.item.accounts;let innerIndex=index">
                            <td>
                                {{innerIndex+1}}
                            </td>
                            <td>
                                {{innerItem.type}}
                            </td>
                            <td>
                                {{innerItem.description}}
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </td>
    </tr>
</ng-template>
اکنون جهت اجرای پروژه، کد‌های ضمیمه شده در پایان قسمت ( GraphQL Mutations در ASP.NET Core ( عملیات POST, PUT, DELETE ) ) را دانلود نمایید و آن را اجرا کنید: 
dotnet restore
dotnet run
سپس پروژه را اجرا کنید: 
ng serve

خروجی به صورت زیر می‌باشد (لیست تمامی Owner ‌ها به همراه Account‌های مربوط به هر Owner):


در متد getOwner، بجای apollo.query می‌توان از apollo.watchQuery استفاده کرد که در نمونه زیر، در ابتدا، GraphQL query را در تابع gql ( از graphql-tag ) برای خصوصیت query در متد apollo.watchQuery پاس میدهیم.
  public getOwners = () => {
    return this.apollo.watchQuery<any>({
      query: gql`query getOwners{
        owners{
          id,
          name,
          address,
          accounts{
            id,
            description,
            type
          }
        }
      }`
    })
  }

و سپس در کامپوننت:
export class AppComponent implements OnInit {

  loading: boolean;
  public owners: OwnerType[];

  private querySubscription: Subscription;

  constructor(private graphQLService: GraphqlService) { }

  ngOnInit() {
    this.querySubscription = this.graphQLService.getOwners()
      .valueChanges
      .subscribe(result => {
        this.loading = result.loading;
        this.owners = result.data["owners"] as OwnerType[];
      });
  }

  ngOnDestroy() {
    this.querySubscription.unsubscribe();
  }
}
متد watchQuery، شیء QueryRef را برگشت می‌دهد که خصوصیت valueChanges را دارد که آن یک Observable می‌باشد. Observable تنها یک بار صادر خواهد شد و آن زمانی است که query کامل می‌شود و خصوصیت loading به false  تنظیم خواهد شد؛ مگر اینکه شما پارامتر notifyOnNetworkStatusChange را در watchQuery  به true  تنظیم کنید. شیء منتقل شده از طریق یک Observable، شامل خصوصیات loading ،error و data است. هنگامی که نتیجه query برگشت داده می‌شود، به خصوصیت data انتساب داده می‌شود. 
 


مابقی query ‌ها و mutation ها از سرویس graphql
بازیابی یک Owner  مشخص 

  public getOwner = (id) => {
    return this.apollo.query({
      query: gql`query getOwner($ownerID: ID!){
      owner(ownerId: $ownerID){
        id,
        name,
        address,
        accounts{
          id,
          description,
          type
        }
      }
    }`,
      variables: { ownerID: id }
    })
  }

ایجاد یک Owner جدید 
  public createOwner = (ownerToCreate: OwnerInputType) => {
    return this.apollo.mutate({
      mutation: gql`mutation($owner: ownerInput!){
        createOwner(owner: $owner){
          id,
          name,
          address
        }
      }`,
      variables: { owner: ownerToCreate }
    })
  }

ویرایش یک Owner 
  public updateOwner = (ownerToUpdate: OwnerInputType, id: string) => {
    return this.apollo.mutate({
      mutation: gql`mutation($owner: ownerInput!, $ownerId: ID!){
        updateOwner(owner: $owner, ownerId: $ownerId){
          id,
          name,
          address
        }
      }`,
      variables: { owner: ownerToUpdate, ownerId: id }
    })
  }

و در نهایت حذف یک Owner
  public deleteOwner = (id: string) => {
    return this.apollo.mutate({
      mutation: gql`mutation($ownerId: ID!){
        deleteOwner(ownerId: $ownerId)
       }`,
      variables: { ownerId: id }
    })
  }
اکنون شما می‌توانید با ویرایش کردن فایل app.component.ts یا ایجاد کردن کامپوننت‌های جدید، از نتایج بدست آمده استفاده کنید.


کد‌های کامل این قسمت را از ایجا دریافت کنید : GraphQL_Angular.zip
کد‌های کامل قسمت ( GraphQL Mutations در ASP.NET Core ( عملیات POST, PUT, DELETE ) ) را از اینجا دریافت کنید :  ASPCoreGraphQL_3.rar  
نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 14 - لایه بندی و تزریق وابستگی‌ها
با سلام؛ زمانیکه از  کد زیر برای جدول blog استفاده می‌کنیم، موقع استفاده، کل جدول رو برامون اطلاعاتش رو میاره. مثلا جدولی که ده هزار رکورد داره رو برام میاره. در صورتیکه نیاز ندارم. حالا نمیدونم من اشتباه مسیر رو رفتم یا واقعا همینطوریه؟
_blogs = _uow.Set<Blog>();
 public BlogService(IUnitOfWork uow)
        {
            _uow = uow;
            _blogs = _uow.Set<Blog>();
        }
مطالب
آشنایی با الگوی M-V-VM‌- قسمت اول

در مورد الگوی MVVM پیشتر دو مطلب در این سایت منتشر شده‌اند : + و +
مشکل عمده‌ای هم که در مورد این الگو وجود دارد کمبود منابع آموزشی آن به زبان ساده است. هر چند این الگو از طرف خود مایکروسافت ارائه شده اما همانند ASP.Net MVC به آن پر و بال ندادند و شاهد چند ده کتاب منتشر شده در مورد آن نیستیم.
به همین جهت خلاصه‌ای چند قسمتی را در این مورد تهیه کرده‌ام که در طی روزهای آتی ارائه خواهند شد.

فهرست قسمت اول:
  • M-V-VM چیست؟
  • آشنایی با اجزای مختلف الگوی M-V-VM
  • مزایای استفاده از الگوی M-V-VM
  • اصول کاری و بایدها و نبایدهای الگوی M-V-VM
  • بایدها و نبایدهای یک View
  • بایدها و نبایدهای ViewModel
  • بایدها و نبایدهای Model
  • مروری بر معایب الگوی M-V-VM



لینک کمکی دریافت این سری 
بازخوردهای دوره
تزریق وابستگی‌ها در حالتی‌که از یک اینترفیس چندین کلاس مشتق شده‌اند
با سلام 
 کلاس UsersManagerService  که داره اینترفیس IUsersManagerService رو پیاده سازی می‌کنه ، اگر روزی فرضا یه سرویس دیگه مثل Sms و ایمیلی که الان توی کلاس هست به سیستم اضافه شد به نظر میاد که باید اون رو هم مثل اینها توی سازنده کلاس اضافه کرد و در هر حال کلاس ما دچار تغییر میشه .این آیا نقض OpenClose Responsibility و SRP نیست ؟
اشتراک‌ها
بررسی ویژگی‌های جدید ECMAScript 2020

چند روزی میشه که نسخه‌ی پایدار Node.js به نسخه‌ی v14 بروزرسانی شده. با این بروزرسانی علاوه بر بهبود‌های مختلف ما می‌تونیم از ویژگی‌های ECMAScript 2020توی کدهامون به صورت پایدار استفاده کنیم. این کار کمکمون میکنه که کدهای بهتر و پایدارتری بنویسیم. 

بررسی ویژگی‌های جدید ECMAScript 2020
اشتراک‌ها
ماهنامه سلام دنیا، شماره 8

این ماهنامه با محوریت BSD تدارک دیده شده است.

  • مرد حرف باز
  • فیسبوک و رویکرد متن باز
  • پیدایش BSD
  • سیستم عامل‌های مبتنی بر BSD
  • روزی که مدیر سیستم‌ها بر زمین حکم راندند (۲)
ماهنامه سلام دنیا، شماره 8
اشتراک‌ها
مفهوم داده‌های بزرگ برای کسب‌وکار
«داده‌های بزرگ» مفهومی است که در بازارهای امروز رواج زیادی یافته است . اما از آنجایی که این مفهوم ممکن است برای بسیاری از افراد گیج‌کننده باشد، برای بسیاری دیگر پولساز است. 
روزی می‌رسد که همه داده‌ها به داده‌های بزرگ تبدیل خواهند شد. جمع‌آوری، پردازش و تحلیل حجم بالای داده‌های ساختاربندی شده و بدون ساختار در مدت زمان کم، رویکردهای منحصر به فردی را برای ما به وجود می‌آورد و شاید امکان پیش‌بینی آینده نیز فراهم شود. 
مفهوم داده‌های بزرگ برای کسب‌وکار