مطالب
Performance در AngularJS قدم اول
به احتمال زیاد برنامه نویسانی که از AngularJS در پروژه‌های خود استفاده می‌کنند، در برخی موارد کند شدن در Rendering و Binding صفحات را تجربه کرده اند. این مقاله مطالب خیلی ساده و راحتی در خصوص استفاده درست و بهینه از Binding می‌باشد.

قدم اول و مهم بحث on time binding هست:
در برخی موارد ما اطلاعاتی که فقط یکبار Bind می‌شوند و در طول اجرا هیچ تغییری نمی‌کنند را درست Bind نمی‌کنیم. برای مثال فرض کنید می‌خواهیم عنوان صفحه را در یک تگ h1 نمایش دهیم. به صورت معمول همه‌ی ما از روش زیر استفاده می‌کنیم.
<h1>{{title}}</h1>

اما این روش درست نیست! چرا؟

AngularJS برای Rendering طرف View از Watcher‌ها استفاده می‌کند که در هر لحظه Binding‌ها را رصد می‌کنند و در صورت تغییر قسمت مورد نظر از View، دوباره Render می‌شود. بحث اصلی خود Watcher‌ها هستند که حتی Binding‌هایی که هیچ وقت مقادیر آنها تغییر نمی‌کنند نیز رصد می‌شود و این باعث کندی عمل Watching در AngularJS می‌شود. در AngularJS نسخه‌ی 1.3 به بعد امکانی فراهم شده‌است که شما بتوانید Binding‌هایی را که یک بار بیشتر تغییر نمی‌کنند، مشخص کنید. به کد زیر دقت کنید:
<h1>{{::title}}</h1>
بله دقیقا به همین راحتی! شما با اضافه کردن :: در ابتدای هر Binding مشخص می‌کنید که این قسمت از View فقط یک بار Render شود. این عمل باعث می‌شود Watcher AngularJS کار کمتری انجام دهد.

به زودی مقاله‌های بیشتری در خصوص Performance در AngularJS خواهم نوشت. امیدوارم لذت برده باشید.

نظرات مطالب
کار با Docker بر روی ویندوز - قسمت پنجم - ایجاد Imageهای سفارشی
سلام
چرا نمیتونیم یک image ویندوزی خیلی ساده وبدون وابستگی بسازیم؟ 
مثل چیزی که برای لینوکس امکانش هست
FROM scratch
COPY hello /
CMD ["/hello"]
همین رو برای ویندوز مجبوریم به شکل زیر بنویسیم
FROM mcr.microsoft.com/windows/nanoserver:1809
COPY hello.txt C:
CMD ["cmd", "/C", "type C:\\hello.txt"]

مطالب
بخش اول - آشنایی و شروع کار با Svelte
 

svelte




معرفی : 
Svelte یک رویکرد جدید برای ایجاد رابط کاربری است که به ما کمک میکند صفحاتی پویا به صورت SPA با کارآیی و کیفیت بالا و همچنین کمترین حجم کد تولید کنیم. تفاوت اصلی svelte با رقبای سنتی خود مانند vue - React - angular  این است که Svelte تنها یک فریم ورک نیست، بلکه درواقع یک کامپایلر است که همین موضوع سبب شده توجه زیادی را اخیرا به خود جلب کند. در فریم ورک‌های سنتی، تمام عملیات در browser انجام میشود یا بهتر است بگوییم در run-time؛ ولی svelte تمام این عملیات را زمان build شدن برنامه شما انجام میدهد و کد جاوا اسکریپتی بدون هیچ وابستگی به هیچ پکیجی تولید میکند. نکته دیگری که باید به آن اشاره کنم این است که برخلاف سایر فریم ورک‌ها، svelte از virtual DOM استفاده نمیکند! در بخش‌های بعد در مورد virtual DOM و معایب آن بیشتر صحبت خواهیم کرد. 


مقایسه مختصر فریم ورک‌های معتبر :
مقایسه‌هایی که در ادامه قصد دارم به اشتراک بگذارم، بر مبنای سه بخش Performance - size - lines of code است که به صورت مختصر با هم بررسی خواهیم کرد و کاری با جزئیات این مقایسه نداریم؛ چرا که هدف از نشان دادن این مقایسه صرفا این است که شاید برای ما سوال شود چرا باید یا بهتر است به این فریم ورک اهمیت بدهیم. 

  • Performance : کارآیی - که در ارتباط با مدت زمان پاسخ گویی و قابل استفاده شدن برنامه میباشد. (مقایسه به درصد - هرچه بیشتر عملکرد بهتر)


در مقایسه اول، اکثر فریم ورک‌ها، امتیازی بالای 90 درصد دارند که در واقع نشان دهنده این است شما از هرکدام از این موارد استفاده کنید، چندان تفاوتی را احساس نخواهید کرد. 
با توجه به اینکه svelte به نسبت بقیه این فریم ورک‌ها که خیلی از آنها کاملا جا افتاده هستند، بسیار جدید است و جای بهبود دارد از نظر performance عملکرد قابل قبولی از خود نشان داده است.

  • Size : اندازه - که نشان دهنده حجم نهایی فایل‌های تولید شده ( Css-Html-JavaScript ) فریم ورک است. این مقایسه اندازه فریم ورک و تمام وابستگی‌های آن است که به bundle نهایی برنامه اضافه شده است (هر چه اندازه فایل کمتر باشد بهتر است چراکه توسط کاربر نهایی زودتر دانلود میشود).


