مسیرراه‌ها
WPF
          مطالب
          استفاده از Razor در فایل‌های JavaScript و CSS
          یکی از مشکلات سینتکس Razor سمت سرور، این است که در فایل‌های JavaScript و CSS سمت کاربر نمی‌توانیم از آن استفاده کنیم، به عنوان مثال فرض کنید در یک فایل JavaScript نیاز به مشخص سازی آدرس یک اکشن متد دارید؛ مثلاً انجام یک عملیات ای‌جکسی. در این حالت به عنوان یک Best Practice بهتر است از Url.Action استفاده کنید. اما همانطور که عنوان شد، این امکان یعنی استفاده از سینتکس Razor در فایل‌های JS و CSS مهیا نیست.
          ساده‌ترین راه‌حل، تولید ویوهای سمت سرور JavaScript ایی است. برای اینکار تنها کاری که باید انجام دهیم، تغییر مقدار Content-Type صفحه به مقدار موردنظر می‌باشد؛ مثلاً text/javascript برای فایل‌های JS و text/css برای فایل‌های CSS. به عنوان مثال برای فایل‌های CSS به این صورت عمل خواهیم کرد:
          public ActionResult Style()
          {
                      Response.ContentType = "text/css";
                      var model = new Style
                      {
                          Color = "red",
                          Background = "blue"
                      };
                      return View(model);
          }
          برای ویوی آن نیز خواهیم داشت:
          @model ExternalJavaScript.Models.Style
          @{
              Layout = null;
          }
          body {
              color : @Model.Color;
              background-color : @Model.Background;
          }
          در نهایت ویوی فوق را به عنوان فایل CSS در فایل Layout استفاده خواهیم کرد:
          <link rel="stylesheet" href="@Url.Action("Style","Home")" />
          برای حالت فوق می‌توانیم یک اکشن فیلتر به صورت زیر تهیه کنیم:
          public class ContentType : ActionFilterAttribute
              {
                  private string _contentType;
                  public ContentType(string ct)
                  {
                      this._contentType = ct;
                  }
          
                  public override void OnActionExecuted(ActionExecutedContext context) { /* nada */ }
                  public override void OnActionExecuting(ActionExecutingContext context)
                  {
                      context.HttpContext.Response.ContentType = this._contentType;
                  }
              }
          و برای استفاده از آن خواهیم داشت:
          [ContentType("text/css")]
          public ActionResult Style()
           {
               var model = new Style
                {
                          Color = "red",
                          Background = "blue"
                };
               return View(model);
          }

          برای فایل‌های JS نیز می‌توانیم از یک View به عنوان محل قرارگیری کدهای جاوا اسکریپت استفاده کنیم:
          public class JavaScriptSettingsController : Controller
          {
                  public ActionResult Index()
                  {
                      return PartialView();
                  }
          }
          در این حالت در داخل فایل Index.cshtml کدهای جاوا اسکریپت را همراه با سینتکس Razor می‌توانیم بنویسیم:
          $(function(){
              $.post('@Url.Action("GetData", "Home")', function (data) {
                  $('.notificationList').html(data);
                      if ($(data).filter("li").length != 0) {
                          $('#notificationCounter').html($(data).filter("li").length);
                      }
              });
          });
          سپس در داخل فایل Layout.cshtml_ می‌توانیم به ویوی فوق ارجاعی داشته باشیم:
          <script src="/JavaScriptSettings"></script>
          این روش به خوبی برای ویوهای JS و CSS کار خواهد کرد؛ اما از آنجائیکه ویوی ما توسط ویژوال استودیو به عنوان یک فایل JS و یا CSS معتبر شناخته نمی‌شود، Intellisense برای آن مهیا نیست. برای فعال سازی Intellisense و همچنین معتبر شناخته شدن ویوی فوق، بهترین راه‌حل قرار دادن کدهای JS درون بلاک script است (برای فایل‌های CSS نیز همینطور):
          <script>
              $(function () {
                  $.post('@Url.Action("Index", "Home")', function (data) {
                      $('.notificationList').html(data);
                      if ($(data).filter("li").length != 0) {
                          $('#notificationCounter').html($(data).filter("li").length);
                      }
                  });
              });
          </script>
          اما با اجرای برنامه، در کنسول مرورگر بلافاصله خطای Uncaught SyntaxError: Unexpected token < را دریافت خواهید کرد. در این حالت به روشی نیاز داریم که در زمان اجرا بلاک script را حذف نمائید. بنابراین از یک اکشن فیلتر سفارشی برای اینکار استفاده خواهیم کرد. کار این اکشن فیلتر، تغییر مقدار Content-Type و همچنین حذف بلاک مورد نظر می‌باشد:
          public class ExternalFileAttribute : ActionFilterAttribute
              {
                  private readonly string _contentType;
                  private readonly string _tag;
                  public ExternalFileAttribute(string ct, string tag)
                  {
                      this._contentType = ct;
                      _tag = tag;
                  }
          
                  public override void OnResultExecuted(ResultExecutedContext filterContext)
                  {
                      var response = filterContext.HttpContext.Response;
                      response.Filter = new StripEnclosingTagsFilter(response.Filter, _tag);
                      response.ContentType = _contentType;
                  }
          
                  private class StripEnclosingTagsFilter : MemoryStream
                  {
                      private static Regex _leadingOpeningScriptTag;
                      private static Regex _trailingClosingScriptTag;
          
                      //private static string Tag;
          
                      private readonly StringBuilder _output;
                      private readonly Stream _responseStream;
          
                      /*static StripEnclosingTagsFilter()
                      {
                          LeadingOpeningScriptTag = new Regex(string.Format(@"^\s*<{0}[^>]*>", Tag), RegexOptions.Compiled);
                          TrailingClosingScriptTag = new Regex(string.Format(@"</{0}>\s*$", Tag), RegexOptions.Compiled);
                      }*/
          
                      public StripEnclosingTagsFilter(Stream responseStream, string tag)
                      {
                          _leadingOpeningScriptTag = new Regex(string.Format(@"^\s*<{0}[^>]*>", tag), RegexOptions.Compiled);
                          _trailingClosingScriptTag = new Regex(string.Format(@"</{0}>\s*$", tag), RegexOptions.Compiled);
          
                          _responseStream = responseStream;
                          _output = new StringBuilder();
                      }
          
                      public override void Write(byte[] buffer, int offset, int count)
                      {
                          string response = GetStringResponse(buffer, offset, count);
                          _output.Append(response);
                      }
          
                      public override void Flush()
                      {
                          string response = _output.ToString();
          
                          if (_leadingOpeningScriptTag.IsMatch(response) && _trailingClosingScriptTag.IsMatch(response))
                          {
                              response = _leadingOpeningScriptTag.Replace(response, string.Empty);
                              response = _trailingClosingScriptTag.Replace(response, string.Empty);
                          }
          
                          WriteStringResponse(response);
                          _output.Clear();
                      }
          
                      private static string GetStringResponse(byte[] buffer, int offset, int count)
                      {
                          byte[] responseData = new byte[count];
                          Buffer.BlockCopy(buffer, offset, responseData, 0, count);
          
                          return Encoding.Default.GetString(responseData);
                      }
          
                      private void WriteStringResponse(string response)
                      {
                          byte[] outdata = Encoding.Default.GetBytes(response);
                          _responseStream.Write(outdata, 0, outdata.GetLength(0));
                      }
                  }
              }
           در نهایت می‌توانیم اکشن‌متد موردنظرمان را با فیلتر سفارشی مزین کنیم:
          [ExternalFile("text/javascript", "script")]
          public ActionResult Index()
          {
                return PartialView();
          }
          برای تولید ویوهای CSS نیز کافی است مقادیر فیلتر را تغییر دهیم:
          [ExternalFile("text/css", "style")]
          public ActionResult Style()
          {
                      var model = new Style
                      {
                          Color = "red",
                          Background = "blue"
                      };
                      return View(model);
          }
          نظرات مطالب
          ارتقاء به ASP.NET Core 1.0 - قسمت 19 - بومی سازی
          - اگر از ویندوز 10 که تاریخ شمسی آن فعال شده استفاده کنید، این مورد بعد از تنظیم فرهنگ ترد جاری، شمسی نمایش داده می‌شود (امتحان کردم).
          - ولی درکل بهتر است این تنظیمات استاندارد را تغییر ندهید و از متدهای الحاقی استفاده کنید (هرجایی که نیاز هست و نه به صورت سراسری با دستکاری جزئیات فرهنگ جاری؛ چون اثرات جانبی نامطلوبی را می‌توانند به همراه داشته باشند).
          نظرات مطالب
          خلاصه اشتراک‌های روز جمعه 4 آذر 1390
          یک سری توهماتی این دور و اطراف هست مانند اینکه لینوکس نیازی به ویروس یاب نداره، لینوکس امنه، لینوکس خیلی گله! بی نظیر‌تر از اون نیست؛ ولی واقعیت این است که این سیستم عامل زمانیکه از اون حد کاربران یک یا چند درصدی دستکاپ خودش فاصله می‌گیره و مثلا میشه Android، تازه مشخص میشه که ای بابا! ویندوز هم امنه! اگر کاربری نمی‌دونه هر فایلی رو نباید اجرا کنه، هر دسترسی رو نباید بده این مشکل سیستم عامل نیست. ولی خوب این هجمه سیاسی و عموما کودکانه علیه ویندوز وجود داره و گاهی هم لازم هست این‌ها رو کمی عیان‌تر بیان کرد با مثال‌های دنیای واقعی تا کمی از توهمات دور بشیم که بله؛ اگر از کاربران حرفه‌ای سرورها فاصله بگیریم می‌رسیم به «عوام». میرسیم به دنیایی خارج از یک یا چند درصد کاربری دسکتاپ. اینجا است که حالا باید دید سیستم عامل تا چه حد می‌تونه مؤثر واقع بشه، یا اینکه رکورد بزنه تا تاریخ امروز.
          مطالب
          بررسی تغییرات Blazor 8x - قسمت ششم - نکات تکمیلی ویژگی راهبری بهبود یافته‌ی صفحات SSR


          در قسمت قبل، در حین بررسی رفتار جزیره‌های تعاملی Blazor Server، نکته‌ی زیر را هم درباره‌ی راهبری صفحات SSR مرور کردیم:
          « اگر دقت کنید، جابجایی بین صفحات، با استفاده از fetch انجام شده؛ یعنی با اینکه این صفحات در اصل static HTML خالص هستند، اما ... کار full reload صفحه مانند ASP.NET Web forms قدیمی انجام نمی‌شود (و یا حتی برنامه‌های MVC و Razor pages) و نمایش صفحات، Ajax ای است و با fetch استاندارد آن صورت می‌گیرد تا هنوز هم حس و حال SPA بودن برنامه حفظ شود. همچنین اطلاعات DOM کل صفحه را هم به‌روز رسانی نمی‌کند؛ فقط موارد تغییر یافته در اینجا به روز رسانی خواهند شد.»
          در این قسمت، نکات تکمیلی این قابلیت را که به آن enhanced navigation هم گفته می‌شود، بررسی می‌کنیم.


          روش غیرفعال کردن راهبری بهبودیافته برای بعضی از لینک‌ها

          ویژگی راهبری بهبودیافته فقط در حین هدایت بین صفحات مختلف یک برنامه‌ی Blazor 8x SSR، فعال است. اگر در این بین، کاربری به یک صفحه‌ی غیر بلیزری هدایت شود، راهبری بهبود یافته شکست خورده و سعی می‌کند حالت full document load را پیاده سازی و اجرا کند. مشکل اینجاست که در این حالت دو درخواست ارسال می‌شود: ابتدا حالت راهبری بهبودیافته فعال می‌شود و در ادامه پس از شکست این راهبری، هدایت مستقیم صورت می‌گیرد. برای رفع این مشکل می‌توان ویژگی جدید data-enhance-nav را با مقدار false، به لینک‌های خارجی مدنظر اضافه کرد تا برای این حالت‌ها دیگر ویژگی راهبری بهبودیافته فعال نشود:
          <a href="/not-blazor" data-enhance-nav="false">A non-Blazor page</a>


          فعالسازی مدیریت بهبودیافته‌ی فرم‌های SSR

          در قسمت چهارم این سری با فرم‌های جدید SSR مخصوص Blazor 8x آشنا شدیم. این فرم‌ها هم می‌توانند از امکانات راهبری بهبود یافته استفاده کنند (یعنی مدیریت ارسال آن، توسط fetch API انجام شده و به روز رسانی قسمت‌های تغییریافته‌ی صفحه را Ajax ای انجام دهند)؛ برای نمونه اینبار همانند تصویر زیر، از fetch استاندارد برای ارسال اطلاعات به سمت سرور کمک گرفته می‌شود (یعنی عملیات Ajax ای شده‌؛ بجای یک post-back معمولی):


           اما ... این قابلیت به صورت پیش‌فرض در فرم‌های تعاملی SSR غیرفعال است. چون همانطور که عنوان شد، اگر مقصد این فرم، یک آدرس غیربلیزری باشد، دوبار ارسال فرم صورت خواهد گرفت؛ یکبار با استفاده از fetch API و بار دیگر پس از شکست، به صورت معمولی. اما اگر مطمئن هستید که endpoint این فرم، قطعا یک کامپوننت بلیزری است، بهتر است این قابلیت را در یک چنین فرم‌هایی نیز به صورت زیر فعال کنید:
          <form method="post" @onsubmit="() => submitted = true" @formname="name" data-enhance>
              <AntiforgeryToken />
              <InputText @bind-Value="Name" />
              <button>Submit</button>
          </form>
          
          @if (submitted)
          {
              <p>Hello @Name!</p>
          }
          
          @code {
          
              bool submitted;
          
              [SupplyParameterFromForm]
              public string Name { get; set; } = "";
          }
          البته باتوجه به اینکه در اینجا هم می‌توان از EditForm‌ها استفاده کرد، در این حالت فقط کافی است ویژگی Enhance را به آن‌ها اضافه نمائید:
          <EditForm method="post" Model="NewCustomer" OnValidSubmit="() => submitted = true" FormName="customer" Enhance>
              <DataAnnotationsValidator />
              <ValidationSummary/>
              <p>
                  <label>
                      Name: <InputText @bind-Value="NewCustomer.Name" />
                  </label>
              </p>
              <button>Submit</button>
          </EditForm>
          
          @if (submitted)
          {
              <p id="pass">Hello @NewCustomer.Name!</p>
          }
          
          @code {
              bool submitted = false;
          
              [SupplyParameterFromForm]
              public Customer? NewCustomer { get; set; }
          
              protected override void OnInitialized()
              {
                  NewCustomer ??= new();
              }
          
               public class Customer
              {
                  [StringLength(3, ErrorMessage = "Name is too long")]
                  public string? Name { get; set; }
              }
          }

          نکته‌ی مهم: در این حالت فرض بر این است که هیچگونه هدایتی به یک Non-Blazor endpoint صورت نمی‌گیرید؛ وگرنه با یک خطا مواجه خواهید شد.



          غیرفعال کردن راهبری بهبودیافته برای قسمتی از صفحه

          اگر با استفاده از جاواسکریپت و خارج از کدهای بیلزر، اطلاعات DOM را به‌روز رسانی می‌کنید، ویژگی راهبری بهبودیافته، از آن آگاهی نداشته و به صورت خودکار تمام تغییرات شما را بازنویسی می‌کند. به همین جهت اگر نیاز است قسمتی از صفحه را که مستقیما توسط کدهای جاواسکریپتی تغییر می‌دهید، از به‌روز رسانی‌های این قابلیت مصون نگه‌دارید، می‌توانید ویژگی جدید data-permanent را به آن قسمت اضافه کنید:
          <div data-permanent>
              Leave me alone! I've been modified dynamically.
          </div>


          امکان آگاه شدن از بروز راهبری بهبودیافته در کدهای جاواسکریپتی

          اگر به هردلیلی در کدهای جاواسکریپتی خودنیاز به آگاه شدن از وقوع یک هدایت بهبودیافته را دارید (برای مثال جهت بازنویسی تغییرات ایجاد شده‌ی توسط آن)، می‌توانید به نحو زیر، مشترک رخ‌دادهای آن شوید:
          <script>
              Blazor.addEventListener('enhancedload', () => {
                  console.log('enhanced load event occurred');
              });
          </script>


          ویژگی جدید Named Element Routing در Blazor 8x

          Blazor 8x از ویژگی مسیریابی سمت کلاینت به کمک تعریف URL fragments پشتیبانی می‌کند. به این صورت رسیدن (اسکرول) به یک قسمت از صفحه‌ای طولانی، بسیار ساده می‌شود.
          برای مثال المان h2 با id مساوی targetElement را درنظر بگیرید:
          <div class="border border-info rounded bg-info" style="height:500px"></div>
          
          <h2 id="targetElement">Target H2 heading</h2>
          <p>Content!</p>
          در Blazor 8x برای رسیدن به آن، هر سه حالت زیر میسر هستند:
          <a href="/counter#targetElement">
          
          <NavLink href="/counter#targetElement">
          
          Navigation.NavigateTo("/counter#targetElement");


          معرفی متد جدید Refresh در Blazor 8x

          در Blazor 8x، امکان بارگذاری مجدد صفحه با فراخوانی متد جدید NavigationManager.Refresh(bool forceLoad = false) میسر شده‌است. این متد در حالت پیش‌فرض از قابلیت راهبری بهبودیافته برای به روز رسانی صفحه استفاده می‌کند؛ مگر اینکه اینکار میسر نباشد. اگر آن‌را با پارامتر true فراخوانی کنید، full-page reload رخ خواهد داد.
          همین اتفاق در مورد متد Navigation.NavigateTo نیز رخ‌داده‌است. این متد نیز در Blazor 8x به صورت پیش‌فرض بر اساس قابلیت راهبری بهبود یافته کار می‌کند؛ مگر اینکه اینکار میسر نباشد و یا پارامتر forceLoad آن‌را به true مقدار دهی کنید.
          مطالب
          غلط یاب فارسی در دات نت با استفاده از امکانات open office

          مدتی است که محصور کننده‌ای سورس باز برای امکانات غلط‌ یاب مجموعه‌ی open office در سایت code project ارائه شده است:
          NHunspell - Hunspell for the .NET platform
          دریافت آخرین نسخه‌ی آن از source forge

          خوشبختانه کتابخانه‌ی واژه‌های فارسی هم برای اپن آفیس مهیا است.
          دریافت

          پس از دریافت کتابخانه‌ی فوق و همچنین فایل‌های مربوط به زبان فارسی، فقط کافی است ارجاعی به اسمبلی NHunspell.dll در برنامه اضافه شود و سپس یک مثال ساده در مورد استفاده از آن به صورت زیر خواهد بود:

          using System;
          using System.Collections.Generic;
          using System.Windows.Forms;
          using NHunspell;

          namespace testWinForms87
          {
          class CSpellCheck
          {
          public static void Test()
          {
          using (Hunspell hunspell = new Hunspell(@"fa_ir.aff", @"fa_ir.dic"))
          {
          bool correct = hunspell.Spell("دباق");
          if (correct)
          MessageBox.Show("مشکلی نیست!");
          else
          {
          List<string> suggestions = hunspell.Suggest("دباق");
          string result = string.Empty;
          foreach (string suggestion in suggestions)
          {
          result += suggestion + Environment.NewLine;
          }

          if (result != string.Empty)
          MessageBox.Show(result,"لیست پیشنهادها");
          }
          }
          }
          }
          }




          مطالب
          نحوه نمایش منوهای Visual studio 2012 با حروف کوچک
          چند روز پیش بصورت اتفاقی به این فکر افتادم که چرا منوهای visual studio 2012 برخلاف ظاهر زیبای خود محیط، اینقدر زمخت و با حروف بزرگ نوشته است.


          و اینکه به چه صورت میتوانم آنها را بصورت حروف کوچک نمایش دهم و حس کنجکاوی اونم از نوع مخصوص گل کرد.


          برای اینکار دو روش وجود دارد :
          روش 1 - تغییر مقدار در رجیستری سیستم عامل ویندوز
           بدین صورت که شما باید به این مسیر مراجعه نموده
          در ویندوز 7 :
            HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\General\
          در ویندوز 8 :
           HKEY_CURRENT_USER\Software\Microsoft\VSWinExpress\11.0\General\
          در نسخه web express:
           HKEY_CURRENT_USER\Software\Microsoft\VSWDExpress\11.0\General\

          ایجاد یک کلید از نوع DWORD :


          و با نام SuppressUppercaseConversion و با مقدار 1 در مسیر یاد شده تنظیم نمائید.

           
          سپس راه اندازی مجدد visual studio  و مشاهده منوهای تغییر یافته .

          روش 2 - کسانی مثل من کمی تنبل هستند و از این کارهای فوق دوست ندارند راه آسانتر را میتوانند تجربه کنند بصورت ذیل:
           
           در منوی start ویندوز با تایپ کلمه powershell  و انتخاب Windows PowerShell به صفحه‌ای آبی رنگ (در ویندوز 7 ) وارد میشود .


           دستور ذیل را کپی و به پنجره powershell انتقال دهید :
          Set-ItemProperty -Path HKCU:\Software\Microsoft\VisualStudio\11.0\General -Name SuppressUppercas
          eConversion -Type DWord -Value 1

            سپس راه اندازی مجدد visual studio  و مشاهده منوهای تغییر یافته   
          اشتراک‌ها
          نصب لینوکس بر روی ویندوز به صورت مستقیم و بدون VMWare!

          خبر خوب اینکه مایکروسافت از نسخه‌ی 1607 ویندوز 10، قابلیت WSL رو به سیستم‌عامل خودش اضافه کرده که به ما این امکان رو میده تا به راحتی، یک لینوکس سبک، کارا، با Performance مناسب و به صورت یک Application ویندوزی معمولی را داشته باشیم. 

          نصب لینوکس بر روی ویندوز به صورت مستقیم و بدون VMWare!
          اشتراک‌ها
          ویندوز سرور 2012 چهارم سپتامبر منتشر می‌شود!
          ویندوز سرور 2012 آخرین پلتفرم ابری غول نرم افزاری مایکروسافت که نسخه‌ی RTM آن چندی پیش منتشر شد، در تاریخ چهارم سپتامبر 2012 به صورت عمومی عرضه خواهد شد.
          ویندوز سرور 2012 چهارم سپتامبر منتشر می‌شود!
          نظرات مطالب
          ASP.NET MVC #12
          - مشکلی از این لحاظ نیست که نشود از RenderAction در فایل layout استفاده کرد.
          - منطق تهیه گروه بندی مطالب شما احتمالا یک حلقه بی‌نهایت دارد یا یک الگوریتم بازگشتی بی پایان است.
          - ممکن است در این حالت از return PartialView استفاده نکردید و return View بوده. در این حالت View بازگشتی ارجاعی را به فایل layout خواهد داشت. یعنی به صورت تو در تو فایل layout اجرا و تکرار می‌شود.
          - یا در اینجا بهتر است در ابتدای فایل بنویسید  Layout = null تا زمان رندر شدن در فایل layout دوباره سبب ارجاع بی‌نهایتی به فایل Layout نشود.