با تشکر از زحمات شما
به نظر من استفاده از #F در کنار #C به عنوان Library برای حل مسائل خاص خیلی میتونه مفید باشه
اگه ممکنه در مورد صورت مسئله و راه حلهای ارائه شده با #F بیشتر بنویسید تا بیشتر مورد استفاده قرار بگیره ،و خیلی کاربردیتر موضوع رو ببینیم
ممنون
نکاتی درمورد روشهای تبدیل (Cast) آبجکتها
با سلام
لطفا نکات، انواع روش ها، تفاوت روش ها، میزان استفاده از حافظی اصلی و ... را درمورد تبدیل نوع (cast) آبجکتها در زبان c# به یکدیگر را در طی یک مقاله ارائه نمائید.اکثر برنامه نویسان این روشها را میشناسند و مورد استفاده قرار میدهند ولی شاید روش صحیح تبدبل نوع در برنامه نویسی را به خوبی نشناسند.
با تشکر
C# 7 - Throw Expressions
C#7: Throw Expressions and More Expression-bodied Members
Reasons You Should Use the Brand-New C# 7.0 in Your WebDriver Tests
پیش از ارائه نهایی مطلب، تمام کدهای آن با VS 2017 RTM آزمایش و بررسی شوند.
var facilities = _db.Bookings.GroupBy(c=>c.Facility) .Select(c => new { Name=c.Key.Name, TotalRevenue = c.Sum(s=>s.MemId==0? s.Slots*s.Facility.GuestCost: s.Slots*s.Facility.MemberCost) }) .OrderBy(result => result.TotalRevenue) .ToList();
در این مقاله قصد داریم یک Api تحت وب را با استفاده از فریمورک ASP.NET Core توسعه دهیم تا عملیات CRUD را بر روی دیتابیس MongoDb که یکی از محبوبترین دیتابیسهای NoSql است، انجام دهد. قبل از شروع کار باید ویژوال استودیو نسخهی 2019 را نصب داشته باشید؛ بهطوریکه ورک لود ASP.NET and web development را هم حتما همراه آن نصب کرده باشید. علاوه بر آن باید .Net Core SDK 3.0+ و دیتابیس MongoDb را هم نصب کنید که میتوانید آنها را از آدرسهای زیر دانلود کنید. نگران نصب MongoDb هم نباشید چون نکته خاصی ندارد.
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/
https://dotnet.microsoft.com/download/dotnet-core
نسخهی جاری MongoDb، 4.4 است که پس از نصب، به صورت پیشفرض در آدرس C:\Program Files\MongoDB قرار میگیرد. در مسیر C:\Program Files\MongoDB\Server\4.4\bin فایلهای اصلی MongoDb قرار دارند و برای تعامل با MongoDb، به این فایلها نیاز خواهیم داشت. پس برای اینکه به راحتی بتوان در هر جای سیستم از طریق پاورشل به این فایلها دسترسی داشته باشید، این مسیر را به Path environment variable ویندوز اضافه کنید.
MongoDb دارای یک بخش اصلی یا اصطلاحا یکdaemon است که وظیفهی آن، پردازش درخواستهایی است که برای کار با دادهها صادر میشود. در حقیقت همه کارهایی که ما با دادهها انجام میدهیم مثلا دسترسی به دادهها و دستکاری آنها، از طریق این daemon انجام میگیرد و پشت صحنهی این daemon، با Storage Engine کار خواهد کرد. برای اجرای daemon، پاور شل را باز کنید و دستور mongod را وارد کنید. اگر با تنظیمات پیشفرض اجرا کنید، بر روی پورت 27017 بالا آمده و فایلهای دیتابیس را هم در مسیر C:\data\db قرار میدهد. اگر این مسیر را نداشته باشید، با خطا مواجه میشوید. یا باید این مسیر را تعریف کنید و یا از سوئیچ dbpath -- استفاده کنید تا مسیر فایل دیتابیس را تغییر دهید. پس پاور شل را باز کنید و دستور زیر را وارد کنید.
>> mongod --dbpath C:\BooksData
>> mongo
>> use BookstoreDb
بعد از ساختن دیتابیس، باید یک کالکشن بسازید. کالکشنها را میتوان معادل جداول، در دیتابیسهای رابطهای تصور کرد. با دستور createCollection می توان اینکار را انجام داد. برای اینکار دستور زیر را وارد کنید.
>> db.createCollection('Books')
بعد از ساختن کالکشن، میخواهیم مقداری دیتا را در آن قرار دهیم. معادل رکورد در دیتابیسهای رابطهای، در دیتابیس مونگو دیبی، Document نام دارد که مانند رکوردهای دیتابیسهای رابطهای نیست و ساختار و اسکیمای خاصی ندارد؛ یعنی میتوان هر دیتایی را با هر ساختاری در آن ذخیره کرد. میخواهیم دو Document را به کالکشن Books اضافه کنیم. پس دستور زیر را وارد میکنیم. توجه کنید دادهها با ساختار json وارد میشوند.
>> db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])
{ "acknowledged" : true, "insertedIds" : [ ObjectId("5bfd996f7b8e48dc15ff215d"), ObjectId("5bfd996f7b8e48dc15ff215e") ] }
>> db.Books.find().pretty()
{ "_id" : ObjectId("5bfd996f7b8e48dc15ff215d"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" }, { "_id" : ObjectId("5bfd996f7b8e48dc15ff215e"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Roslyn #1
سکوی کامپایلر دات نت یا Roslyn (با تلفظ «رازلین») بازنویسی مجدد کامپایلرهای VB.NET و #C توسط همین زبانها است. این سکوی کامپایلر به همراه یک سری کتابخانه و اسمبلی ارائه میشود که امکان آنالیز زبانهای مدیریت شده را به صورت مستقل و یا یکپارچهی با ویژوال استودیو، فراهم میکنند. برای نمونه در VS.NET 2015 تمام سرویسهای زبانهای موجود، با Roslyn API جایگزین و بازنویسی شدهاند. نمونههایی از این سرویسهای زبانها، شامل Intellisense و مرور کدها مانند go to references and definitions، به همراه امکانات Refactoring میشوند. به علاوه به کمک Roslyn میتوان یک کامپایلر و ابزارهای مرتبط با آن، مانند FxCop را تولید کرد و یا در نهایت یک فایل اسمبلی نهایی را از آن تحویل گرفت.
چرا مایکروسافت Roslyn را تولید کرد؟
پیش از پروژهی Roslyn، کامپایلرهای VB.NET و #C با زبان ++C نوشته شده بودند؛ از این جهت که در اواخر دههی 90 که کار تولید سکوی دات نت در حال انجام بود، هنوز امکانات کافی برای نوشتن این کامپایلرها با زبانهای مدیریت شده وجود نداشت و همچنین زبان محبوب کامپایلر نویسی در آن دوران نیز ++C بود. این انتخاب در دراز مدت مشکلاتی مانند کاهش انعطاف پذیری و productivity تیم کامپایلر نویس را با افزایش تعداد سطرهای کامپایلر نوشته شده به همراه داشت و افزودن ویژگیهای جدید را به زبانهای VB.NET و #C سختتر و سختتر کرده بود. همچنین در اینجا برنامه نویسهای تیم کامپایلر مدام مجبور بودند که بین زبانهای مدیریت شده و مدیریت نشده سوئیچ کنند و امکان استفادهی همزمان از زبانهایی را که در حال توسعهی آن هستند، نداشتند.
این مسایل سبب شدند تا در طی بیش از یک دهه، چندین نوع کامپایلر از صفر نوشته شوند:
- کامپایلرهای خط فرمانی مانند csc.exe و vbc.exe
- کامپایلر پشت صحنهی ویژوال استودیو (برای مثال کشیدن یک خط قرمز زیر مشکلات دستوری موجود)
- کامپایلر snippetها در immediate window ویژوال استودیو
هر کدام از این کامپایلرها هم برای حل مسایلی خاص طراحی شدهاند. کامپایلرهای خط فرمانی، با چندین فایل ورودی، به همراه ارائهی تعدادی زیادی خطا و اخطار کار میکنند. کامپایلر پشت صحنهی ویژوال استودیوهای تا پیش از نسخهی 2015، تنها با یک تک فایل در حال استفاده، کار میکند و همچنین باید به خطاهای رخ داده نیز مقاوم باشد و بیش از اندازه گزارش خطا ندهد. برای مثال زمانیکه کاربر در حالت تایپ یک سطر است، بدیهی است تا اتمام کار، این سطر فاقد ارزش دستوری صحیحی است و کامپایلر باید به این مساله دقت داشته باشد و یا کامپایلر snippetها تنها جهت ارزیابی یک تک سطر از دستورات وارد شده، طراحی شدهاست.
با توجه به این مسایل، مایکروسافت از بازنویسی سکوی کامپایلر دات نت این اهداف را دنبال میکند:
- بالا بردن سرعت افزودن قابلیتهای جدید به زبانهای موجود
- سبک کردن حجم کاری کامپایلر نویسی و کاهش تعداد آنها به یک مورد
- بالا بردن دسترسی پذیری به API کامپایلرها
برای مثال اکنون برنامه نویسها بجای اینکه یک فایل cs را به کامپایلر csc.exe ارائه کنند و یک خروجی باینری دریافت کنند، امکان دسترسی به syntax trees، semantic analysis و تمام مسایل پشت صحنهی یک کامپایلر را دارند.
- ساده سازی تولید افزونههای مرتبط با زبانهای مدیریت شده.
اکنون برای تولید یک آنالیز کنندهی سفارشی، نیازی نیست هر توسعه دهندهای شروع به نوشتن امکانات پایهای یک کامپایلر کند. این امکانات به صورت یک API عمومی در دسترس برنامه نویسها قرار گرفتهاند.
- آموزش مسایل درونی یک کامپایلر و همچنین ایجاد اکوسیستمی از برنامه نویسهای علاقمند در اطراف آن.
همانطور که اطلاع دارید، Roslyn به صورت سورس باز در GitHub در دسترس عموم است.
تفاوت Roslyn با کامپایلرهای سنتی
اکثر کامپایلرهای موجود به صورت یک جعبهی سیاه عمل میکنند. به این معنا که تعدادی فایل ورودی را دریافت کرده و در نهایت یک خروجی باینری را تولید میکنند. اینکه در این میان چه اتفاقاتی رخ میدهد، از دید استفاده کننده مخفی است.
نمونهای از این کامپایلرهای جعبه سیاه را در تصویر فوق مشاهده میکنید. در اینجا شاید این سؤال مطرح شود که در داخل جعبهی سیاه کامپایلر سیشارپ، چه اتفاقاتی رخ میدهد؟
خلاصهی مراحل رخ داده در کامپایلر سیشارپ را در تصویر فوق ملاحظه میکنید. در اینجا ابتدا کار parse اطلاعات متنی دریافتی شروع میشود و از روی آن syntax tree تولید میشود. در مرحلهی بعد مواردی مانند ارجاعاتی به mscorlib و امثال آن پردازش میشوند. در مرحلهی binder کار پردازش حوزهی دید متغیرها، اشیاء و اتصال آنها به هم انجام میشود. در مرحلهی آخر، کار تولید کدهای IL و اسمبلی باینری نهایی صورت میگیرد.
با معرفی Roslyn، این جعبهی سیاه، به صورت یک API عمومی در دسترس برنامه نویسها قرار گرفتهاست:
همانطور که مشاهده میکنید، هر مرحلهی کامپایل جعبهی سیاه، به یک API عمومی Roslyn نگاشت شدهاست. برای مثال Parser به Syntax tree API نگاشت شدهاست. به علاوه این API صرفا به موارد فوق خلاصه نمیشود و همانطور که پیشتر نیز ذکر شد، برای اینکه بتواند جایگزین سه نوع کامپایلر موجود شود، به همراه Workspace API نیز میباشد:
Roslyn امکان کار با یک Solution و فایلهای آن را دارد و شامل سرویسهای زبانهای مورد نیاز در ویژوال استودیو نیز میشود. برفراز Workspace API، یک مجموعه API دیگر به نام Diagnostics API تدارک دیده شدهاست تا برنامه نویسها بتوانند امکانات Refactoring جانبی را توسعه داده و یا در جهت بهبود کیفیت کدهای نوشته شده، اخطارهایی را به برنامه نویسها تحت عنوان Code fixes و آنالیز کنندهها، ارائه دهند.
سؤال: مرورگر چه زمانی از کش محلی خودش استفاده خواهد کرد (بدون ارسال درخواستی به سرور) و چه زمانی مجددا از سرور درخواست دریافت مجدد این عنصر کش شده را میکند؟
برای پاسخ دادن به این سؤال نیاز است با مفهومی به نام Conditional Requests (درخواستهای شرطی) آشنا شد که در ادامه به بررسی آن خواهیم پرداخت.
درخواستهای شرطی
مرورگرهای وب دو نوع درخواست شرطی و غیر شرطی را توسط پروتکل HTTP و HTTPS ارسال میکنند. دراینجا، زمانی یک درخواست غیرشرطی ارسال میشود که نسخهی ذخیره شدهی محلی منبع مورد نظر، مهیا نباشد. در این حالت، اگر منبع درخواستی در سرور موجود باشد، در پاسخ ارسالی خود وضعیت 200 یا HTTP/200 OK را باز میگرداند. اگر هدرهای دیگری نیز مانند کش کردن منبع در اینجا تنظیم شده باشند، مرورگر نتیجهی دریافتی را برای استفادهی بعدی ذخیره خواهد کرد.
در بار دومی که منبع مفروضی درخواست میگردد، مرورگر ابتدا به کش محلی خود نگاه خواهد کرد. همچنین در این حالت نیاز دارد که بداند این کش معتبر است یا خیر؟ برای بررسی این مورد ابتدا هدرهای ذخیره شده به همراه منبع، بررسی میشوند. پس از این بررسی اگر مرورگر به این نتیجه برسد که کش محلی معتبر است، دیگر درخواستی را به سرور ارسال نخواهد کرد.
اما در آینده اگر مدت زمان کش شدن تنظیم شده توسط هدرهای مرتبط، منقضی شده باشد (برای مثال با توجه به max-age هدر کش شدن منبع)، مرورگر هنوز هم درخواست کاملی را برای دریافت نسخهی جدید منبع مورد نیاز، به سرور ارسال نمیکند. در اینجا ابتدا یک conditional request را به وب سرور ارسال میکند (یک درخواست شرطی). این درخواست شرطی تنها دارای هدرهای If-Modified-Since و یا If-None-Match است و هدف از آن سؤال پرسیدن از وب سرور است که آیا این منبع خاص، در سمت سرور اخیرا تغییر کردهاست یا خیر؟ اگر پاسخ سرور خیر باشد، باز هم از همان کش محلی استفاده خواهد شد و مجددا درخواست کاملی برای دریافت نمونهی جدیدتر منبع مورد نیاز، به سرور ارسال نمیگردد.
پاسخی که سرور جهت مشخص سازی عدم تغییر منابع خود ارسال میکند، با هدر HTTP/304 Not Modified مشخص میگردد (این پاسخ هیچ body خاصی نداشته و فقط یک سری هدر است). اما اگر منبع درخواستی اخیرا تغییر کرده باشد، پاسخ HTTP/200 OK را در هدر بازگشت داده شده، به مرورگر بازخواهد گرداند (یعنی محتوا را مجددا دریافت کن).
چه زمانی مرورگر درخواستهای شرطی If-Modified-Since را به سرور ارسال میکند؟
اگر یکی از شرایط ذیل برقرار باشد، مرورگر حتی اگر تاریخ کش شدن منبع ویژهای به 10 سال بعد تنظیم شده باشد، مجددا یک درخواست شرطی را برای بررسی اعتبار کش محلی خود به سرور ارسال میکند:
الف) کش شدن بر اساس هدر خاصی به نام vary صورت گرفتهاست (برای مثال بر اساس id یا نام یک فایل).
ب) اگر نحوهی هدایت به صفحهی جاری از طریق META REFRESH باشد.
ج) اگر از طریق کدهای جاوا اسکریپتی، دستور reload صفحه صادر شود.
د) اگر کاربر دکمهی refresh را فشار دهد.
ه) اگر قسمتی از صفحه توسط پروتکل HTTP و قسمتی دیگر از آن توسط پروتکل HTTPS ارائه شود.
و ... اگر بر اساس هدر تاریخ مدت زمان کش شدن منبع، زمان منقضی شدن آن فرا رسیده باشد.
مدیریت درخواستهای شرطی در ASP.NET MVC
تا اینجا به این نکته رسیدیم که قرار دادن ویژگی Output cache بر روی یک اکشن متد، الزاما به معنای کش شدن آن تا مدت زمان تعیین شده نخواهد بود و مرورگر ممکن است (در یکی از 6 حالت ذکر شده فوق) توسط ارسال هدر If-Modified-Since ، سعی در تعیین اعتبار کش محلی خود کند و اگر پاسخ 304 را از سرور دریافت نکند، حتما نسبت به دریافت مجدد و کامل آن منبع اقدام خواهد کرد.
سؤال: چگونه میتوان هدر If-Modified-Since را در ASP.NET MVC مدیریت کرد؟
پاسخ: اگر از فیلتر OutputCache استفاده میکنید، به صورت خودکار هدر Last-Modified را اضافه میکند؛ اما این مورد کافی نیست.
در ادامه یک کنترلر و اکشن متد GetImage آنرا ملاحظه میکنید که تصویری را از مسیر app_data/images خوانده و بازگشت میدهد. همچنین این تصویر بازگشت داده شده را نیز با توجه به OutputCache آن به مدت یک ماه کش میکند.
using System.IO; using System.Web.Mvc; namespace MVC4Basic.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } const int AMonth = 30 * 86400; [OutputCache(Duration = AMonth, VaryByParam = "name")] public ActionResult GetImage(string name) { name = Path.GetFileName(name); var path = Server.MapPath(string.Format("~/app_data/images/{0}", name)); var content = System.IO.File.ReadAllBytes(path); return File(content, "image/png", name); } } }
<img src="@Url.Action("GetImage","Home", new { name = "test.png"})"/>
بار اول که صفحهی اول برنامه درخواست میشود، یک چنین هدرهایی رد و بدل خواهند شد (توسط ابزارهای توکار مرورگر وب کروم تهیه شدهاست؛ همان دکمهی F12 معروف):
Remote Address:127.0.0.1:5656 Request URL:http://localhost:10419/Home/GetImage?name=test.png Request Method:GET Status Code:200 OK Response Headers Cache-Control:public, max-age=2591916 Expires:Sat, 31 May 2014 12:45:55 GMT Last-Modified:Thu, 01 May 2014 12:45:55 GMT
در همین حال اگر صفحه را ریفرش کنیم (فشردن دکمهی F5)، اینبار هدرهای حاصل چنین شکلی را پیدا میکنند:
Remote Address:127.0.0.1:5656 Request URL:http://localhost:10419/Home/GetImage?name=test.png Request Method:GET Status Code:304 Not Modified Request Headers If-Modified-Since:Thu, 01 May 2014 12:45:55 GMT
در ادامه بجای اینکه صفحه را ریفرش کنیم، یکبار دیگر در نوار آدرس آن، دکمهی Enter را فشار خواهیم داد تا آدرس موجود در آن (ریشه سایت) مجددا در حالت معمولی دریافت شود.
Remote Address:127.0.0.1:5656 Request URL:http://localhost:10419/Home/GetImage?name=test.png Request Method:GET Status Code:200 OK (from cache)
مشکل! مرورگر را ببندید، تا کار دیباگ برنامه خاتمه یابد. مجددا برنامه را اجرا کنید. مشاهده خواهید کرد که ... اجرای برنامه در Break point قرار گرفته در سطر اول متد GetImage متوقف میشود. چرا؟! مگر قرار نبود تا یک ماه دیگر کش شود؟! هدر رد و بدل شده نیز Status Code:200 OK کامل است (که سبب دریافت کامل فایل میشود).
Remote Address:127.0.0.1:5656 Request URL:http://localhost:10419/Home/GetImage?name=test.png Request Method:GET Status Code:200 OK Request Headers If-Modified-Since:Thu, 01 May 2014 12:45:55 GMT
using System; using System.IO; using System.Net; using System.Web.Mvc; namespace MVC4Basic.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } const int AMonth = 30 * 86400; [OutputCache(Duration = AMonth, VaryByParam = "name")] public ActionResult GetImage(string name) { name = Path.GetFileName(name); var path = Server.MapPath(string.Format("~/app_data/images/{0}", name)); var lastWriteTime = System.IO.File.GetLastWriteTime(path); this.Response.Cache.SetLastModified(lastWriteTime.ToUniversalTime()); var header = this.Request.Headers["If-Modified-Since"]; if (!string.IsNullOrWhiteSpace(header)) { DateTime isModifiedSince; if (DateTime.TryParse(header, out isModifiedSince) && isModifiedSince > lastWriteTime) { return new HttpStatusCodeResult(HttpStatusCode.NotModified); } } var content = System.IO.File.ReadAllBytes(path); return File(content, "image/png", name); } } }
برای امتحان آن همانطور که عنوان شد فقط کافی است یکبار مرورگر خود را کاملا بسته و مجددا برنامه را اجرا کنید.
Remote Address:127.0.0.1:5656 Request URL:http://localhost:10419/Home/GetImage?name=test.png Request Method:GET Status Code:304 Not Modified Request Headers If-Modified-Since:Thu, 01 May 2014 13:43:32 GMT
موارد کاربرد
اکثر فید خوانهای معروف نیز ابتدا هدر If-Modified-Since را ارسال میکنند و سپس (اگر چیزی تغییر کرده بود) محتوای فید شما را دریافت خواهند کرد. بنابراین برای کاهش بار برنامه و هچنین کاهش میزان انتقال دیتای سایت، مدیریت آن در حین ارائه محتوای پویای فیدها نیز بهتر است صورت گیرد. همچنین هر جایی که قرار است فایلی به صورت پویا به کاربران ارائه شود؛ مانند مثال فوق.
تبدیل این کدها به روش سازگار با ASP.NET MVC
ما در اینجا رسیدیم به یک سری کد تکراری if و else که باید در هر اکشن متدی که OutputCache دارد، تکرار شود. روش AOP وار آن در ASP.NET MVC، تبدیل این کدها به یک فیلتر با قابلیت استفادهی مجدد است:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class SetIfModifiedSinceAttribute : ActionFilterAttribute { public string Parameter { set; get; } public string BasePath { set; get; } public override void OnActionExecuting(ActionExecutingContext filterContext) { var response = filterContext.RequestContext.HttpContext.Response; var request = filterContext.RequestContext.HttpContext.Request; var path = getPath(filterContext); if (string.IsNullOrWhiteSpace(path)) { response.StatusCode = (int)HttpStatusCode.NotFound; filterContext.Result = new EmptyResult(); return; } var lastWriteTime = File.GetLastWriteTime(path); response.Cache.SetLastModified(lastWriteTime.ToUniversalTime()); var header = request.Headers["If-Modified-Since"]; if (string.IsNullOrWhiteSpace(header)) return; DateTime isModifiedSince; if (DateTime.TryParse(header, out isModifiedSince) && isModifiedSince > lastWriteTime) { response.StatusCode = (int)HttpStatusCode.NotModified; response.SuppressContent = true; filterContext.Result = new EmptyResult(); } } string getPath(ActionExecutingContext filterContext) { if (!filterContext.ActionParameters.ContainsKey(Parameter)) return string.Empty; var name = filterContext.ActionParameters[Parameter] as string; if (string.IsNullOrWhiteSpace(name)) return string.Empty; var path = Path.GetFileName(name); path = filterContext.HttpContext.Server.MapPath(string.Format("{0}/{1}", BasePath, path)); return !File.Exists(path) ? string.Empty : path; } }
و برای استفاده از آن خواهیم داشت:
[SetIfModifiedSince(Parameter = "name", BasePath = "~/app_data/images/")] [OutputCache(Duration = AMonth, VaryByParam = "name")] public ActionResult GetImage(string name) { name = Path.GetFileName(name); var path = Server.MapPath(string.Format("~/app_data/images/{0}", name)); var content = System.IO.File.ReadAllBytes(path); return File(content, "image/png", name); }
خلاصهی بحث
چون فیلتر OutputCache در ASP.NET MVC، هدر If-Modified-Since را پردازش نمیکند (از این جهت که پردازش آن برای نمونه در مثال فوق وابسته به منطق خاصی است و عمومی نیست)، اگر با هر بار گشودن سایت خود مشاهده کردید، تصاویر پویایی که قرار بوده یک ماه کش شوند، دوباره از سرور درخواست میشوند (البته به ازای هرباری که مرورگر از نو اجرا میشود و نه در دفعات بعدی که صفحات سایت با همان وهلهی ابتدایی مرور خواهند شد)، نیاز است خودتان دسترسی کار پردازش هدر If-Modified-Since را انجام داده و سپس status code 304 را در صورت نیاز، ارسال کنید.
و در حالت عمومی، طراحی سیستم caching محتوای پویای شما بدون پردازش هدر If-Modified-Since ناقص است (تفاوتی نمیکند که از کدام فناوری سمت سرور استفاده میکنید).
برای مطالعه بیشتر
Understanding Conditional Requests and Refresh
Use If-Modified-Since header in ASP.NET
Make your browser cache the output of an HttpHandler
304 Your images from a database
Conditional GET
Website Performance with ASP.NET - Part4 - Use Cache Headers
ASP.NET MVC 304 Not Modified Filter for Syndication Content
چگونه فایلهای PDF را نمایش دهیم؟
استفاده از کنترلهای Active-X در WPF
نمایش یک فایل PDF در WinForms ، WPF و سیلورلایت
همچنین روشهای دیگری که عموما مبتنی بر تبدیل PDF به تصویر هستند نیز جهت نمایش فایلهای PDF کاربرد دارند. در لینک ذیل، جمع آوری مطالب مرتبطی را خواهید یافت:
iTextSharp
به علاوه مرورگرهای مدرن نیز در پی ارائه پشتیبانی توکاری از نمایش فایلهای PDF هستند. برای نمونه میتوان به پروژه PDF.js فایرفاکس که از نگارش 15 آن جرئی از فایرفاکس شده است، اشاره کرد.
الف) اگر از Web forms استفاده میکنید: استفاده از Script manager (^ و ^)
ب) اگر از MVC استفاده میکنید: استفاده از Bundling & minification
در هر دو حالت نحوه ارائه اسکریپتها تحت کنترل برنامه ASP.NET در خواهد آمد و مستقیما و بدون دخالت ASP.NET، توسط IIS توزیع نمیشوند.
- برای مپ کردن فایلهای استاتیک به موتور ASP.NET میشود از StaticFileHandler استفاده کرد. اگر کش کردن اطلاعات استاتیک در سمت سرور فعال شود، این مساله بار اضافهای را به سرور تحمیل نخواهد کرد.
<system.web> <httpHandlers> <add path="*.js" verb="*" type="System.Web.StaticFileHandler" /> </httpHandlers>