در مقایسه size یکی از دلایل محبوبیت این کامپایلر را مشاهده میکنید که تفاوت قابل توجهی نسبت به سایر فریم ورک‌ها دارد.


  • Lines of Code : تعداد خطوط کد - نشان دهنده این است که یک نویسنده بر اساس این فریم ورک‌ها چند سطر کد را باید برای تهیه‌ی یک برنامه‌ی جدید بنویسد.


نکته دیگری که باید اینجا بهش اشاره کنم، ساده بودن svelte است. این سادگی سبب میشود میزان کدنویسی برای ساخت یک برنامه به مراتب کمتر از فریم ورک‌های دیگر باشد. که در نتیجه بازدهی استفاده از آن را بالاتر خواهد برد.
برای کسب اطلاعات بیشتر و مطالعه منبع این مقایسه میتوانید به این لینک مراجعه نمایید.

نتیجه گیری : ( مزایا  -  معایب  )
درمورد مزایای استفاده از svelte میتوان به راحتی کارکردن با آن، حجم بسیار کم کدهای نهایی برنامه و عملکرد مناسب آن و همینطور استفاده نکردن از virtualDom اشاره کرد؛ چرا که برای اولین بار کدهای تولید شده به معنای واقعی واکنش گرا خواهند بود.
هرچند معایبی هم شاید داشته باشد که قبل از هر چیز بهتر است به آنها اشاره کنم. بزرگترین و شاید تنها ایرادی که من میتوانم از این فناوری بگیرم این است که خالق این تکنولوژی یک نفر است! angular توسط شرکت google توسعه داده میشود. react  توسط فیسبوک توسعه داده میشود. vue درست است که شرکت بزرگی آن را توسعه نمیدهد ولی نتیجه یک کار تیمی و چند صد نفر برنامه نویس مختلف است که به صورت open source به توسعه آن میپردازند. شاید این تنها نکته منفی باشد که اعتماد به این تکنولوژی را سخت کرده است.



دانلود و نصب : 
پیش نیاز :
قبل از هرچیز برای نصب Svelte به Node.Js نیاز داریم. قبل از شروع کار، از نصب بودن آن اطمینان حاصل نمایید.
ساخت اولین برنامه : 
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev
با استفاده از degit در ابتدا اقدام به دریافت sveltejs/template میکنیم که قالب ساده‌ای برای شروع کار با svelte میباشد. سپس به فولدری که فایل‌ها در آن قرار گرفته‌اند، رفته و وابستگی‌های قالب را نصب میکنیم. در انتها با دستور npm run dev پروژه ساده HelloWorld ما به صورت پیش فرض بر روی پورت 5000 localhost قابل مشاهده است.
البته با استفاده از اسکریپت dev، کدهای ما برای زمان برنامه نویسی بهینه شده‌اند و چندان برای پابلیش و استفاده مناسب نیستند؛ لذا برای تولید کدهای مناسب برای محصول نهایی میتوانیم از دستور npm run build استفاده کنیم.
در بخش بعد به بررسی ساختار فایل‌ها و کدهای ایجاد شده Svelte میپردازیم.
نظرات مطالب
بررسی مشکلات AngularJS 1.x
سلام
بنده هم بیش از 2 سال است که با Angular کار می‌کنم  مشکلاتی که از نظر من بیشتر مهمه و باید اول پروژه  قبل از انتخاب، در نظر گرفته شود شامل موارد زیر هستش
  • وضعیت Angular (و فکر می‌کنم بقیه SPA ها) در کامپوننت‌ها خیلی بد و شما در خیلی موارد انتخاب ندارید و از کامپوننت‌های pure javascript و جی کوئری هم بیشتر مواقع نمیشه استفاده کرد و تنها یک راه اینه که خودتون کامپوننت‌های مورد نیاز خودتونو بنویسید که اینم  با توجه به Resource و زمان پروژه خیلی جاها امکان پذیر نیست. کامپوننت هایی که با Angular پیاده شده اند اکثرا یا از لحاظ Performance واقعا افتضاح هستند مثل Kendo یا خیلی ساده هستند که جوابگو نیستن و بازم مجبورید که به سمت پیاده سازی کامپوننت برید.
  • بحث Performance هم در صورتی که با یک پروژه سنگین روبرو باشید مطمئنا اذیت خواهد کرد و خیلی جاها مجبورید به سمت Pure javascript حرکت کنید و همیشه باید حواستون به watch ها، Bind‌ها و ... باشه(dirty watch) تو بحث Performance هم اگر بخوایید از Pattern‌های خاصی استفاده کنید (Flux) تا حدودی نسبت به pure javascript دستتون بسته است و باید خیلی چیزها را خودتون طراحی و پیاده سازی کنید.
  • مشکل سوم هم لود اولیه صفحتونه که می‌تونه مشکل ساز بشه
البته من فکر می‌کنم این موارد در همه SPA‌ها تقریبا موجود هستش و باید سیر تکاملی خودشونو طی کنن 
نظرات مطالب
اعتبارسنجی مبتنی بر کوکی‌ها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- ابتدا باید هدر مورد انتظار را مشخص کنید:
public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddAntiforgery(options => options.HeaderName = "__RequestVerificationToken"); 
}
- بعد متدی را برای تولید توکن در فایل razor درج کنید:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf

@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}
- سپس اگر از jQuery استفاده می‌کنید، به صورت زیر این هدر با هر درخواستی به سمت سرور ارسال می‌شود:
<script type="text/javascript">
  $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
      jqXHR.setRequestHeader("__RequestVerificationToken", '@GetAntiXsrfRequestToken()');
  });
