آموزش کامل پلاگین نویسی در dynamics crm

آموزش پلاگین نویسی در Dynamics CRM

🚀 شروع درس 1 (Foundation واقعی)

🧠 پلاگین یعنی چی؟

در CRM، هر عملیاتی که کاربر انجام می‌دهد یک Event تولید می‌کند.

مثال:

  • Create Account → Event
  • Update Contact → Event
  • Delete Lead → Event

👉 پلاگین یعنی:

کدی که روی این Event سوار می‌شود و اجرا می‌شود.


⚙️ ساختار اجرای ساده

 
User Action

CRM Event

Plugin Executes

CRM Saves Data
 

🧱 3 مفهوم اصلی که باید بفهمی

1. Context (مغز اجرای پلاگین)

 
IPluginExecutionContext context
 

📌 داخلش هست:

  • چه عملیاتی انجام شده
  • روی چه entity
  • چه کسی اجرا کرده

2. Target (داده در حال تغییر)

 
Entity entity = (Entity)context.InputParameters["Target"];
 

📌 یعنی:

رکوردی که کاربر دارد روش کار می‌کند


3. Service (دسترسی به CRM)

 
IOrganizationService service
 

📌 برای:

  • ساخت رکورد
  • آپدیت
  • گرفتن داده

🧪 اولین مثال واقعی

🎯 اگر Account ساخته شد، اسمش تغییر کند:

 
public class SimplePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

if (!context.InputParameters.Contains(“Target”))
return;

var entity = context.InputParameters[“Target”] as Entity;

if (entity == null)
return;

if (entity.LogicalName == “account”)
{
entity[“name”] = “Created by Plugin”;
}
}
}

 

🧠 نکته مهم این درس

✔ پلاگین همیشه روی Event اجرا می‌شود
✔ Target یعنی داده فعلی
✔ Context یعنی اطلاعات اجرای عملیات
✔ Service برای کار با CRM است


❗ قبل از رفتن درس بعد

اگر این 3 چیز رو گرفتی:

  • پلاگین چیست
  • Target چیست
  • Context چیست

👉 آماده‌ای برای درس 2 (Pipeline واقعی و Pre/Post)

📚 درس 2: Pipeline و اجرای واقعی پلاگین (خیلی مهم)

در این درس می‌فهمی پلاگین دقیقاً کِی و چطور داخل CRM اجرا می‌شود و چرا ترتیب اجرا مهم است.

در Microsoft Dynamics 365 Customer Engagement همه پلاگین‌ها داخل یک “Pipeline” اجرا می‌شوند.


🧠 1. Pipeline یعنی چی؟

Pipeline یعنی:

مسیر اجرای عملیات از لحظه درخواست کاربر تا ذخیره در دیتابیس و بعد از آن


⚙️ 2. مراحل Pipeline

 
PreValidation

PreOperation

Main Operation (CRM Core)

PostOperation
 

حالا واقعی و کاربردی توضیح می‌دم 👇


🔵 1. PreValidation (قبل از همه چیز)

📌 چی کار می‌کنه؟

  • قبل از اینکه CRM حتی بررسی جدی انجام بده
  • بدون دیتابیس کامل

📌 کاربرد:

  • چک کردن اجازه‌ها
  • validation سریع

مثال:

 
if (string.IsNullOrEmpty(entity["name"].ToString()))
{
throw new InvalidPluginExecutionException("Name is required");
}
 

👉 یعنی: هنوز چیزی ذخیره نشده، فقط داریم جلوگیری می‌کنیم


🟡 2. PreOperation (مهم‌ترین بخش)

📌 چی کار می‌کنه؟

  • قبل از ذخیره در دیتابیس
  • ولی بعد از validation

📌 قدرت اصلی:

👉 می‌تونی داده را تغییر بدی


🎯 مثال واقعی:

 
entity["name"] = "Modified before save";
 

📌 نتیجه:
این مقدار در دیتابیس ذخیره می‌شود


💡 چرا مهمه؟

