مطالب
فعال سازی قسمت ارسال فایل و تصویر ویرایشگر آنلاین RedActor در ASP.NET MVC
در سایت جاری از ویرایشگر آنلاین RedActor استفاده شده و کار کردن با آن هم بسیار ساده است:
یک TextArea ساده را به صفحه اضافه کرده و این افزونه جی‌کوئری را بر روی آن اجرا می‌کنید. به این ترتیب TextArea به صورت خودکار تبدیل به یک ویرایشگر مطلوب خواهد شد. برای مثال:
@Html.TextAreaFor(model => model.ArticleBody, htmlAttributes: new { style = "width:98%; height:500px" })

<script type="text/javascript">
$('#ArticleBody').redactor({
                autoformat: false,
                convertDivs: false
            });
</script>
اما فعال سازی قسمت ارسال فایل و تصویر همراه با آن چطور؟
یک سری مثال نوشته شده با PHP به همراه این ویرایشگر آنلاین هستند که برای ایده گرفتن بد نیستند (البته به این معنا نیست که این ویرایشگر نیازی به PHP دارد. تنها قسمت سمت سرور مثال‌های آن با PHP است). برای مثال اگر در PHP از دستور echo برای ارائه یک نتیجه نهایی به ویرایشگر RedActor استفاده شده، معادل آن در ASP.NET MVC مساوی return Content است.
<script type="text/javascript">
$('#ArticleBody').redactor({
                imageUpload: "@Url.Action(result: MVC.RedactorUpload.ImageUpload())",
                fileUpload: "@Url.Action(result: MVC.RedactorUpload.FileUpload())",
                linkFileUpload: "@Url.Action(result: MVC.RedactorUpload.FileLinkUpload())"
                , autoformat: false
                , convertDivs: false
            });
</script>
برای فعال سازی قسمت آپلود این ادیتور نیاز است پارامترهای imageUpload، fileUpload و linkFileUpload مقدار دهی شوند.
همانطور که ملاحظه می‌کنید از T4MVC برای مشخص سازی مسیرها استفاده شده. برای مثال MVC.RedactorUpload.ImageUpload به این معنا است که در کنترلری به نام RedactorUpload، اکشن متدی به نام ImageUpload پذیرای ارسال فایل ادیتور خواهد بود و به همین ترتیب در مورد سایر پارامترها.
RedactorUploadController هم ساختار بسیار ساده‌ای دارد. برای مثال هر کدام از متدهای آپلود یاد شده یک چنین امضایی دارند:
[HttpPost]
public virtual ActionResult ImageUpload(HttpPostedFileBase file)
{
}
البته در مورد مسایل امنیتی آپلود هم پیشتر در سایت بحث شده است. برای مثال در اینجا استفاده از فیلتر زیر را فراموش نکنید:
 [AllowUploadSpecialFilesOnly(".jpg,.gif,.png")]
در هر کدام از متدهای آپلود (به سه متد برای سه پارامتر یاد شده نیاز است)، ابتدا HttpPostedFileBase را در پوشه‌ایی که مدنظر دارید ذخیره کنید. سپس باید محتوایی را به RedActor بازگشت دهید و اصل کار یکپارچگی با ASP.NET MVC نیز در همینجا است:
در حالت imageUpload، محتوایی به شکل زیر باید بازگشت داده شود:
 return Content("<img src='" + path + "' />");
در حالت fileUpload، پس از ذخیره سازی فایل در سرور، مسیر آن باید به نحو زیر بازگشت داده شود:
 return Content("<a href=" + path + ">" + someName + "</a>");
و در حالت linkFileUpload فقط باید مسیر نهایی فایل ذخیره شده بر روی سرور را بازگشت دهید:
 return Content(path);

همچنین باید دقت داشت که کار ارسال فایل به سرور توسط خود افزونه RedActor انجام می‌شود و نیازی به کدنویسی ندارد. فقط باید سمت سرور آن‌را به نحوی که عنوان شد مدیریت کنید. ابتدا فایل را در سرور ذخیره کنید. سپس باید یک محتوای رشته‌ای را به نحو یاد شده، ساخت و توسط return Content بازگشت داد.

پ.ن.
قسمتی از مطالب متن فوق در نگارش جدید این ویرایشگر به نحو زیر تغییر کرده است.
مطالب
آشنایی با Catel MVVM Frameowork
در این مقاله به بررسی اولیه فریمورک Catel و برخی ویژگی‌های آن خواهیم پرداخت.
همانطور که می‌دانید فریمورک‌های متعددی برای MVVM به وجود آمده اند، مانند MVVM Light یا Caliburn و Chinch و ... که هر کدام از آن‌ها دارای ویژگی هایی می‌باشند اما Catel تنها یک فریمورک برای MVVM نیست بلکه دارای قسمت‌های دیگری مانند کنترل‌های اختصاصی و سرویس‌های متعدد و پرکاربرد و Extension‌‌های مفید و ... نیز می‌باشد که کار توسعه یک برنامه MVVM را فوق العاده لذتبخش می‌کند.
برای شروع کار با این فریمورک ابتدا بایستی قالب پروژه را از این آدرس دریافت نمایید. بعد از دریافت و نصب آن یک زیرگروه جدید به نام Catel به قسمت افزودن پروژه جدید اضافه خواهد شد که شامل قالب پروژه برای WPF و Silverlight و Windows Phone و Windows Store می باشد. در این قسمت گزینه WPF Application with Catel را انتخاب نمایید و پروژه را ایجاد کنید. بعد از ایجاد پروژه نوبت به نصب بسته های nuget مورد نیاز Catel می رسد. تنها بسته مورد نیاز Catel.Extensions.Controls می باشد که به صورت خودکار بسته های Catel.MVVM و Catel.Core را نیز نصب خواهد کرد. البته بسته‌های دیگری مانند Catel.Extensions.Prism, Catel.Extensions.FluentValidation و Catel.Extensions.Data و Catel.Fody و ... نیز برای این فریمورک وجود دارد که در این مطلب به آن‌ها نیازی نداریم.
اکنون ساختار اصلی پروژه ما ایجاد شده است. در این ساختار پوشه‌های Models ،Views و ViewModels به صورت پیش فرض وجود دارند. Catel برای برقراری ارتباط بین View و ViewModel از IViewLocator، IViewModelLocator و یکسری قواعد نام گذاری پیروی میکند تا نیاز به رجیستر کردن تک تک ویوها و ویومدل‌ها به صورت دستی نباشد که البته این قواعد قابل تغییر و شخصی سازی هستند. قرارداد پیش فرض برای پروژه‌های کوچک ممکن است مناسب باشد ولی در پروژه‌های بزرگ نیاز به سفارشی سازی دارد که در قسمت‌های بعد به آن خواهیم پرداخت. 
View و ViewModel:

برای ایجاد یک ViewModel جدید، باید از منوی Add New Item قسمت Catel گزینه (ViewModel (Catel را انتخاب نمایید. با توجه به code snippet های تهیه شده برای این فریمورک، کار تهیه ViewModel‌ها فوق العاده سریع انجام می‌شود. به عنوان مثال برای اضافه کردن یک Command در ویومدل، از vmcommand و یا vmcommandwithcanexecute و برای ایجاد پروپرتی هم از vmprop و vmpropchanged میتوان استفاده نمود. همانطور که ملاحظه می‌کنید نام این snippet‌‌ها کاملا واضح می‌باشد و نیاز به توضیح اضافی ندارند.
همینطور برای ایجاد یک View گزینه (DataWindow (WPF with Catel را انتخاب نمایید. ViewModel‌‌‌ها در Catel از کلاس پایه ViewModelBase و View‌‌ها نیز از کلاس DataWindow مشتق می‌شوند.
DataWindow یک Window پیشرفته با قابلیت هایی مانند افزودن خودکار دکمه‌های Ok / Cancel یا Ok / Cancel / Apply یا Close می‌باشد که می‌تواند باعث تسریع روند ایجاد Window‌های تکراری شود. اما اگر به هیچ کدام از این دکمه‌های ذکر شده نیاز نداشتید DataWindowMode.Custom را انتخاب می‌کنید. نشان دادن Validation در بالای پنجره به صورت popup نیز یکی دیگر از قابلیت‌های این Window پیشرفته است. البته DataWindow دارای overload‌‌های مختلفی است که می‌توانید به کمک آن ویژگی‌های ذکر شده را فعال یا غیر فعال کنید.
حال برای درک بهتر command‌ها و نحوه تعریف و بکارگیری آن‌ها یک command جدید در MainWindowViewModel با استفاده از vmcommand ایجاد کنید. مانند قطعه کد زیر:
public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
            : base()
        {
            ShowPleaseWait = new Command(OnShowPleaseWaitExecute);
        }

        public override string Title { get { return "View model title"; } }

        public Command ShowPleaseWait { get; private set; }
        private void OnShowPleaseWaitExecute()
        {
            var pleaseWaitService = GetService<IPleaseWaitService>();
            pleaseWaitService.Show(() =>
            {
                Thread.Sleep(3000);
            });
        }
    }
در داخل بدنه این command از PleaseWaitService استفاده کردیم که در ادامه توضیح داده خواهد شد. در MainView نیز یک button اضافه کنید و پروپرتی Command آن را به صورت زیر تنظیم کنید:
<Button Margin="6"
                Command="{Binding ShowPleaseWait}"
                Content="Show PleaseWait!" />
اکنون با فشردن button کد داخل بدنه command اجرا خواهد شد.

سرویس ها:

کتابخانه Catel.MVVM دارای سرویس‌های مختلف و پرکاربردی می‌باشد که در ادامه به بررسی آن‌ها خواهیم پرداخت:
PleaseWaitService: از این سرویس برای نشان دادن یک loading به کاربر در حین انجام یک کار سنگین استفاده می‌شود و نحوه استفاده از آن به صورت زیر است:
var pleaseWaitService = GetService<IPleaseWaitService>();
pleaseWaitService.Show(() =>
{
        Thread.Sleep(3000);
});
UIVisualizerService: از این سرویس برای باز کردن پنجره‌های برنامه استفاده می‌شود. هر View در برنامه دارای یک ViewModel می باشد. برای باز کردن View ابتدا یک نمونه از ViewModel مربوطه را ایجاد میکنیم و با دادن viewmodel به متد Show یا ShowDialog پنجره مورد نظر را باز میکنیم.
var uiService = GetService<IUIVisualizerService>();
var viewModel = new AnotherWindowViewModel();
uiService.Show(viewModel);
OpenFileService: برای نشان دادن OpenFileDialog جهت باز کردن یک فایل در برنامه.
var openFileService = GetService<IOpenFileService>();
openFileService.Filter = "ZIP files (*.zip)|*.zip";
openFileService.IsMultiSelect = false;
openFileService.Title = "Open file";
if (openFileService.DetermineFile())
{
       // ?
}
SaveFileService: برای نشان دادن SaveFileDialog جهت ذخیره سازی.
var saveFileService = GetService<ISaveFileService>();
saveFileService.Filter = "ZIP files (*.zip)|*.zip";
saveFileService.FileName = "test";
saveFileService.Title = "Save file";
if (saveFileService.DetermineFile())
{
       // ?
}
ProcessService: برای اجرا کردن یک process. به عنوان مثال برای باز کردن ماشین حساب ویندوز به صورت زیر عمل می‌کنیم:
var processService = GetSetvice<IProcessService>();
processService.StartProcess(@"C:\Windows\System32\calc.exe");
SplashScreenService: برای نشان دادن SplashScreen در ابتدای برنامه هایی که سرعت بالا آمدن پایینی دارند.
var splashScreenService = GetService<ISplashScreenService>();
splashScreenService.Enqueue(new ActionTask("Creating the shell", OnCreateShell));
splashScreenService.Enqueue(new ActionTask("Initializing modules", OnInitializeModules));
splashScreenService.Enqueue(new ActionTask("Starting application", OnStartApplication));
MessageService: برای نشان دادن MessageBox به کاربر.
var messageService = GetService<IMessageService>();
if (messageService.Show("Are you sure?", "?", MessageButton.YesNo, MessageImage.Warning) == MessageResult.Yes)
{
       // ?
}
همانطور که ملاحظه کردید اکثر کارهای مورد نیاز یک پروژه با کمک سرویس‌های ارائه شده در این فریمورک به آسانی انجام می‌شود.
دریافت مثال و پروژه کامل این قسمت:
نظرات مطالب
نحوه استفاده از ViewModel در ASP.NET MVC
سلام؛ وقتی رو صفحه اصلی سایت کاربر روی ادامه مطلب کلیک میکنه و وارد صفحه مربوط به اون مطلب میشه، صفحه جدید از یک پارشال ویوو تشکیل شده که دارای یک تگ فرم هست برای ارسال نظرات کاربران و هم چنین یک پارشال ویوو دیگر برای نمایش مطلب کامل اون لینک میباشد. برای استفاده هردو مدل یک view model تعریف شده که شامل هر دو موجودیت‌ها است. وقتی توی ویوو اصلی دکمه ادامه مطلب زده میشه این ارور داده میشه:

The model item passed into the dictionary is of type 'Class.Domain.Enities.Product', but this dictionary requires a model item of type 'WebAli.ViewModel.ProductCommentListViewModel'. 

مطالب
اصلاح شیوه نامگذاری در ReSharper

یکی از روش‌های متداول نام گذاری متدها در سی شارپ به این صورت است که متدهای خصوصی با حروف کوچک شروع شوند یا lower camel case و متدهای عمومی با حرف بزرگ.
ReSharper 4.5 که جزو ابزارهای واجب کاری است، گزینه Naming style را نیز اضافه کرده و اگر شما از اصول نامگذاری متدها، کلاس‌ها ، متغیرها و غیره پیروی نکنید، علایم راهنمایی را به شما ارائه خواهد کرد. در این نگارش تمامی متدها به یک صورت در نظر گرفته می‌شوند: Upper camel case .



برای اصلاح آن می‌توان به برگه گزینه‌های آن مراجعه کرده و در قسمت naming style بر روی دکمه add مربوط به user defined naming rules کلیک و تغییر زیر را اعمال نمود:



پس از اعمال آن اگر یک متد خصوصی را با حرف بزرگ شروع کنید، تصویر زیر نمایش داده خواهد شد:





نظرات مطالب
فعال سازی عملیات CRUD در Kendo UI Grid
نکات مطلب «فرمت کردن اطلاعات نمایش داده شده به کمک Kendo UI Grid» را در مورد کار با قالب‌ها مطالعه کنید.
روش اول:
columns: [
                { field: "units", title: "Units" },
                { field: "price", title: "Price" },
                { field: null, title: "Extended Price", template: '#= units * price #' }
            ]
روش دوم؛ یک ستون قالب دار با این فرمت اضافه می‌کنید: 
#=calculateField(data)#
که متد آن برای نمونه به این ترتیب محاسبه شود:
//Passed data contains current row model
function calculateField(data) {
  return data.f1 + " " + data.f2;
}
نظرات مطالب
استفاده از چند فرم در کنار هم در ASP.NET MVC
سلام.
مرسی از مقاله خوبتون.
من یه مشکلی دارم شاید اگه ممکنه منو هم راهنمایی کنین.
فرض کنیم یه صفحه داریم که توی اون صفحه چند تا فرم وجود داره و تعداد این فرم‌ها هم نا مشخص هستش و این فرمها به صورت پارشل ایجاد میشن. وهمچنین قصد بر این است که همه این فرم‌ها توسط یک دکمه و به ترتیب سابمیت بشن. من خودم این کار رو به کمک جاوا اسکریپت انجام دادم. حالا می‌ خواستم ببینم پیشنهاد شما چیه. ممنون از همتون. 
مطالب
React 16x - قسمت 15 - مسیریابی - بخش 1 - تعریف و تنظیم مسیریابی‌ها
React برخلاف Angular، دارای قابلیت‌های توکار مسیریابی نیست و تنها کاری را که انجام می‌دهد همان رندر View است که تا اینجا بررسی کردیم. به همین جهت در این قسمت ابتدا یک برنامه‌ی عمومی و ساده را با نصب کتابخانه‌ی ثالثی برای توضیح مفاهیم مسیریابی، شامل کار با پارامترهای مسیریابی، کوئری استرینگ‌ها، هدایت کاربران به صفحات دیگر، مدیریت صفحات یافت نشده و مسیریابی تو در تو، بررسی می‌کنیم. سپس به عنوان تمرین، همان برنامه‌ی طراحی گریدی را که تا قسمت 14 تکمیل کردیم، با معرفی مسیریابی بهبود خواهیم بخشید.


برپایی پیش‌نیازها

در اینجا برای بررسی مسیریابی، یک پروژه‌ی جدید React را ایجاد می‌کنیم.
> create-react-app sample-15
> cd sample-15
> npm start
در ادامه توئیتر بوت استرپ 4 را نیز نصب می‌کنیم. برای این منظور پس از باز کردن پوشه‌ی اصلی برنامه توسط VSCode، دکمه‌های ctrl+` را فشرده (ctrl+back-tick) و دستور زیر را در ترمینال ظاهر شده وارد کنید:
> npm install --save bootstrap
سپس برای افزودن فایل bootstrap.css به پروژه‌ی React خود، ابتدای فایل index.js را به نحو زیر ویرایش خواهیم کرد:
import "bootstrap/dist/css/bootstrap.css";
این import به صورت خودکار توسط webpack ای که در پشت صحنه کار bundling & minification برنامه را انجام می‌دهد، مورد استفاده قرار می‌گیرد.

همچنین کتابخانه‌ی ثالث بسیار معروف react-router-dom را نیز نصب می‌کنیم:
> npm i react-router-dom --save
نگارش dom آن مخصوص کار با مرورگر است و نگارش native آن (react-router-native)، مخصوص React Native و تولید برنامه‌های موبایل می‌باشد که مبحث دیگری است.


افزودن مسیریابی به برنامه

پس از نصب کتابخانه‌ی react-router-dom، برای افزودن آن به برنامه و فعالسازی مسیریابی، به فایل index.js مراجعه کرده و import آن‌را به ابتدای فایل اضافه می‌کنیم:
import { BrowserRouter } from "react-router-dom";
سپس کامپوننت App را داخل BrowserRouter، محصور می‌کنیم:
ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);
کار BrowserRouter، محصور سازی مدیریت تاریخچه‌ی مرور صفحات در مرورگر و انتقال آن به درخت کامپوننت‌های React است. به این ترتیب در هر قسمتی از درخت کامپوننت‌های برنامه می‌توان از History object مرورگر استفاده کرد.


ثبت و معرفی مسیریابی‌ها

در ادامه باید مسیریابی‌های خود را ثبت کنیم؛ به این معنا که بر اساس URL خاصی، چه کامپوننتی باید رندر شود. به همین جهت پوشه‌ی جدید src\components را ایجاد کرده و کامپوننت src\components\navbar.jsx را که یک کامپوننت تابعی بدون حالت است، در آن تعریف می‌کنیم:
import React from "react";

const NavBar = () => {
  return (
    <nav className="navbar bg-dark navbar-dark navbar-expand-sm">
      <div className="navbar-nav">
        <a className="nav-item nav-link" href="/">
          Home
        </a>
        <a className="nav-item nav-link" href="/products">
          Products
        </a>
        <a className="nav-item nav-link" href="/posts/2018/06">
          Posts
        </a>
        <a className="nav-item nav-link" href="/admin">
          Admin
        </a>
      </div>
    </nav>
  );
};

export default NavBar;
کار آن نمایش منوی بالای صفحه است.


سپس به فایل app.js مراجعه کرده و ساختار آن‌را به صورت زیر، جهت درج این NavBar، ویرایش می‌کنیم تا سبب رندر و نمایش منوی راهبری در مرورگر شود:
import "./App.css";

import React, { Component } from "react";

import NavBar from "./components/navbar";

class App extends Component {
  render() {
    return (
      <div>
        <NavBar />
      </div>
    );
  }
}

export default App;
در ادامه در کامپوننت App، یک container را اضافه می‌کنیم که قرار است در آن بر اساس URL رسیده، محتوای کامپوننت خاصی رندر شود. به همین جهت کامپوننت Route را در اینجا قرار می‌دهیم و در آن یک یا چند Route را ثبت می‌کنیم:
import "./App.css";

import React, { Component } from "react";
import { Route } from "react-router-dom";

import Dashboard from "./components/admin/dashboard";
import Home from "./components/home";
import NavBar from "./components/navbar";
import Posts from "./components/posts";
import Products from "./components/products";

class App extends Component {
  render() {
    return (
      <div>
        <NavBar />
        <div className="container">
          <Route path="/products" component={Products} />
          <Route path="/posts" component={Posts} />
          <Route path="/admin" component={Dashboard} />
          <Route path="/" component={Home} />
        </div>
      </div>
    );
  }
}

export default App;
Route نیز یک کامپوننت است؛ همانند تمام کامپوننت‌هایی که تاکنون تعریف کردیم و دارای چند ویژگی است که به صورت props به آن منتقل می‌شوند. برای نمونه خاصیت path آن به مسیر products/ در مرورگر اشاره می‌کند و سبب رندر کامپوننت جدید Products که در بالای این ماژول نیز import شده، می‌شود. در اینجا سه مسیریابی دیگر را نیز ثبت کرده‌ایم که کامپوننت‌های جدید متناظر با آن‌ها به صورت زیر تعریف می‌شوند:

کامپوننت جدید src\components\products.jsx جهت رندر لیست آرایه‌ی اشیاء product:
import React, { Component } from "react";

class Products extends Component {
  state = {
    products: [
      { id: 1, name: "Product 1" },
      { id: 2, name: "Product 2" },
      { id: 3, name: "Product 3" }
    ]
  };

  render() {
    return (
      <div>
        <h1>Products</h1>
        <ul>
          {this.state.products.map(product => (
            <li key={product.id}>
              <a href={`/products/${product.id}`}>{product.name}</a>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

export default Products;

کامپوننت بدون حالت تابعی src\components\home.jsx با این محتوا:
import React from "react";

const Home = () => {
  return <h1>Home</h1>;
};

export default Home;

کامپوننت بدون حالت تابعی src\components\posts.jsx با این محتوا:
import React from "react";

const Posts = () => {
  return (
    <div>
      <h1>Posts</h1>
      Year: , Month:
    </div>
  );
};

export default Posts;

کامپوننت بدون حالت تابعی src\components\admin\dashboard.jsx در پوشه‌ی جدید admin با این محتوا:
import React from "react";

const Dashboard = ({ match }) => {
  return (
    <div>
      <h1>Admin Dashboard</h1>
    </div>
  );
};

export default Dashboard;
تا اینجا اگر برنامه را اجرا کنیم، در اولین بار نمایش آن، شاهد رندر کامپوننت Home خواهیم بود. اما اگر در همین حالت بر روی لیست products، در منوی بالای صفحه کلیک کنیم، هم کامپوننت products و هم کامپونت home، هر دو با هم رندر شده‌اند. یک چنین رفتاری را در سایر صفحات نیز می‌توان مشاهده کرد:



معرفی کامپوننت Switch

<div className="container">
  <Route path="/products" component={Products} />
  <Route path="/posts" component={Posts} />
  <Route path="/admin" component={Dashboard} />
  <Route path="/" component={Home} />
</div>
الگوریتم تطابق کامپوننت Route، ابتدا بررسی می‌کند که آیا برای مثال URL ای با path مساوی products/ شروع شده‌است؟ اگر اینطور است، کامپوننت متناظر با آن را که برای نمونه در اینجا Products است، رندر می‌کند. این حالت جهت مسیری مانند products/new/ نیز صدق می‌کند؛ چون این URL نیز با products/ شروع شده‌است. همچنین این تطابق‌گر، مسیر ثبت شده‌ی برای کامپوننت Home را نیز چون با / شروع شده‌است و جزء ابتدایی مسیر products/ است هم رندر می‌کند. به همین جهت است که وقتی مسیر products/ را درخواست می‌دهیم، در صفحه دو کامپوننت products و home، با هم رندر می‌شوند.
یک روش حل این مشکل، استفاده از ویژگی exact است:
<Route path="/" exact component={Home} />
به این ترتیب اگر مسیر درخواستی دقیقا مساوی / بود، کامپوننت Home را رندر خواهد کرد. با این تغییر، با مراجعه‌ی به آدرس products/، دیگر رندر کامپوننت home را شاهد نخواهیم بود:


راه دوم رفع این مشکل، استفاده از کامپوننت Switch است. به همین جهت ابتدا این کامپوننت را import می‌کنیم:
import { Route, Switch } from "react-router-dom";
سپس تمام Routeهای تعریف شده را داخل Switch محصور خواهیم کرد:
class App extends Component {
  render() {
    return (
      <div>
        <NavBar />
        <div className="container">
          <Switch>
            <Route path="/products" component={Products} />
            <Route path="/posts" component={Posts} />
            <Route path="/admin" component={Dashboard} />
            <Route path="/"  component={Home} />
          </Switch>
        </div>
      </div>
    );
  }
}
Switch اولین مسیریابی را که با URL داده شده تطابق داشته باشد، رندر می‌کند. همچنین در اینجا دیگر نیازی به ذکر ویژگی exact نیز وجود ندارد. بنابراین با استفاده از Switch اگر مسیر داده شده، products/ باشد، مسیریابی تعریف شده‌ی با آن یافت می‌شود که در اینجا اولین Route تعریف شده‌است. سپس کار رندر کامپوننت آن‌را انجام داده و از مابقی مسیریابی‌های تعریف شده، صرفنظر می‌کند.
بنابراین هنگام کار با Switch، ترتیب مسیریابی‌های تعریف شده مهم است و باید از یک مسیریابی ویژه شروع شده و به یک مسیریابی عمومی مانند / ختم شود.


معرفی کامپوننت Link

تا اینجا اگر برنامه را اجرا کرده باشید و پیشتر سابقه‌ی کار با برنامه‌های SPA یا Single page applications را داشته باشید، یک مشکل دیگر را نیز احساس کرده‌اید: سیستم مسیریابی که تا کنون تعریف کرده‌ایم، به صورت SPA عمل نمی‌کند. یعنی به ازای هربار کلیک بر روی لینک‌های منوی راهبری سایت، یکبار دیگر به طور کامل برنامه از صفر بارگذاری مجدد می‌شود و تمام اسکریپت‌های آن مجددا از سرور دریافت شده و رندر خواهند شد. این مورد را در برگه‌ی network ابزارهای توسعه دهندگان مرورگر خود بهتر می‌توانید مشاهده کنید. به ازای هر درخواست نمایش کامپوننتی، تعدادی درخواست HTTP به سمت سرور ارسال می‌شوند که برای دریافت صفحه‌ی index و bundle.js برنامه هستند. اما در برنامه‌های SPA، مانند جمیل، با هربار کلیک بر روی لینکی، شاهد ریفرش و بارگذاری مجدد کل آن صفحه نیستیم و تنها اطلاعات موجود در قسمت container به روز می‌شوند.

یک نکته: در اینجا ممکن است دو درخواست websocket و info را نیز مشاهده کنید. این دو مرتبط به hot module reloading هستند که با ذخیره‌ی برنامه در ادیتور VSCode، بلافاصله سبب به روز رسانی و ریفرش برنامه در مرورگر می‌شوند.

برای رفع مشکل SPA نبودن برنامه، باید به کامپوننت NavBar مراجعه کرده و تمام anchor‌های استاندارد تعریف شده‌ی در آن‌را با کامپوننت Link جایگزین کنیم:
import React from "react";
import { Link } from "react-router-dom";

const NavBar = () => {
  return (
    <nav className="navbar bg-dark navbar-dark navbar-expand-sm">
      <div className="navbar-nav">
        <Link className="nav-item nav-link" to="/">
          Home
        </Link>
        <Link className="nav-item nav-link" to="/products">
          Products
        </Link>
        <Link className="nav-item nav-link" to="/posts/2018/06">
          Posts
        </Link>
        <Link className="nav-item nav-link" to="/admin">
          Admin
        </Link>
      </div>
    </nav>
  );
};

export default NavBar;
در اینجا ابتدا کامپوننت Link را در ابتدای ماژول، import کردیم. سپس تمام anchorها را یافته و تبدیل به کامپوننت Link نمودیم. همچنین href آن‌ها را نیز به ویژگی to تغییر دادیم.
با این تغییرات اگر برنامه را اجرا کنیم، اینبار با کلیک بر روی هر لینک، دیگر شاهد بارگذاری کامل صفحه در مرورگر نخواهیم بود؛ بلکه تنها قسمت container ای که کامپوننت Route مسیریابی در آن درج شده‌است، به روز رسانی می‌شود و این عملیات نیز بسیار سریع است؛ از این جهت که محتوای این کامپوننت‌ها از همان bundle.js حاوی تمام کدهای برنامه تامین می‌شود و این فایل تنها یکبار در آغاز برنامه از سرور خوانده شده و سپس توسط مرورگر پردازش می‌شود. بنابراین در برنامه‌های SPA، برخلاف برنامه‌های وب معمولی، هربار که کاربر آدرس متفاوتی را انتخاب می‌کند، بارگذاری مجدد برنامه و خوانده شدن محتوای متناظر از سرور صورت نمی‌گیرد؛ این محتوا هم اکنون در bundle.js برنامه مهیا است و قابلیت استفاده‌ی آنی را دارد.

اما کامپوننت Link چگونه کار می‌کند؟
کامپوننت لینک در نهایت همان anchor‌های استاندارد را رندر می‌کند؛ اما به هر کدام یک onClick را نیز اضافه می‌کند که سبب جلوگیری از رفتار پیش‌فرض anchor می‌شود. به همین جهت مرورگر درخواست اضافه‌ای را به سمت سرور ارسال نمی‌کند. در اینجا مدیریت کننده‌ی onClick، تنها Url بالای صفحه را در مرورگر تغییر می‌دهد. اکنون که Url تغییر کرده‌است، یکی از مسیریابی‌های تعریف شده، با این Url تطابق یافته و سپس کامپوننت متناظر با آن‌را رندر می‌کند.


بررسی Route props


اگر بر روی لینک نمایش products در منوی راهبری سایت کلیک کرده و سپس به خروجی افزونه‌ی react developer tools دقت کنیم (تصویر فوق)، مشاهده می‌کنیم که این کامپوننت هم اکنون تعدادی خاصیت را به صورت props در اختیار دارد؛ مانند history (امکان هدایت کاربر را به صفحه‌ای دیگر دارد)، location (آدرس جاری برنامه) و match (اطلاعاتی در مورد الگوریتم تطابق مسیر). کار تنظیم این props، توسط کامپوننت Route ای که کار ثبت مسیریابی‌ها را انجام می‌دهد، صورت می‌گیرد. به عبارتی کامپوننت Route، محصور کننده‌ی کامپوننتی است که آن‌را به عنوان پارامتر، دریافت و در صورت تطابق با مسیر جاری، آن‌را رندر می‌کند. همچنین در این بین کار تزریق خواص props یاد شده را نیز انجام می‌دهد.


ارسال props سفارشی در حین مسیریابی به کامپوننت‌ها

همانطور که بررسی کردیم، کامپوننت Route، حداقل سه خاصیت props را به کامپوننت‌هایی که رندر می‌کند، تزریق خواهد کرد. اما در اینجا برای تزریق خواص سفارشی چگونه باید عمل کرد؟
در حین کار با کامپوننت Route، برای ارسال props اضافی، بجای استفاده از ویژگی component آن، باید از ویژگی render استفاده کرد:
<Route
  path="/products"
  render={() => <Products param1="123" param2="456" />}
/>
در اینجا کار با تعریف یک arrow function شروع می‌شود که در نهایت المان کامپوننت مدنظر را همانند روش متداولی که برای تعریف تمام کامپوننت‌های React و تنظیم ویژگی‌های آن‌ها استفاده می‌شود، بازگشت می‌دهد که تاثیر آن‌را در خروجی افزونه‌ی react developer tools بهتر می‌توان مشاهده کرد:


البته اگر به تصویر فوق دقت کنید، سایر خواص پیشینی که تزریق شده بودند مانند history، location و match، دیگر در اینجا حضور ندارند. برای رفع این مشکل باید تعریف arrow function انجام شده را به صورت زیر تغییر داد:
<Route
  path="/products"
  render={props => (
    <Products param1="123" param2="456" {...props} />
  )}
/>
ابتدا پارامتر arrow function را به همان props تنظیم می‌کنیم. سپس با استفاده از spread operator، این props را در المان JSX تعریف شده، گسترده و تزریق می‌کنیم؛ با این خروجی:



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: sample-15-part-01.zip
مطالب
Embed کردن SQL Server Express 2008 در یک برنامه
مقدمه
نصب Microsoft Sql Server یکی از عملیات مشکل برای کاربر نهایی می‌باشد. برای رفع این مشکل، باید آنرا بصورت اتوماتیک و بدون درگیر کردن کاربر آن را نصب کنیم.برای اینکار دو روش موجود است:
1) استفاده از فایل Configure.ini
2) ارسال پارامتر به فایل Setup.exe از طریق Command Prompt

قابلیت‌های نسخه‌های مختلف Sql Server Express 2008
 نسخه / قابلیت Database Engine Management Studio Basic Full-Text Search Reporting Services
Management Studio Basic    X    
 Runtime Only
 X      
 with Tools   X  X    
  with Advanced Services     X  X  X  X

(SQL Server 2008 Management Studio Express (SSMSE
ابزارهای مدیریتی گرافیکی رایگان برای پیکربندی، مدیریت و اداره کردن برنامه‌های SQL Server Express 2008
استفاده برای مدیریت چندین نمونه از موتور پایگاه داده SQL Server که توسط نسخه‌های مختلف SQL Server 2008 ساخته شده اند.

(SQL Server 2008 Express (Runtime Only
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده

SQL Server 2008 Express with Tools
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده
SQL Server Management Studio Basic - یک ابزار مدیریتی ویژوال برای ساخت، ویرایش و مدیریت پایگاه‌های داده

SQL Server 2008 Express with Advanced Services
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده
SQL Server Management Studio Basic - یک ابزار مدیریتی ویژوال برای ساخت، ویرایش و مدیریت پایگاه‌های داده
Full-Text Search - یک موتور قدرتمند و پرسرعت برای جستجوی داده‌های متن-فشرده

دو حالت برای نصب SQL Server وجود دارد:
نصب یک نمونه جدید
آپگرید

نصب SQL Server Express 2008 از طریق Command Prompt
1) پس از دانلود SQL Server Express 2008 با پارامتر X/ انرا از حالت فشرده خارج کنید.
برای این کار Command Prompt (یا همان cmd) را باز کنید و با دستور cd به مسیری که فایل  SQL Server Express هست بروید.
حالا نام فایل نصب را همراه با پارامتر X/ در cmd تایپ کنید. مثلا: SQLExpr32_x86_enu.exe /x
نکته: اگر فایل یا سی دی نصب ویژوال استودیو 2010 را دارید می‌توانید فایل نصب SQL Server Express را در مسیر WCU\SSE\ پیدا کنید.
2) همانطور که می‌بینید یک مسیر برای Extract از شما خواسته شده. یک مسیر وراد کنید.
3) در مسیر ساخته شده، یک فایل با پسوند bat. بسازید و آنرا یا یک ویرایشگر متنی باز کنید و دستورات زیر را در آن تایپ کنید:
Setup.exe /q /Action=Install /Hideconsole /Features=SQL,Tools
/InstanceName=SQLExpress /SQLSYSADMINACCOUNTS="Builtin\Administrators"
/SQLSVCACCOUNT="<DomainName\UserName>" /SQLSVCPASSWORD="<StrongPassword>

توضیح پارامترهای فوق بشرح زیر است:
q/ (اختیاری): اینکه Setup به حالت خاموش (quiet mode) و بدون رابط کاربری اجرا شود.
Action/ (الزامی): عملیاتی که باید انجام شود. این پارامتر مقدار install و upgrade را قبول می‌کند.
Features/ (الزامی): اینکه کدام قابلیت‌های SQL Server باید نصب شوند.
HideConsole/ (اختیاری): اگر از این پارامتر استفاده شود، پنجره کنسول نمایش داده نخواهد شد.
InstanceName/ (الزامی): نام نمونه ایی که باید نصب شود.
SQLSYSADMINACCOUNTS/ (الزامی): مقررات لوگین برای اعضای با نقش "مدیر سیستم".
SQLSVCACCOUNT/ (الزامی): تعیین اکانتی که سرویس SQL Server را در Startup ویندوز اجرا کند.
SQLSVCACCOUNT/ (اگر از یک اکانت لوکال یا تحت Domain استفاده کنید الزامی است): تعیین پسورد اکانت پارامتر SQLSVCACCOUNT.

باتوجه به سیاست‌ها نصب می‌توانید از پارامترها دیگری نیز استفاده کنید. بعنوان مثال پارامترهای زیر برای نصب روی سیستمی که نام کاربری و پسورد انرا نداریم مناسب است:
setup.exe /q /Action=Install /Features=SQL /InstanceName=SQLExpress /SECURITYMODE=SQL /SAPWD="1234567" 
/SQLSYSADMINACCOUNTS="Builtin\Administrators" /SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" 
/SQLSVCSTARTUPTYPE="Automatic" /TCPENABLED=1 
نکته: اگر مقدار پارامتر SECURITYMODE برابر SQL باشد حتما باید پارامتر SAPWD مقداردهی شود.
نکته: اگر مقدار TCPENABLED برابر 1 باشد پروتکل TCP/IP فعال می‌شود. اگر هیچ نمونه‌ی دیگری روی سیستم نصب نباشد مقدار TCP Port برابر 1433 است، درغیر اینصورت یک مقدار تصادفی تولید می‌شود.
نکته: برای خوانایی بیشتر، پارامترهای فوق در چند خط نوشته شده اند. برای اجرای صحیح در یک فایل bat، همه انها باید در یک خط باشند.
برای اولین بهتر است از پارامتر HideConsel/ استفاده نکنید تا خطای احتمالی رو مشاهده کنید. برای آپگرید کردن نیز می‌توانید از دستور زیر استفاده کنید:
Setup.exe /q /Hideconsole /ACTION=upgrade /INSTANCENAME=SQLExpress

برای مشاهده دیگر پارامترها به مستندات MSDN مراجعه کنید. همچنین می‌توان نصب از طریق فایل Configuration را نیز انجام داد.
امیدوارم مفید واقع شده باشد.
مطالب
صفحه کلید مجازی برای ورود اطلاعات
همانگونه که اطلاع دارید یکی از روش‌های سرقت اطلاعات استفاده از نرم افزارهای جاسوس صفحه کلید (Key Logger) است، البته ثبت کلید‌های فشرده شده می‌تواند توسط سخت افزارهایی که سر راه سوکت صفحه کلید و کیس قرار می‌گیره، انجام بشه. در صورتی که چنین سخت افزاری (مخصوصا در کافی نت‌ها) روی کامپیوتر کاربر نصب باشه، یا توسط ویروس و بدافزارها اینگونه نرم‌افزارهایی روی سیستم کاربر قرار بگیره هر کلیدی که توسط کاربر روی صفحه کلید فشرده میشه توسط اینها ثبت شده و در موقع مناسب برای فرد سازنده به طریقی (ایمیل یا ارتباط از طریق برنامه‌های مبتنی بر سوکت) حتی بسیاری از این برنامه‌ها پا را فراتر گذاشته و عنوان پنجره ای که کلیدها در آن فشرده شده نیز ثبت می‌شود (توسط توابع API ویندوز- البته اگر دوستان مایل باشن و از نظر مدیریت سایت ایرادی نداشته باشه، نحوه طراحی این نوع برنامه‌های جاسوس سخت افزار، صفحه کلید، یا ماوس آموزش می‌دم توی همین سایت)، حال برای امنیت برنامه‌های تحت وب یا ویندوز چگونه می‌توان در زمان ورود اطلاعات حساس مانند کلمه عبور یا شماره کارت اعتباری این امنیت را برای کاربر ایجاد کرد که داده‌هایش توسط این سخت افزارها یا بدافزار‌ها جایی ثبت نشود؟
بله، حدس شما درست است استفاده از صفحه کلیدهای مجازی میشه گفت یکی از بهترین راه‌های ممکن هست، چون در این روش‌ها کلید به صورت سخت افزاری فشرده نمی‌شود (کلید فشرده شده به صف پیام‌های ویندوز نمی‌رود) در نتیجه نرم افزار‌ها یا سخت افزارهای جاسوس نمی‌توانند این اطلاعات را ثبت کنند. و کاربر با خیال راحت می‌تواند داده‌های خود را وارد نمایند (تاکید می‌کنم این روش فقط جلو این نرم افزارها یا سخت افزارها را می‌گیرد و تضمینی برای اینکه در زمان ارسال داده‌های شما لو نرود ندارد).
خوب حال چه باید کرد؟
یک راه می‌تواند پیاده‌سازی صفحه کلید مجازی با کدهای طرف کلاینت مانند جاوا اسکریپت و وی‌بی اسکریپت است، اما گروهی پلاگینی را توسعه داده‌اند که با چند خط کدنویسی ساده به راحتی می‌توانید یک صفحه کلید مجازی چندزبانه (با هر زبانی که دلتون می‌خواد) داشته باشید و از اون در برنامه‌های خودتون استفاده کنید.

نحوه‌ی نصب:
ایتدا فایل‌های مورد نیاز را از سایت سازنده که شامل فایل جاوا اسکریپت ، فایل استایل و یک تصویر (آخرین نسخه) یا از این آدرس به صورت کامل (در حال حاضر نسخه 1.49) دریافت کرده، پس از دریافت فایل‌ها آنها را در هاست خود بارگزاری (آپلود) نمائید. سپس کدهای زیر را در صفحه‌ای که می‌خواهید صفحه کلید نمایش یابد در بین تگ <head> ... و <head/> قرار دهید.
<script type="text/javascript" src="keyboard.js" charset="UTF-8"></script>
<link rel="stylesheet" type="text/css" href="keyboard.css">
حالا فقط کافی است به inputbox‌ها و یا هر ورودی دیگر خود class=keyboardInput بدهید.
مثال:
<input type="text" value="" class="keyboardInput">
در نهایت کد صفحه شما باید اینگونه باشد:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="keyboard.js" charset="UTF-8"></script>
    <link rel="stylesheet" type="text/css" href="keyboard.css"/>
</head>
<body>
    <input type="text" value="" class="keyboardInput"/>
</body>
</html>

با این کار پس از اجرای صفحه مورد نظر خروجی شما مانند تصویر زیر خواهد بود، جهت محدود کردن کلیدها و عملیات دلخواه و سفارشی سازی با پارامترهای دلخواه می‌تواند از دموهای موجود در سایت سازنده بهره بگیرید.

موفق وموید باشید.
نظرات مطالب
کار با اسکنر در برنامه های تحت وب (قسمت دوم و آخر)
سلام؛ ممنون از مطلب مفیدتون. من راهی رو گفتیم رفتم wcfservice هم run کردم و درست بود اما با اجرای WinForm  و  زدن آدرس locallhost:8010 چیزی باز نمیشه. کد زیر هم اصلا کار نمیکنه:
 <script>
  $( "#get-scan" ).click(function () {
       var url = 'http://localhost:8010/' ;
       $. get (url, function (data) {
       $( "#img-scanned" ).attr( "src" , "data:image/Jpeg;base64,  " + data.GetScanResult);
    });
  });
پورت رو هم 6019 میذارم بازم همینطور. ممنون میشم راهنمایی کنید.