</script>
مطالب
Pipeها در Angular 2 – قسمت دوم – ساخت Pipe سفارشی
در قسمت قبل، مقدماتی از Pipeها را مورد برسی قرار دادیم؛ از جمله کاربرد Pipeها، نحوه استفاده از آنها، معرفی یکسری Pipe از پیش ساخته شده Angular، نحوه ارسال پارامتر به آنها و همچنین نحوه استفاده از آنها را در داخل Typescript، فراگرفتیم. در این قسمت نحوه ساخت Pipeهای سفارشی و همچنین نکات تکمیلی در مورد آنها را مورد بحث و بررسی قرار می‌دهیم.

نحوه ساخت Pipe سفارشی

علاوه بر استفاده از Pipeهای از پیش ساخته شده Angular، شما می‌توانید Pipeهای سفارشی خود را نیز تعریف و استفاده کنید. به عنوان مثال می‌خواهیم Pipe ای را با نام perNumber تعریف کنیم، تا تمامی اعداد موجود در عبارت ورودی Pipe را به صورت اعداد فارسی نمایش دهد. یعنی با اعمال این Pipe به عدد 123456 خروجی ۱۲۳۴۵۶ مورد انتظار است. برای ایجاد Pipe سفارشی مراحل زیر را انجام دهید.


قدم اول - ساخت یک فایل با نام دلخواه

طبق Style Guide در Angular.io نام این فایل را per-number.pipe.ts انتخاب می‌کنیم.


قدم دوم – افزودن ماژولهای مورد نیاز

داخل فایل ایجاد شده ماژول‌های Pipe و PipeTransform را با استفاده از دستور import از angular/core@ اضافه می‌کنیم.
 import { Pipe, PipeTransform } from '@angular/core';


قدم سوم – ساخت کلاس و مزین کردن آن به Pipe@

یک کلاس با نام دلخواه را مثلا به نام PerNumberPipe ایجاد می‌کنیم. این کلاس علاوه بر اینکه PipeTransform را پیاده سازی خواهد کرد، مزین به متادیتای Pipe@ نیز می‌باشد. متادیتای Pipe@ هنگام تزئین کلاس، یک نام را دریافت می‌کند. این نام قرار است به عنوان نام نهایی Pipe برای اعمال بر روی Template expressions مورد استفاده قرار بگیرد.
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'perNumber'}) export class PerNumberPipe implements PipeTransform {

}


قدم چهارم – پیاده سازی متد transform

به واسطه اعمال اینترفیس PipeTransform، این کلاس باید متد transform را پیاده سازی کند. این متد در پارامتر اول خود، عبارت ورودی را که قرار است Pipe بر روی آن اعمال شود، دریافت می‌کند و در ادامه تعداد دلخواهی پارامتر ورودی Pipe را که می‌خواهد، می‌تواند دریافت کند.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'perNumber'})
export class PerNumberPipe implements PipeTransform {
    transform(value: any, ...args: any[]): any {

    }
}

نکته ۱: نام انتخابی برای Pipe در آذین‌گر Pipe@ بایستی یک شناسه معتبر در JavaScript باشد.
نکته ۲: متد transform برای Pipe اجباری است و حتما بایستی پیاده سازی شود. اینترفیس PipeTransform این متد را برای کلاس اجباری می‌کند؛ هرچند استفاده از این اینترفیس برای کلاس Pipe کاملا اختیاری است.


قدم آخر – نوشتن کد تبدیل اعداد

Pipe مورد نظر ما قرار است یک رشته عددی را از ورودی دریافت کند و تمامی اعداد لاتین آن را به فارسی تبدیل کند. همچنین این Pipe هیچگونه پارامتری را دریافت نمی‌کند. کد زیر نحوه پیاده سازی متد transform را نمایش می‌دهد.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'perNumber'}) export class PerNumberPipe implements PipeTransform {
    transform(input: string): string{
        if (input == undefined) return '';
        var str = input.toString().trim();
        if (str === "") return "";
        str = str.replace(/0/g, '۰');
        str = str.replace(/1/g, '۱');
        str = str.replace(/2/g, '۲');
        str = str.replace(/3/g, '۳');
        str = str.replace(/4/g, '۴');
        str = str.replace(/5/g, '۵');
        str = str.replace(/6/g, '۶');
        str = str.replace(/7/g, '۷');
        str = str.replace(/8/g, '۸');
        str = str.replace(/9/g, '۹');
        return str;
    }
}


نحوه معرفی Pipe سفارشی به برنامه

حالا جهت استفاده از Pipe سفارشی در کامپوننت‌های خود کافی است آنرا یکبار در قسمت declarations در AppModule خود  تعریف کنید.
import { PerNumberPipe } from './pipes/per-number.pipe.ts'
...

declarations: [PerNumberPipe]


نحوه استفاده از Pipeهای سفارشی 

نحوه استفاده از Pipeهای سفارشی، دقیقا مشابه Pipeهای از قبل ساخته شده Angular می‌باشد.
<h3>{{'12345679' | perNumber}}</h3>
 

یکسری از Pipeهای مربوط به زبان فارسی در گیت‌هاب بنده پیاده سازی شده است که نیازمند همکاری دوستان است. لطفا جهت همکاری برای ساخت یک ابزار جامع برای زبان فارسی در Angular به این لینک مراجعه کنید.
 
Pipeها و تشخیص تغییرات