چون:
✔ بدون Update اضافه
✔ سریع
✔ مستقیم قبل از ذخیره


🔴 3. Main Operation (Core CRM)

📌 چی هست؟

  • خود CRM داده را ذخیره می‌کند
  • شما اینجا دخالتی نداری

🟢 4. PostOperation (بعد از ذخیره)

📌 چی کار می‌کنه؟

  • بعد از اینکه داده ذخیره شد
  • مناسب برای کارهای جانبی

🎯 مثال واقعی:

 
Entity task = new Entity("task");
task["subject"] = "Account created";
service.Create(task);
 

🧠 تفاوت خیلی مهم (مصاحبه‌ای)

مرحلهتغییر دادهدسترسی به DBکاربرد
PreValidationچک اولیه
PreOperationتغییر داده
Main✔ (CRM)ذخیره
PostOperationعملیات جانبی

⚠️ نکته طلایی

❗ اگر اشتباه انتخاب کنی:

  • PreOperation → تغییر داده
  • PostOperation → ساخت Task / Email
  • PreValidation → فقط چک ساده

🔥 3. ترتیب اجرای چند پلاگین

فرض کن 2 پلاگین داری:

 
Plugin A (PreOperation)
Plugin B (PreOperation)
 

👉 ترتیب اجرا مهم است و ممکن است:

  • باعث اختلاف داده شود
  • یا رفتار غیرمنتظره ایجاد شود

🧠 4. مفهوم Step در CRM

هر پلاگین وقتی ثبت می‌شود یک Step دارد:

📌 Step = اتصال پلاگین به یک Event

مثلاً:

  • Account Create → PreOperation Step

🧪 مثال واقعی کامل این درس

🎯 اگر Account ساخته شد، اسم را تغییر بده (PreOperation)

 
if (entity.LogicalName == "account")
{
entity["name"] = "Pipeline Modified Name";
}
 

👉 این مقدار قبل از ذخیره تغییر می‌کند


🧩 5. خلاصه این درس

✔ Pipeline مسیر اجرای پلاگین است
✔ PreValidation = قبل از همه چیز
✔ PreOperation = تغییر داده قبل از ذخیره
✔ PostOperation = کارهای جانبی بعد از ذخیره
✔ Main = خود CRM

🔥 درس 3:

  • PreImage / PostImage
  • کار واقعی با داده قبلی و جدید
  • Organization Service
  • Retrieve / Query داخل پلاگین

فقط بگو: «درس 3»

 

بریم درس بعد
 

📚 درس 3: کار واقعی با داده‌ها (PreImage + Service + Query)

این درس یکی از مهم‌ترین بخش‌های پلاگین‌نویسی در Microsoft Dynamics 365 Customer Engagement هست، چون از اینجا به بعد وارد “داده واقعی و حرفه‌ای” می‌شیم، نه فقط تغییر ساده فیلد.


🧠 1. مشکل اصلی Update در CRM

وقتی یک رکورد Update می‌شود:

👉 تو فقط مقدار جدید (Target) را داری
❌ مقدار قبلی را نداری


🎯 مثال واقعی:

قبل:

 
Email = A@test.com
 

بعد:

 
Email = B@test.com
 

ولی در پلاگین فقط B را می‌بینی 😐


🟡 2. PreImage چیست؟

📌 تعریف ساده:

یک کپی از داده “قبل از تغییر”


⚙️ استفاده:

 
Entity preImage = (Entity)context.PreEntityImages["PreImage"];
 

🎯 مثال واقعی:

 
string oldEmail = preImage["emailaddress1"].ToString();
string newEmail = entity["emailaddress1"].ToString();

if (oldEmail != newEmail)
{
// email changed
}

 

💡 کاربرد واقعی:

✔ تشخیص تغییر فیلد
✔ لاگ گرفتن
✔ مقایسه قبل و بعد


🟢 3. PostImage چیست؟

📌 تعریف:

داده بعد از انجام عملیات (نسخه نهایی)

📌 بیشتر برای:

  • لاگ نهایی
  • ارسال اطلاعات کامل

⚙️ 4. Organization Service (قلب CRM)

برای کار با دیتابیس از این استفاده می‌کنیم:

 
var factory = (IOrganizationServiceFactory)
serviceProvider.GetService(typeof(IOrganizationServiceFactory));

var service = factory.CreateOrganizationService(context.UserId);

 

📌 این Service چه کار می‌کند؟

✔ Create رکورد
✔ Update رکورد
✔ Retrieve داده
✔ Query


🧪 5. Create رکورد واقعی

🎯 مثال: بعد از Update یک Task بساز

 
Entity task = new Entity("task");
task["subject"] = "Record Updated";
task["description"] = "Created from plugin";

service.Create(task);

 

🔍 6. Query داخل پلاگین (مهم پیشرفته پایه)

🎯 گرفتن داده از CRM:

 
QueryExpression query = new QueryExpression("account");
query.ColumnSet = new ColumnSet("name", "emailaddress1");

query.Criteria.AddCondition(“accountid”, ConditionOperator.Equal, accountId);

EntityCollection result = service.RetrieveMultiple(query);

 

📌 معنی ساده:

👉 “از CRM یک رکورد یا لیست رکورد بگیر”


⚠️ نکته مهم

Query زیاد داخل پلاگین = ❌ Performance بد


🧠 7. تفاوت Target و PreImage

موردTargetPreImage
زمانبعد تغییرقبل تغییر
دادهجدیدقدیمی
کاربردذخیرهمقایسه

🧪 8. مثال واقعی کامل (خیلی مهم)

🎯 اگر Email تغییر کرد → لاگ بساز

 
Entity pre = (Entity)context.PreEntityImages["PreImage"];

string oldEmail = pre.Contains(“emailaddress1”) ? pre[“emailaddress1”].ToString() : “”;
string newEmail = entity.Contains(“emailaddress1”) ? entity[“emailaddress1”].ToString() : “”;

if (oldEmail != newEmail)
{
Entity log = new Entity(“new_log”);
log[“name”] = “Email changed”;
log[“description”] = oldEmail + ” → “ + newEmail;

service.Create(log);
}

 

🧠 9. نکات طلایی این درس

✔ PreImage فقط در Update وجود دارد
✔ Service برای کار با CRM است
✔ Query باید محدود استفاده شود
✔ Target = داده جدید
✔ PreImage = داده قدیمی


🔥 10. چیزی که الان باید بلد باشی

اگر اینو فهمیدی یعنی:

✔ می‌تونی داده قبل و بعد رو مقایسه کنی
✔ می‌تونی رکورد بسازی
✔ می‌تونی از CRM داده بخونی


🚀 آماده‌ای برای درس 4؟

در درس بعدی می‌ریم سراغ چیزهایی که مصاحبه‌گرها عاشقشن:

🔴 درس 4:

  • Depth (جلوگیری از loop واقعی)
  • Trace logging حرفه‌ای
  • Sync vs Async واقعی
  • Performance issues
  • شرط‌های حرفه‌ای پلاگین

📚 درس 4: کنترل‌های حرفه‌ای پلاگین (Depth + Trace + Performance)

این درس جاییه که پلاگین از “کار کردن” تبدیل میشه به “درست کار کردن در پروژه واقعی” در Microsoft Dynamics 365 Customer Engagement.

اینجا چیزهایی رو یاد می‌گیری که جلوی 90٪ باگ‌های واقعی رو می‌گیرن.


🧠 1. مشکل بزرگ در پلاگین‌ها: Loop (Recursion)

❗ سناریو بد:

  1. کاربر یک رکورد Update می‌کند
  2. پلاگین اجرا می‌شود
  3. داخل پلاگین دوباره Update می‌زنی
  4. دوباره پلاگین اجرا می‌شود
  5. دوباره… (بی‌نهایت 😵)

🛑 2. Depth چیست؟

📌 تعریف:

Depth یعنی چند بار این پلاگین در یک زنجیره اجرا شده