Angular برای اعمال Pipe بر روی Template expressions بایستی تمامی رخدادهای برنامه را تحت نظر قرار داده و با مشاهده هر تغییری بر روی عبارت ورودی Pipe، فراخوانی Pipe را آغاز کند. از جمله این رخدادها می‌توان به رخداد mouse move، timer tick، server response و فشرده شدن کلیدهای ماوس و یا کیبورد اشاره کرد. واضح است که بررسی تغییرات عبارت در این همه رخداد می‌تواند مخرب باشد و بر روی کارآئی (Performance) تاثیر منفی خواهد گذاشت. اما Angular برای حل این مشکل و همچنین هنگام مشاهده سریع تغییرات هنگام استفاده از Pipeها، الگوریتم‌های سریع و ساده‌ای در نظر گرفته است.


در قسمت بعد با انواع Pipeها در Angular و همچنین نحوه پیاده سازی آنها، آشنا خواهیم شد. 
مطالب
SQL تولیدی در NHibernate از کدام متد صادر شده است؟

اگر مطلب "ذخیره سازی SQL تولیدی در NH3" را دنبال کرده باشید که یک مثال عملی از "NHibernate 3.0 و عدم وابستگی مستقیم به Log4Net" بود، خروجی حاصل از آن به صورت زیر است:
---+ 12/29/2010 05:35:59.75 +---
SQL ...

---+ 12/29/2010 05:35:59.75 +---
SQL ...
و پس از مدتی این فایل هیچ حسی را منتقل نمی‌کند! یک سری SQL که لاگ شده‌اند. مشخص نیست کدام متد در کدام کلاس و کدام فضای نام، سبب صدور این عبارت SQL ثبت شده‌، گردیده‌ است.
خوشبختانه در دات نت فریم ورک می‌توان با بررسی Stack trace ، رد کاملی را از فراخوان‌های متدها یافت:
StackTrace stackTrace = new StackTrace();
StackFrame stackFrame = stackTrace.GetFrame(1);
MethodBase methodBase = stackFrame.GetMethod();
Type callingType=methodBase.DeclaringType;
با بررسی StackFrame ها امکان یافتن نام متدها، فضاهای نام و غیره میسر است. مثلا یکی از کاربردهای مهم این روش، ثبت فراخوان‌های متدی است که استثنایی را ثبت کرده است.
بر این اساس سورس مثال قبل را جهت درج اطلاعات فراخوان‌های متدها تکمیل کرده‌ام، که از این آدرس قابل دریافت است.