🎯 مثال:

 
User Update
→ Plugin (Depth 1)
→ Plugin again (Depth 2)
→ Plugin again (Depth 3)
 

⚙️ جلوگیری از Loop

 
if (context.Depth > 1)
return;
 

💡 معنی ساده:

👉 اگر این پلاگین از داخل خودش اجرا شد → توقف


🧠 3. Trace Service (دیباگ واقعی)

در پروژه واقعی هیچ Console نداری 😐
پس از Trace استفاده می‌کنیم.


⚙️ گرفتن Trace:

 
ITracingService tracing =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
 

🎯 استفاده:

 
tracing.Trace("Plugin started");
tracing.Trace("Account Name: " + entity["name"]);
 

📌 کاربرد واقعی:

✔ پیدا کردن باگ
✔ دیدن جریان اجرای پلاگین
✔ Debug در CRM


⚙️ 4. Sync vs Async Plugin

🔵 Sync (همزمان)

👉 کاربر منتظر می‌ماند

ویژگی‌ها:

  • سریع
  • روی UI تاثیر دارد
  • برای validation و تغییر داده

🟢 Async (غیر همزمان)

👉 بعد از ذخیره اجرا می‌شود

ویژگی‌ها:

  • کاربر منتظر نیست
  • مناسب کارهای سنگین

🎯 مثال:

Sync:

 
Validate + Change Name
 

Async:

 
Send Email + Call API
 

⚠️ 5. Performance Issues (خیلی مهم مصاحبه)

❌ کارهای بد داخل پلاگین:

  • Query زیاد
  • Loop روی رکوردها
  • Call API بیرونی در PreOperation

✔️ قانون طلایی:

پلاگین باید سریع و سبک باشد


🧪 6. شرط‌های حرفه‌ای (Best Practice)

 
if (!context.InputParameters.Contains("Target"))
return;

if (context.MessageName != “Update”)
return;

if (entity == null)
return;

 

🔥 7. مثال واقعی حرفه‌ای

🎯 جلوگیری از اجرا در Depth بالا + Trace + شرط‌ها

 
if (context.Depth > 1)
return;

tracing.Trace(“Plugin started”);

if (context.MessageName == “Update”)
{
Entity entity = (Entity)context.InputParameters[“Target”];

if (entity.Contains(“name”))
{
tracing.Trace(“Name changed: “ + entity[“name”]);
}
}

 

🧠 8. خلاصه این درس

✔ Depth = جلوگیری از loop
✔ Trace = دیباگ واقعی در CRM
✔ Sync = سریع و حساس
✔ Async = سنگین و پس‌زمینه
✔ Performance = مهم‌تر از کد زدن

📚 درس 5: سناریوهای واقعی + معماری حرفه‌ای پلاگین (جمع‌بندی عملی)

این درس، نقطه‌ایه که پلاگین‌نویسی در Microsoft Dynamics 365 Customer Engagement از حالت آموزشی تبدیل میشه به کار واقعی پروژه و مصاحبه سطح بالا.

اینجا یاد می‌گیری:
👉 شرکت‌ها واقعاً از پلاگین چی می‌خوان
👉 چطور طراحی کنی که خراب نشه
👉 و چطور مثل Senior فکر کنی


🧠 1. تفکر واقعی پلاگین در پروژه

پلاگین در شرکت‌ها برای این چیزها استفاده میشه:

  • کنترل بیزنس‌قانون‌ها (Business Rules)
  • اتومات کردن کارها
  • ساخت رکوردهای کمکی
  • جلوگیری از داده اشتباه

🎯 2. سناریو واقعی 1: ساخت Task خودکار

📌 داستان:

وقتی یک Account ساخته شد → یک Task برای Follow-up بساز


⚙️ کد:

 
Entity task = new Entity("task");
task["subject"] = "Follow up new account";
task["description"] = "Auto generated by plugin";

service.Create(task);

 

💡 کاربرد:

✔ Sales team فراموش نکنه مشتری جدید رو پیگیری کنه


🎯 3. سناریو واقعی 2: Validation حرفه‌ای

📌 داستان:

اگر Revenue کمتر از صفر بود → اجازه ذخیره نده


⚙️ کد:

 
if (entity.Contains("revenue"))
{
decimal revenue = ((Money)entity["revenue"]).Value;

if (revenue < 0)
{
throw new InvalidPluginExecutionException(“Revenue cannot be negative”);
}
}

 

💡 نکته:

👉 اینجا پلاگین نقش “Guard” داره


🎯 4. سناریو واقعی 3: لاگ تغییرات

📌 داستان:

اگر ایمیل تغییر کرد → لاگ ثبت کن


⚙️ کد:

 
Entity pre = (Entity)context.PreEntityImages["PreImage"];

string oldEmail = pre.Contains(“emailaddress1”) ? pre[“emailaddress1”].ToString() : “”;
string newEmail = entity.Contains(“emailaddress1”) ? entity[“emailaddress1”].ToString() : “”;

if (oldEmail != newEmail)
{
Entity log = new Entity(“new_log”);
log[“name”] = “Email changed”;
log[“description”] = oldEmail + ” → “ + newEmail;

service.Create(log);
}

 

🧠 5. معماری حرفه‌ای پلاگین (خیلی مهم مصاحبه)

❌ اشتباه رایج:

همه چیز داخل یک کلاس پلاگین


✔️ معماری درست:

 
Plugin Layer

Service Layer

Business Logic Layer

CRM Service Layer
 

📌 معنی ساده:

  • پلاگین فقط “ورودی و خروجی”
  • منطق اصلی داخل Service Class

⚙️ 6. Best Practices (چیزهایی که Senior ها می‌دونن)

✔️ 1. پلاگین سبک باشد

❌ Query سنگین داخل پلاگین ممنوع


✔️ 2. همیشه Depth چک شود

 
if (context.Depth > 1)
return;
 

✔️ 3. از PreImage برای مقایسه استفاده کن


✔️ 4. Exception کنترل شده بده

 
throw new InvalidPluginExecutionException("Invalid data");
 

✔️ 5. فقط کار ضروری داخل پلاگین

👉 نه Business پیچیده


🔥 7. سوالات مصاحبه (خیلی مهم)

❓ چرا پلاگین بهتر از Workflow است؟

✔ سریع‌تر
✔ real-time
✔ کنترل کامل با C#


❓ PreOperation چه مزیتی دارد؟

✔ تغییر داده قبل از ذخیره بدون Update اضافی


❓ Depth چیست؟

✔ جلوگیری از اجرای تکراری (loop)


❓ چه زمانی Async استفاده می‌کنیم؟

✔ کارهای سنگین مثل:

  • Email
  • API call
  • Logging

🧠 8. تصویر ذهنی کامل سیستم

 
User Action

CRM Event

Plugin (Validation / Logic)

Database Save

Post Plugin (Task / Email / Log)
 

🚀 9. جمع‌بندی نهایی

اگر این 5 درس رو گرفتی یعنی:

✔ پلاگین را از صفر می‌فهمی
✔ Pipeline را درک می‌کنی
✔ PreImage و Service را بلدی
✔ از Loop جلوگیری می‌کنی
✔ سناریو واقعی می‌زنی
✔ آماده مصاحبه هستی

⚙️ Sync vs Async (عمیق و واقعی)

🧠 اول تصویر ذهنی درست

 
User Action

CRM Pipeline

Plugin Execution

Database Commit
 

حالا تفاوت Sync و Async فقط “زمان اجرا” نیست، کل تجربه سیستم رو تغییر می‌ده.


🔵 1. Sync Plugin (همزمان)

📌 تعریف واقعی:

پلاگینی که در همان لحظه اجرای عملیات کاربر اجرا می‌شود و کاربر باید منتظر تمام شدن آن بماند.


⚙️ جریان واقعی:

 
User clicks Save

Plugin runs

CRM waits ⏳

Save completes

User sees result
 

🎯 ویژگی‌ها:

✔ اجرا داخل Transaction
✔ کاربر منتظر می‌ماند
✔ اگر خطا بده → کل عملیات Rollback می‌شود
✔ مناسب Business Rules


🧪 مثال واقعی Sync:

 
if (entity.Contains("revenue"))
{
decimal revenue = ((Money)entity["revenue"]).Value;

if (revenue < 0)
{
throw new InvalidPluginExecutionException(“Revenue cannot be negative”);
}
}

 

📌 اینجا:
👉 اگر خطا بده → Save کلاً انجام نمی‌شود


⚠️ نکته مهم:

Sync = “کنترل داده”


🟢 2. Async Plugin (غیرهمزمان)

📌 تعریف واقعی:

پلاگینی که بعد از Commit شدن داده اجرا می‌شود و کاربر منتظر آن نمی‌ماند.


⚙️ جریان واقعی:

 
User clicks Save

CRM saves data ✔

User is done

Async Plugin runs in background
 

🎯 ویژگی‌ها:

✔ بعد از ذخیره اجرا می‌شود
✔ کاربر هیچ تاخیری حس نمی‌کند
✔ مناسب کارهای سنگین
✔ روی Transaction اصلی تاثیر ندارد


🧪 مثال واقعی Async:

 
Entity task = new Entity("task");
task["subject"] = "Send Welcome Email";
task["description"] = "Async plugin triggered";

service.Create(task);

 

🧠 تفاوت واقعی (مصاحبه‌ای)

ویژگیSyncAsync
زمان اجراهمان لحظهبعد از ذخیره
سرعت UIکندترسریع‌تر
Transactionداردندارد
Rollbackداردندارد
کاربردValidationEmail / API

🔥 3. نکته خیلی مهم (90٪ نمی‌دونن)

❗ Sync = Transactional

اگر Sync fail شود:

👉 کل عملیات CRM fail می‌شود


❗ Async = Non-Transactional

اگر Async fail شود:

👉 داده ذخیره شده، فقط عملیات جانبی fail می‌شود


🧠 4. چه زمانی از کدام استفاده کنیم؟

🔵 Sync استفاده کن وقتی:

  • باید جلوی ذخیره داده اشتباه را بگیری
  • Validation داری
  • تغییر داده قبل از ذخیره می‌خواهی

🟢 Async استفاده کن وقتی:

  • Email ارسال می‌کنی
  • API call می‌زنی
  • Log یا Task می‌سازی
  • عملیات سنگین داری

🧪 5. مثال واقعی ترکیبی (خیلی مهم)

🎯 سناریو:

  • Sync: بررسی اعتبار داده
  • Async: ارسال ایمیل

Sync:

 
if (entity.Contains("emailaddress1"))
{
if (string.IsNullOrEmpty(entity["emailaddress1"].ToString()))
{
throw new InvalidPluginExecutionException("Email is required");
}
}
 

Async:

 
Entity email = new Entity("email");
email["subject"] = "Welcome Email";
email["description"] = "Sent after account creation";

service.Create(email);

 

⚠️ 6. اشتباهات رایج (خیلی مهم)

❌ API call در Sync → UI کند می‌شود
❌ Validation در Async → بی‌فایده
❌ Query سنگین در Sync → Performance بد
❌ فکر کردن Async یعنی “بهتر” → غلط


🧠 7. جمع‌بندی ذهنی

🔵 Sync یعنی:

“الان تصمیم بگیر، الان اجرا کن، کاربر منتظر بماند”

🟢 Async یعنی:

“کار اصلی انجام شده، حالا برو کارهای جانبی را انجام بده

🧠 1. ایده اصلی Debug پلاگین

پلاگین مستقیم داخل CRM اجرا میشه، نه داخل Visual Studio.

پس برای Debug باید:

Visual Studio رو به اجرای CRM “وصل” کنی (Attach)


⚙️ 2. ابزار لازم

✔ Visual Studio
✔ Plugin Registration Tool
✔ CRM Environment (Online یا On-Prem)
✔ DLL پلاگین


🧱 3. مراحل Debug واقعی (قدم‌به‌قدم)


🟢 مرحله 1: Build پروژه

در Visual Studio:

 
Build → Build Solution
 

📌 خروجی: DLL


🟢 مرحله 2: Register پلاگین در CRM

با Plugin Registration Tool:

  1. Connect به CRM
  2. Register Assembly (DLL)
  3. Add Step:
    • Message: Create / Update
    • Entity: account
    • Stage: PreOperation یا PostOperation

🟢 مرحله 3: Attach Debugger

در Visual Studio:

 
Debug → Attach to Process
 

📌 انتخاب Process:

اگر On-Prem:

 
w3wp.exe
 

اگر Online:

 
Plugin Registration Tool Debug (Sandbox)
 

🔥 4. حالا Breakpoint بزن

 
public void Execute(IServiceProvider serviceProvider)
{
// 🔴 Breakpoint اینجا بزن
 

📌 وقتی CRM event اجرا شود → Visual Studio توقف می‌کند


🧠 5. Debug واقعی چه اتفاقی می‌افتد؟

 
User clicks Save

CRM triggers plugin

Visual Studio hits breakpoint

You inspect variables

Step over / Step into
 

🧪 6. بررسی داده‌ها (خیلی مهم)

وقتی breakpoint خورد:

بررسی Context:

 
context.MessageName
context.Depth
context.UserId
 

بررسی Target:

 
entity["name"]
entity["emailaddress1"]
 

🧠 7. ابزارهای Debug داخل VS

✔ Step Over (F10)

→ خط بعدی

✔ Step Into (F11)

→ داخل متدها

✔ Step Out (Shift+F11)

→ خروج از متد


⚠️ 8. مشکلات رایج Debug

❌ Breakpoint کار نمی‌کند؟

دلایل:

  • DLL جدید Deploy نشده
  • Step ثبت نشده
  • Process اشتباه انتخاب شده

❌ تغییرات اعمال نمی‌شود؟

👉 CRM هنوز نسخه قبلی DLL را دارد

✔ حل:

  • Unregister
  • دوباره Register Assembly

🔥 9. Debug حرفه‌ای با Trace (خیلی مهم)

در کنار breakpoint:

 
ITracingService tracing =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));

tracing.Trace(“Reached step 1”);
tracing.Trace(“Entity Name: “ + entity[“name”]);

 

📌 این داخل CRM Log هم ذخیره می‌شود


🧠 10. سناریو واقعی Debug

🎯 مشکل:

“پلاگین اجرا نمی‌شود”

بررسی‌ها:

  1. Step register شده؟
  2. Message درست هست؟ (Create / Update)
  3. Entity درست هست؟
  4. Plugin assembly درست deploy شده؟

🧪 11. Debug حرفه‌ای (Real trick)

اگر breakpoint نمی‌خورد:

 
→ Use tracing first
→ Check Plugin Execution Log
→ Then attach debugger
 

🧠 12. نکته طلایی مصاحبه

اگر ازت بپرسن:

❓ چطور پلاگین رو debug می‌کنی؟

✔ جواب حرفه‌ای:

با استفاده از Plugin Registration Tool پلاگین را deploy می‌کنم، سپس Visual Studio را به process مربوط به CRM attach می‌کنم و breakpoint می‌گذارم و با استفاده از ITracingService جریان اجرا را بررسی می‌کنم.


🚀 جمع‌بندی واقعی

Debug پلاگین یعنی:

✔ Attach کردن VS به CRM process
✔ استفاده از breakpoint
✔ بررسی Context و Target
✔ استفاده از Trace برای دید بهتر
✔ بررسی Step registration

🌐 1. Web API Call از داخل Plugin یعنی چی؟

یعنی:

داخل پلاگین، از C# استفاده می‌کنی تا به یک API خارجی یا داخلی HTTP request بزنی.

📌 مثال‌ها:

  • ارسال داده به یک سیستم حسابداری
  • گرفتن نرخ ارز
  • ارسال پیام به Telegram / Email service
  • اتصال به یک Microservice