اکنون اگر از این ماژول جدید استفاده کنیم، خروجی نمونه‌‌ی آن به صورت زیر خواهد بود:
---+ 01/02/2011 02:19:24.98 +---
-- Void ASP.feedback_aspx.ProcessRequest(System.Web.HttpContext) [File=App_Web_4nvdip40.5.cs, Line=0]
--- Void Prog.Web.UserCtrls.FeedbacksList.Page_Load(System.Object, System.EventArgs) [File=FeedbacksList.ascx.cs, Line=23]
---- Void Prog.Web.UserCtrls.FeedbacksList.BindTo() [File=FeedbacksList.ascx.cs, Line=43]
----- System.Collections.Generic.IList`1[Feedback] Prog.GetAllUserFeedbacks(Int32) [File=FeedbackWebRepository.cs, Line=66]

SELECT ...
@p0 = 3 [Type: Int32 (0)]
به این معنا که عبارت SQL ثبت شده، حاصل از پردازش صفحه‌ی feedback.aspx، سپس متد Page_Load آن که از یوزر کنترل FeedbacksList.ascx استفاده می‌کند، می‌باشد. در اینجا فراخوانی متد BindTo سبب فراخوانی متد GetAllUserFeedbacks در فایل FeedbackWebRepository.cs واقع در سطر 66 آن گردیده است.
اینطوری حداقل می‌توان دریافت که SQL تولیدی دقیقا به کجا بر می‌گردد و چه متدی سبب صدور آن شده است.

ملاحظات:
این ماژول تنها در صورت وجود فایل pdb معتبر کنار اسمبلی‌های شما این خروجی مفصل را تولید خواهد کرد. در غیر اینصورت از آن صرفنظر می‌کند. (برای مثال نام فایل سورس فراخوان، شماره‌ی سطر فراخوان، حتی محل قرارگیری آن فایل بر روی کامپیوتر شما در فایل‌های pdb ثبت می‌گردند؛ به همین جهت توصیه اکید حین ارائه‌ی نهایی برنامه، حذف این نوع فایل‌ها است)

نظرات مطالب
چک لیست تهیه یک برنامه ASP.NET MVC
- لایه سرویس وابستگی به View نداره. هیچ ارجاع مستقیمی از عناصر بصری را در لایه سرویس نخواهید یافت. ViewModelها در MVC یک سری کلاس ساده دارای خاصیت ... خاصیت ... خاصیت بیشتر نیستید.
این سرویس ارائه شده چون با کلاس‌های مدل یا ViewModel ساده‌ای کار می‌کند که ارجاعی از عناصر بصری در آن نیست، در همه جا قابل استفاده است. چه View وجود داشته باشد یا خیر. کاملا مستقل از آن است و در نهایت View را تغذیه خواهد کرد؛ اما ارتباط یک طرفه است و نه دو طرفه.
عدم وابستگی به لایه بصری را در Web forms بهتر می‌شود توضیح داد. زمانیکه شما TextBox1.Text را در کدهای خود دارید، این به معنای وابستگی مستقیم است به عناصر بصری؛ نه حالتیکه یک کلاس ساده ViewModel دارای خاصیت ... خاصیت ... خاصیت را دارید که روح آن از وجود TextBox1 بی‌خبر است.
- در مورد بازگشت کلی domain model هم بحث شد؛ کمی بالاتر، خصوصا در گزارشات. این مساله سبب می‌شود که شما 20 فیلد را بازگشت داده و سپس در سمت کلاینت 3 مورد آن‌را نمایش دهید. به این ترتیب مصرف حافظه بالاتری را خواهید داشت. چون در ابتدای کار باید select تهیه شده در پشت صحنه هر چه هست و نیست را واکشی کند. سپس قصد دارید آن‌را به ViewModel نگاشت کنید. این نگاشت بهتر است همان ابتدای کار در select تهیه شده صورت گیرد؛ به این ترتیب واکشی از دیتابیس مثلا فقط به سه فیلد مورد نیاز محدود خواهد شد (با سرعت بیشتر و مصرف حافظه کمتر).
مطالب
بررسی چند کتابخانه آپلود با پشتیبانی از DragDrop
برای یکی از پروژه‌ها نیاز به یک آپلودر داشتم که قابلیت  Drag&Drop را نیز داشته باشد و در ضمن پیاده سازی آسانی هم داشته باشد. در این بین به تعدادی از کتابخانه‌های جی کوئری می‌پردازیم.
FileDrop
اولین کتابخانه‌ای که با آن آشنا شدم و از آن استفاده کردم، کتابخانه‌ی FileDrop است که بسیار ساده و در عین حال قابلیت‌های خوبی را می‌دهد و از فناوری Filereader  (+) در Html5 برای اینکار استفاده می‌کند. مرورگرهای کروم، فایرفاکس 3.6 به بعد، IE10 به بعد و Opera 12 به بعد از آن پشتیبانی می‌کنند.
فایل‌های مورد نیاز را از اینجا دانلود کنید . فایل اسکریت آن را ابتدا صدا بزنید:
 <script src="~/scripts/jquery.filedrop.js" type="text/javascript"></script>
سپس المان‌های زیر را به کد HTML خود اضافه کنید:
 <div id="dropZone">فایل برنامه را به داخل این کادر بکشانید</div>
        <br>
        فایل یا فایل‌های آپلود شده:
        <ul id="uploadResult"></ul>
تگ اول، محلی است که فایل‌ها به سمت آن درگ و روی آن دراپ می‌شوند که از این به بعد به آن محل آپلود می‌گوییم. المان بعدی جهت گزارش فایل‌هایی است که آپلود شده‌اند. با آپلود شدن هر تعداد فایل، اسم آن به لیست اضافه می‌گردد.
کدهای css زیر را هم به صفحه اضافه کنید تا محل آپلود زیباتر شود:
        .files {
            min-height: 42px;
            background: #CCC none repeat scroll 0% 0%;
            border-top: 1px solid #FFF;
            margin: 11px 0px;
            padding: 11px 13px;
            border-radius: 6px;
        }

        #dropZone.mouse-over {
            background-color: #1d4257;
        }

کد جی کوئری زیر را به صفحه اضافه کنید:
      $('#dropZone').filedrop({
                url: uploadAddress,
                paramname: 'files',
                maxFiles: 1,
                dragOver: function() {
                    $('#dropZone').addClass('mouse-over');
                },
                dragLeave: function() {
                    $('#dropZone').removeClass('mouse-over');
                },
                drop: function() {
                    $('#dropZone').removeClass('mouse-over');
                },
                afterAll: function() {
                    $('#dropZone').html('آپلود با موفقیت انجام شد');
                },
                uploadFinished: function(i, file, response, time) {
                    $('#uploadResult').append('<li>' + file.name + '</li>');
                }
            });
ابتدا پلاگین جی کوئری را روی تگ مربوطه اعمال می‌کنیم و سپس پارامترها را با مشخصات زیر اعمال می‌کنیم:
Url  آدرسی که قرار است فایل‌ها به آن سمت ارسال شوند. 
 Paramname  در سمت سرور باید فایل‌ها را با استفاده از این نام پارامتر دریافت  کنید.
 maxFiles  تعداد فایلهایی که میتوان با درگ و دراپ کردن روی آن به دست آورد. در بالا به یک فایل محدود شده است.
 dragOver  این رویداد زمانی اجرا خواهد شد که اشاره گر با حالت درگ کرده فایل‌ها را به محل آپلود آورده است.
 dragLeave  موقعی که ماوس از محل آپلود خارج می‌شود
 drop  موقعی که شما فایل‌ها را روی محل  آپلود رها می‌کنید.
 afterAll  بعد از اینکه همه کارها تمام شد اجرا می‌شود.(آخرین رویداد)
 uploadFinished  کار آپلود به پایان رسیده است. در مثال بالا پس از پایان آپلود، نام فایل آپلود شده را به کاربر نشان داده‌ایم.

نحوه‌ی دریافت آن در سمت سرور, در یک اکشن متد به صورت زیر است:

[HttpPost]
        public virtual ActionResult UpdateApp(IEnumerable<HttpPostedFileBase>files)
        {
            foreach (HttpPostedFileBase file in files)
            {
                string filePath = Path.Combine(TempPath, file.FileName);
                file.SaveAs(filePath);
            }

            return Json(new {state = "success", message = "با موفقیت عملیات ارسال فایل انجام شد"}, JsonRequestBehavior.AllowGet);
        }

در اکشن متد بالا ما فایل‌ها را از طریق نام پارامتر files که مشخص کرده بودیم، به عنوان یک لیست شمارشی دریافت می‌کنیم.  کدها بالا برای ساده‌ترین راه اندازی ممکن کفایت می‌کنند.

این موارد از اصلی‌ترین‌ها هستند که به کار می‌آیند. به غیر این‌ها یک سری خصوصیات اضافه‌تری هم برای آن وجود دارد.


fallback_id 
 اگر دوست دارید این آپلودر را نیر به یک آپلودر معمولی اتصال دهید از این شناسه استفاده کنید.
 withCredentials   با استفاده از کوکی‌ها یک درخواست cross-origin ایجاد می‌کند.
 data  اگر دوست دارید به همراه فایل‌ها اطلاعات دیگری هم به همراه آن ارسال و پست شوند از این طریق اقدام نمایید. می‌تواند در قالب یک متغیر باشد یا خروجی یک تابع.
data: {
        param1: 'value1',           
        param2: function(){
            return calculated_data; 
        }
 headers برای ارسال مقدار اضافه‌تر در هدر درخواست به کار میرود و صدا زدن آن همانند کد data می‌باشد. 
 error   در صورتیکه در فرایند آپلود خطایی رخ دهد، اجرا می‌گردد. نحوه‌ی کدنویسی آن و بررسی خطاهای آن به شرح زیر است:
error: function(err, file) {
        switch(err) {
            case 'BrowserNotSupported':
                alert('مرورگر از این فناوری پشتیبانی نمی‌کند')
                break;
            case 'TooManyFiles':
                // قصد آپلود همزمان فایل‌های بیشتری از حد مجاز تعیین شده دارید
                break;
            case 'FileTooLarge':
                //حداقل حجم یکی از فایل‌ها از حجم مجاز تعیین شده بیشتر است
                //برای دسترسی به نام آن فایل از کد زیر استفاده کنید
              //file.name
                break;
            case 'FileTypeNotAllowed':
                // نوع حداقل یکی از فایل‌ها با نوع‌ها مشخص شده ما یکی نیست
                break;
            case 'FileExtensionNotAllowed':
                // پسوند حداقل یکی از فایل‌ها مورد تایید نیست
                break;
            default:
                break;
        }
    }
 allowedfiletypes   نوع فایل‌های مجاز را تعیین می‌کند:
allowedfiletypes: 
['image/jpeg','image/png','image/gif']
 allowedfileextensions   پسوند فایل هایی که برای آپلود مجاز هستند را معرفی می‌کند.
allowedfileextensions:
 ['.apk','.jar']
 maxfilesize   حداکثر حجم مجاز برای هر فایل که به مگابایت بیان می‌شود.
 docOver   این رویداد زمانی اجرا می‌شود که فایل‌های درگ شده شما وارد محیط یا پنجره مرورگر می‌شود.
 uploadStarted 
 این رویداد زمانی اجرا میگردد که فرایند آپلود هر فایل به طور جداگانه در حال آغاز شدن است:
متغیر i در کد زیر شامل اندیس فایلی است که آپلودش آغاز شده است و این اندیس از صفر آغاز می‌شود.
متغیر file دسترسی شما را به اطلاعات یک فایل باز میکند مانند نام فایل.
متغیر len تعداد فایل هایی را که کاربر در محل آپلود رها کرده است، باز میگرداند.
function(i, file, len){

    },
uploadFinished 
با اتمام آپلود هر فایل، این رویداد فراخوانی می‌گردد. دو پارامتر اول آن، همانند سابق هستند. پارامتر response خروجی json ایی را که در سمت سرور برگرداندیم، به ما باز می‌گرداند. پارامتر بعدی، زمانی را که برای آپلود طول کشیده است، بر می‌گرداند.
 function(i, file, response, time) {
    }
progressUpdated 
این رویداد برای نمایش پیشرفت یک آپلود مناسب است که آخرین پارامتر آن یک عدد صحیح از پیشرفت فایل را بر می‌گرداند.
function(i, file, progress) {
    },
globalProgressUpdated 
این رویداد میزان پیشرفت کلیه فایل‌ها را به درصد باز می‌گرداند:
function(progress) {
        $('#progress div')
.width(progress+"%"); }
speedUpdated 
سرعت آپلود هر فایل را با کیلوبیت بر ثانیه مشخص می‌کند.
function(i, file, speed) {
    }
rename
در صورتی که قصد تغییر نام فایل ارسالی را دارید می‌توانید از این رویداد استفاده کنید. پارامتر name، نام اصلی فایل را بر می‌گرداند که می‌توانید آن را دستکاری کنید و نام جدیدی را به عنوان خروجی برگردانید. نمونه کاربردی از این رویداد
 rename: function(name) {
    }

beforeEach 
این رویداد قبل از آپلود هر فایل آغاز می‌گردد و برگرداندن مقدار false در آن باعث جلوگیری و کنسل شدن آپلود آن فایل می‌گردد.
function(file) {
    }

beforeSend 
پارامترهای اولی تکراری هستند ولی آخرین پارامتر یک تابع done را می‌توان به آن پاس کرد که قبل از اجرای کل عملیات آپلود صدا زده می‌شود.
 function(file, i, done) {
    }
رویدادی به اسم queuefiles هم هست تعداد فایل‌هایی را که میتوانند به طور موازی و همزمان آپلود گردند، مشخص می‌کند. ولی دراین حالت maxfiles مورد استفاده قرار نمی‌گیرد. جهت بررسی یک مثال عملی و همچنین کدهای سمت سرور در PHP میتوانید از این آموزش استفاده کنید.
با تستی که به صورت لوکال رو آن انجام دادم به نظر نمی‌رسد برای فایل‌های با حجم متوسط به بالا مناسب باشد و برای فایل‌های با حجم کم مناسب می‌باشد. یک فایل 8 مگابایتی در حالت لوکال 9 ثانیه آپلود آن زمان برد و برای فایل‌های بزرگتر، فایرفاکس دیالوگ Stop Script را نشان داد.

PlUpload
این کتابخانه متن باز هم بسیار کارآمد و ساده و قابل انعطاف است و مثالهای آماده زیادی دارد. سایت سابسن هم در بخش آپلود زیرنویس‌ها از این کتابخانه استفاده می‌کند. از آنجا که آموزش این کتابخانه در سایت جاری آمده است از ذکر نکات بیشتر در مورد آن خودداری می‌نماییم.

Bootstrap FileStyle
اگر از قالب بوت استراپ استفاده می‌کنید و دوست دارید روی المان input file  قدیمی، ولی به شکلی مدرن کار کنید این کتابخانه هم فراموش نشود.

DropZoneJS
این کتابخانه به نسبت DropFile امکانات بیشتری را دارد و در سایت اختصاصی آن مثال‌ها و مستندات خوبی قرار گرفته است. در ساده‌ترین حالت آن ابتدا فایل کتابخانه  را صدا زده و سپس تگ فرم را به آن نسبت دهید:
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>

<form action="/upload-target" class="dropzone"></form>
ولی اگر بخواهید آن را به سمت سرور ارسال کنید و  از آنجا آن را کنترل کنید، کد فرم را به شکل زیر تغییر دهید:
ابتدا بسته‌ی نیوگت آن را صدا بزنید:
Install-Package dropzone

با نصب این کتابخانه یک سری فایل CSS هم به سیستم اضافه می‌شود که می‌توانید برای استایل دهی هر چه بیشتر از آن بهره ببرید. کد فرم را به شکل زیر تغییر دهید:
    <form action="~/Home/SaveUploadedFile" method="post" enctype="multipart/form-data" class="dropzone" id="dropzoneForm" style="width: 50px; background: none; border: none;">
        <div class="fallback">
            <input name="file" type="file" multiple />
            <input type="submit" value="Upload" />
        </div>
    </form>
تگی که با کلاس fallback مزین شده است موقعی به کار می‌آید که مرورگر از این کتابخانه پشتیبانی نکرده و مجبور به نمایش یک آپلود معمولی می‌شویم.
با استفاده از کدنویسی هم می‌توان یک المان را به یک آپلودر تبدیل کرد:
var myDropzone = new Dropzone("div#myId", { url: "/file/post"});

//============ OR ====================
$("div#myId").dropzone({ url: "/file/post" });
همانطور که می‌بینید الزامی برای اینکه از یک تگ فرم استفاده کنید ندارد.
برای کانفیگ آپلودرهایی که از طریف المانهای Html ایجاد می‌شوند، می‌توان از کد زیر استفاده کرد و یک تنظیم عمومی برای تمامی آپلودرهای html آن صفحه ایجاد کرد.
Dropzone.options.myId= {
  paramName: "file", //نام پارامتری که فایل از طریق آن انتقال می‌بابد
  maxFilesize: 2, // MB
  accept: function(file, done) {
    if (file.name == "justinbieber.jpg") {
      done("Naha, you don't.");
    }
    else { done(); }
  }
};
تابع بالا یک آرگومان از نوع file را برگردانده و اگر این تابع، تابع done را با پارامتری رشته‌ای صدا بزند، عملیات آپلود آن فایل کنسل شده و پیام خطایی را نمایش می‌دهد و در صورتیکه بدون پارامتر صدا زده شود، عمل آپلود بدون مشکل انجام می‌شود.
ازآنجا که این کتابخانه از تنظیمات وسیعی استفاده می‌کند و از حوصله‌ی این مقاله خارج است، بهتر هست که صفحه‌ی مستندات آن را که کامل هم هست، مطالعه بفرمایید. از سری قابلیت‌هایی که پشتیبانی می‌کند: موارد پوشش داده شده در FileDrop، ساخت layout، ایجاد صف، متد حذف و اضافه و از این قبیل، ایجاد تصویر تمبر مانند و ...

یک نکته تکمیلی در مورد آپلود: در ASP.net به طور پیش فرض نهایت حجم فایل آپلودی 4 مگابایتی تعیین شده است که میتوانید آن را از طریق web.config تغییر دهید:
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="1048576" />
    </system.web>
</configuration>
برای IIS 7 به بعد هم از تکه کد زیر استفاده کنید:
<system.webServer>
   <security>
      <requestFiltering>
         <requestLimits maxAllowedContentLength="1073741824" />
      </requestFiltering>
   </security>
 </system.webServer>
در هر دو کد بالا نهایت حجم بر روی یک گیگابایت تعیین شده است که maxRequestLength به صورت کیلوبایت و maxAllowContentLength به صورت بایت تعیین شده است. توصیه می‌شود هر دو شکل آن را وارد کنید. به خصوص که IIS Express از کد ابتدایی استفاده می‌کند و بخواهید نتیجه‌ی آن را در تست‌ها ببینید.

مطالب
تولید فایل Word بدون نصب MS Word بر روی سرور

یکی از مواردی که ممکن است در محیط کاری با آن برخورد داشت، تقاضای تولید فایل word یک گزارش با فرمتی مشخص از یک برنامه ASP.Net است. برای مثال یک قالب درست کرده‌اند که header‌ و footer و کلا یک فرمت رسمی دارد. الان برنامه شما باید این فایل word رسمی را با گزارشی که تولید می‌کند پر کند. حالا اینجاست که گرفتاری برنامه نویس شروع می‌شود! روی سرور باید word نصب باشد تا توسط اشیاء COM آن بتوان یک چنین کارهایی را آن‌هم با ASP.Net که به صورت پیش فرض کمترین سطح دسترسی را روی سیستم دارد انجام داد. یا اینکه باید به سراغ کامپوننت‌های تجاری رفت و حالا اینجا با این وضع تحریم و غیره چگونه بتوان آنها را خریداری کرد یا شاید احتمالا در سایت‌های وارز بتوان نسخه تکه پاره شده آنها را یافت. مشکلی هم که این نوع کامپوننت‌ها دارند این است که ممکن است سال دیگر اصلا ساپورت نشوند. محصولات مایکروسافت هم که مرتبا در حال به روز رسانی هستند. در این حالت برنامه متکی به این نوع کامپوننت‌های تجاری سورس بسته در همان نگارش قبلی خود مجبور است باقی بماند.
خوشبختانه با ارائه آفیس 2007 و فرمت OpenXML فایلهای آن، این مشکل تقریبا مرتفع شده است. مایکروسافت نیز برای سهولت تولید این نوع اسناد، OpenXML SDK را ارائه داده است که از آدرس زیر قابل دریافت است:
Open XML Format SDK 1.0

البته پیش نمایش نگارش دو SDK آن نیز موجود است که در مطلب جاری به آن پرداخته نخواهد شد.

فایل‌های office 2007 از یک فایلzip تشکیل شده از چند فایل xml داخل آن، ایجاد شده‌اند. برای مثال یک فایل docx را با winrar یا امثال آن باز کنید (تصویر زیر):



برای کار با اینگونه اسناد باید با اصطلاحات زیر آشنا شد:
Package : فایل zip شما (همان فایل برای مثال docx) اینجا یک بسته نام دارد.
Parts : اجزای این بسته که همان فایل‌های آن هستند، parts نامیده شده اند.
Relations : اگر به فایل‌های موجود در یک بسته دقت کنید، فایلهایی با پسوند rels را خواهید دید که بیانگر نحوه ارتباط Parts با یکدیگر هستند.
Relations Ids: هر ارتباط با یک ID منحصربفرد تعریف می‌گردد.

اگر علاقمند باشید که پوستری را در این رابطه مشاهده نمائید می‌توان به آدرس زیر مراجعه نمود.
Open XML Developer Map

نحوه استفاده از OpenXML SDK در دات نت:
ابتدا باید ارجاعی را به فایل DocumentFormat.OpenXml.dll که پس از نصب در مسیر OpenXMLSDK\1.0.1825\lib قرار گرفته است به پروژه افزود. سپس نیاز است تا ارجاعی به کتابخانه WindowsBase نیز به برنامه افزوده شود (تصویر زیر). افزودن ارجاعی به این کتابخانه جهت کامپایل برنامه ضروری است (شکل زیر).


تا اینجا ارجاعات برنامه به صورت زیر خواهند بود:



یک مثال ساده:
قصد داریم یک فایل docx ساده را با استفاده از OpenXML SDK ایجاد کنیم. در مثال زیر فرمت متغیر docXml را می‌توان با ایجاد یک فایل docx ساده در word و سپس باز کردن بسته فشرده شده آن و مشاهده محتوای فایل word\document.xml بدست آورد.
using System.IO;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;

namespace OpenXMLTestApp
{
class CWord
{

public static void CreateDocument(string documentFileName, string text)
{
using (WordprocessingDocument wordDoc =
WordprocessingDocument.Create(documentFileName, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();

string docXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
<w:body><w:p><w:r><w:t>#REPLACE#</w:t></w:r></w:p></w:body>
</w:document>";

docXml = docXml.Replace("#REPLACE#", text);

using (Stream stream = mainPart.GetStream())
{
byte[] buf = (new UTF8Encoding()).GetBytes(docXml);
stream.Write(buf, 0, buf.Length);
}
}
}
}
}

و نحوه استفاده از آن می‌تواند به صورت زیر باشد:

CWord.CreateDocument("test.docx", "سلام دنیا");

این کتابخانه کار ایجاد فایل‌های xml ، تولید روابط بین‌ آنها و همچنین بسته بندی و zip کردن نهایی را به صورت خودکار انجام می‌دهد.

برای مطالعه بیشتر می‌توان به منابع زیر مراجعه نمود:

یک ویدیوی آموزشی رایگان از مایکروسافت
دریافت

سؤالات متداول در MSDN
http://msdn.microsoft.com/en-us/library/bb491088.aspx
البته اگر پس از نصب SDK به پوشه doc آن مراجعه نمائید، این سؤال و جواب‌ها را در فایل راهنمای chm آن نیز می‌توان پیدا کرد.

مثال دیگری در مورد ایجاد یک گزارش از بانک اطلاعاتی و گرفتن خروجی docx از آن
http://openxmldeveloper.org/articles/GenerateWordTable.aspx
البته این مثال خیلی قدیمی است و قسمت‌های کار با پکیج را با SDK‌ ارائه شده می‌توان به صورت خودکار انجام داد. اما حداقل نحوه تولید جداول استاندارد OpenXML را می‌توان از آن ایده گرفت.

مثالی در مورد نحوه قرار دادن عکس در فایل docx تولیدی

همچنین مثال‌های بیشتری را در وبلاگ‌های مربوطه می‌توان یافت:
http://blogs.msdn.com/brian_jones/
http://blogs.msdn.com/ericwhite/default.aspx