🧠 2. چرا اصلاً از Plugin به API call می‌زنیم؟

در CRM:

  • Business logic داریم
  • ولی بعضی کارها بیرون CRM هست

🎯 مثال واقعی:

وقتی Account ساخته شد:

  • باید به ERP ارسال شود
  • یا در سیستم دیگر ثبت شود

⚙️ 3. روش کلی کار

 
CRM Plugin

HTTP Request

External API

Response

CRM (optional action)
 

🧱 4. کد پایه Web API call

در پلاگین معمولاً از HttpClient استفاده می‌شود:

 
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
 

🎯 مثال ساده (POST request)

 
HttpClient client = new HttpClient();

string url = “https://example.com/api/data”;

var json = “{\”name\”:\”test\”}”;

HttpContent content = new StringContent(json, Encoding.UTF8, “application/json”);

HttpResponseMessage response = client.PostAsync(url, content).Result;

string result = response.Content.ReadAsStringAsync().Result;

 

⚠️ 5. نکته خیلی مهم (مصاحبه‌ای)

❌ استفاده از .Result یا .Wait() در CRM خطرناک است

چون:

  • ممکن است Thread را block کند
  • Performance را خراب کند

🟡 6. Sync vs Async در API Call

🔵 Sync Plugin + API Call

❌ بدترین حالت

  • کاربر منتظر می‌ماند
  • اگر API کند باشد → CRM کند می‌شود

🟢 Async Plugin + API Call ⭐ BEST

✔ کاربر منتظر نمی‌ماند
✔ API در background اجرا می‌شود
✔ مناسب integration ها


🧠 7. مثال واقعی حرفه‌ای

🎯 سناریو:
وقتی Account ساخته شد → به سیستم خارجی ارسال شود

 
HttpClient client = new HttpClient();

string url = “https://external-system/api/account”;

string json = “{\”name\”:\”” + entity[“name”] + “\”}”;

HttpContent content = new StringContent(json, Encoding.UTF8, “application/json”);

HttpResponseMessage response = client.PostAsync(url, content).Result;

if (!response.IsSuccessStatusCode)
{
throw new InvalidPluginExecutionException(“API call failed”);
}

 

⚠️ 8. مشکلات واقعی (خیلی مهم)

❌ 1. Timeout

API کند باشد → CRM hang می‌کند


❌ 2. Retry ندارد

اگر API fail شود → باید خودت مدیریت کنی


❌ 3. Security

نباید API Key را hardcode کنی


🧠 9. Best Practice حرفه‌ای

✔ استفاده از Async Plugin
✔ استفاده از Configuration Entity برای API URL
✔ مدیریت Exception
✔ محدود کردن timeout


🎯 مثال بهتر:

 
client.Timeout = TimeSpan.FromSeconds(5);
 

🔥 10. معماری درست (Enterprise View)

 
Plugin

Integration Layer

HTTP Client

External API

Response Handler
 

📌 نکته مهم:
👉 API call نباید مستقیم داخل business logic سنگین باشد


🧠 11. چه زمانی API call در Plugin بد است؟

❌ وقتی:

  • Sync Plugin باشد
  • API کند باشد
  • حجم درخواست زیاد باشد

🟢 12. بهترین حالت واقعی

✔ Async Plugin
✔ Queue-based integration (در پروژه‌های بزرگ)
✔ Retry mechanism
✔ Logging کامل


🧪 13. نکته مصاحبه‌ای طلایی

❓ آیا API call در Plugin خوب است؟

✔ جواب حرفه‌ای:

بله، اما فقط در Async plugin یا با طراحی مناسب، چون در Sync plugin می‌تواند باعث performance issue و blocking در CRM pipeline شود.


🚀 جمع‌بندی

Web API call در Plugin یعنی:

✔ اتصال CRM به سیستم‌های خارجی
✔ استفاده از HttpClient
✔ ترجیحاً Async
✔ مدیریت خطا و timeout
✔ طراحی درست برای جلوگیری از کندی CRM

اشتراک گذاری :

نوشتن دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

نوشتن دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *