نظرات مطالب
ASP.NET MVC #13
بله. نیاز هست که options مربوط به jQuery validator مانند onfocusout، onkeyup، onclick و غیره مقدار دهی شوند: (^) و (^)
البته حالت پیش فرض آن جهت کم کردن بار ارسالی به سرور در نظر گرفته شده که صحیح است.
نظرات مطالب
خلاصه اشتراک‌های روز دو شنبه 18 مهر 1390
با تشکر از پاشخ مفیدتون. اینکه ما اسم یک متد را صراحتا ر jQuery Ajax ذکر کنیم از لحاظ امنیتی مشکل زا خواهد بود؟
با تشکر
نظرات مطالب
نگاشت JSON به کلاس‌های معادل آن
آقای نصیری من فقط وقتی که می خواهم با jQuery یک AJAX Post بزنم از JSON استفاده می کنم که آن هم خیلی عملا در گیرش نیستم (از JSON.Stringfy  که معرفی کردید استفاده می کنم.)
JSON چه کاربردها و استفاده هایی دارد ؟
نظرات مطالب
NiftyDotNet!
سلام!

شبیه روش jQuery هست چون از همون روش استفاده میکنه.خود کتاب خونه منظورم نیست.روش گرد کردن منظورمه.

موفق باشید.
یادآوری خوبی بود...
نظرات مطالب
آشنایی با ویژگی DebuggerDisplay در VS.Net
با سلام و تشکر از شما که با این وبلاگ فوق العاده کمک زیادی حداقل به من در خصوص یادگیری JQUERY کردید در مورد attribute ها یک راهنمایی کنید که داریم برنامه می نویسیم کجا باید از attribute ها استفاده کرد و مجبوریم فقط از آن استفاده کنیم
پاسخ به بازخورد‌های پروژه‌ها
عدم امکان آپلود تصویر
دلیلش این هست که تمامی فرم‌ها در این سیستم به صورت ajax به سمت سرور ارسال می‌شوند.
برای اپلود فایل به کمک ajax باید از از افزونه‌ی jquery form plugin بهره بگیرید.
مطالب دوره‌ها
مثال - نمایش بلادرنگ تعداد کاربران آنلاین توسط SignalR
راه حل‌های زیادی برای محاسبه و نمایش تعداد کاربران آنلاین یک برنامه وب وجود دارند و عموما مبتنی بر کار با متغیرهای سشن یا Application و امثال آن هستند. این روش‌ها عموما دقیق نبوده و خصوصا قسمت قطع اتصال کاربر را نمی‌توانند دقیقا تشخیص دهند. به همین جهت نیاز به یک تایمر دارند که مثلا اگر در 5 دقیقه قبل، کاربری درخواست مشاهده آدرسی را به سرور ارسال نکرده بود، از لیست کاربران آنلاین حذف شود.
در ادامه بجای این روش‌ها، از SignalR برای محاسبه تعداد کاربران آنلاین و همچنین به روز رسانی بلادرنگ این عدد در سمت کاربر، استفاده خواهیم کرد.

تشخیص اتصال و قطع اتصال کاربران در SignalR

زیر ساخت‌های کلاس Hub موجود در SignalR، دارای متدهای ردیابی اتصال (OnConnected)، قطع اتصال (OnDisconnected) و یا برقراری مجدد اتصال کاربران (OnReconnected) هستند. با بازنویسی این متدها می‌توان به تخمین بسیار دقیقی از تعداد کاربران آنلاین یک سایت رسید.


پیشنیازهای بحث
پیشنیازهای این بحث با مطلب «مثال - نمایش درصد پیشرفت عملیات توسط SignalR» یکی است. برای مثال نحوه دریافت وابستگی‌ها، تنظیمات فایل global.asax و افزودن اسکریپت‌ها، تفاوتی با مثال یاد شده ندارند.


تعریف هاب کاربران آنلاین برنامه

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;

namespace SignalR05.Common
{
    public class OnlineUsersHub : Hub
    {
        public static readonly ConcurrentDictionary<string, string> OnlineUsers = new ConcurrentDictionary<string, string>();

        public void UpdateUsersOnlineCount()
        {
            // آی پی معرف یک کاربر است
            // اما کانکشن آی دی معرف یک برگه جدید در مرورگر او است
            // هر کاربر می‌تواند چندین برگه را به یک سایت گشوده یا ببندد
            var ipsCount = OnlineUsers.Select(x => x.Value).Distinct().Count();
            this.Clients.All.updateUsersOnlineCount(ipsCount);
        }

        /// <summary>
        /// اگر کاربران اعتبار سنجی شده‌اند بهتر است از
        /// this.Context.User.Identity.Name
        /// بجای آی پی استفاده شود
        /// </summary>        
        protected string GetUserIpAddress()
        {
            object environment;
            if (!Context.Request.Items.TryGetValue("owin.environment", out environment))
                return null;

            object serverRemoteIpAddress;
            if (!((IDictionary<string, object>)environment).TryGetValue("server.RemoteIpAddress", out serverRemoteIpAddress))
                return null;

            return serverRemoteIpAddress.ToString();
        }

        public override Task OnConnected()
        {
            var ip = GetUserIpAddress();
            OnlineUsers.TryAdd(this.Context.ConnectionId, ip);
            UpdateUsersOnlineCount();

            return base.OnConnected();
        }

        public override Task OnReconnected()
        {
            var ip = GetUserIpAddress();
            OnlineUsers.TryAdd(this.Context.ConnectionId, ip);
            UpdateUsersOnlineCount();

            return base.OnReconnected();
        }

        public override Task OnDisconnected()
        {
            // در این حالت ممکن است مرورگر کاملا بسته شده باشد
            // یا حتی صرفا یک برگه مرورگر از چندین برگه متصل به سایت بسته شده باشند
            string ip;
            OnlineUsers.TryRemove(this.Context.ConnectionId, out ip);
            UpdateUsersOnlineCount();

            return base.OnDisconnected();
        }
    }
}
کدهای کامل هاب شمارش کاربران آنلاین را در اینجا ملاحظه می‌کنید؛ به همراه نکته‌ی نحوه‌ی دریافت IP کاربر متصل شده به سایت، در یک هاب. کار افزودن یا حذف این کاربران به ConcurrentDictionary تعریف شده، در روال‌های بازنویسی شده اتصال، قطع اتصال و اتصال مجدد یک کاربر، انجام شده است.
در اینجا، هم به IP کاربر و هم به ConnectionId او نیاز است. از این جهت که هر ConnectionId، معرف یک برگه جدید باز شده در مرورگر کاربر است. اگر صرفا IPها را پردازش کنیم، با بسته شدن یکی از چندین برگه مرورگر او که اکنون به سایت متصل هستند، آمار او را از دست خواهیم داد. این کاربر هنوز چندین برگه باز دیگر را دارد که با سایت در ارتباط هستند، اما چون IP او را از لیست حذف کرده‌ایم (در نتیجه بسته شدن یکی از برگه‌ها)، آمار کلی شخص را نیز از دست خواهیم داد. بنابراین هر دوی IP و ConnectionIdها باید پردازش شوند.
اگر برنامه شما دارای اعتبارسنجی است (یک صفحه لاگین دارد)، بهتر است بجای IP از this.Context.User.Identity.Name استفاده کنید.


کدهای سمت کلاینت نمایش آمار کاربران

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery.signalR-1.1.3.min.js" type="text/javascript"></script>
    <script type="text/javascript" src='<%= ResolveClientUrl("~/signalr/hubs") %>'></script>
</head>
<body>
    <form id="form1" runat="server">
    online users count: <span id="usersCount"></span>
    </form>
    <script type="text/javascript">
        $(function () {
            $.connection.hub.logging = true;
            var onlineUsersHub = $.connection.onlineUsersHub;
            onlineUsersHub.client.updateUsersOnlineCount = function (count) {
                $('#usersCount').text(count);
            };
            $.connection.hub.start();
        });
    </script>
</body>
</html>
با توجه به اینکه در هاب تعریف شده، متد پویای updateUsersOnlineCount، آمار تعداد کاربران متصل را (تعداد آی پی‌های منحصربفرد متصل را) به کلاینت‌ها ارسال می‌کند، بنابراین در سمت کلاینت نیز با تعریف callback ایی به همین نام، می‌توان این آمار دریافتی را به کاربران سایت نمایش داد. آماری که به صورت خودکار با کم و زیاد شدن کاربران به روز شده و نیازی نیست کاربر به صورت دستی، صفحه را به روز کند.


کدهای کامل این مثال را از اینجا نیز می‌توانید دریافت کنید:
SignalR05.zip
 
مسیرراه‌ها
WPF
          مطالب
          طراحی گردش کاری با استفاده از State machines - قسمت اول
          State machine چیست؟

          State machine مدلی است بیانگر نحوه واکنش سیستم به وقایع مختلف. یک ماشین حالت وضعیت جاری قسمتی از سیستم را نگهداری کرده و به ورودی‌های مختلف پاسخ می‌دهد. این ورودی‌ها در نهایت وضعیت سیستم را تغییر خواهند داد.
          نحوه پاسخگویی یک ماشین حالت (State machine) را به رویدادی خاص، انتقال (Transition) می‌نامند. در یک انتقال مشخص می‌شود که ماشین حالت بر اساس وضعیت جاری خود، با دریافت یک رویداد، چه عکس العملی را باید بروز دهد. عموما (و نه همیشه) در حین پاسخگویی ماشین حالت به رویدادهای رسیده، وضعیت آن نیز تغییر خواهد کرد. در اینجا گاهی از اوقات پیش از انجام عملیاتی، نیاز است شرطی بررسی شده و سپس انتقالی رخ دهد. به این شرط، guard گفته می‌شود.
          بنابراین به صورت خلاصه، یک ماشین حالت، مدلی است از رفتاری خاص، تشکیل شده از حالات، رویدادها، انتقالات، اعمال (actions) و شرط‌ها (Guards). در اینجا:
          - یک حالت (State)، شرطی منحصربفرد در طول عمر ماشین حالت است. در هر زمان مشخصی، ماشین حالت در یکی از حالات از پیش تعریف شده خود قرار خواهد داشت.
          - یک رویداد (Event)، اتفاقی است که به ماشین حالت اعمال می‌شود؛ یا همان ورودی‌های سیستم.
          - یک انتقال (Transition)، بیانگر نحوه رفتار ماشین حالت جهت پاسخگویی به رویداد وارده بر اساس وضعیت جاری خود می‌باشد. در طی یک انتقال، سیستم از یک حالت به حالتی دیگر منتقل خواهد شد.
          - برای انجام یک انتقال، نیاز است یک شرط (Guard/Conditional Logic) بررسی شده و در صورت true بودن آن، انتقال صورت گیرد.
          - یک عمل (Action)، بیانگر نحوه پاسخگویی ماشین حالت در طول دوره انتقال است.


          چگونه می‌توان الگوی ماشین حالت را تشخیص داد؟

          اکثر برنامه‌های وب، متشکل از پیاده سازی چندین ماشین حالت می‌باشند؛ مانند ثبت نام در سایت، درخواست یک کتاب از کتابخانه، ارسال درخواست‌ها و پاسخگویی به آن‌ها و یا حتی ارسال یک مطلب در سایت، تائید و انتشار آن.
          البته عموما در حین طراحی برنامه‌ها، کمتر به این نوع مسایل به شکل یک ماشین حالت نگاه می‌شود. به همین جهت بهتر است معیارهایی را برای شناخت زود هنگام آن‌ها مدنظر داشته باشیم:
          - آیا در جدول بانک اطلاعاتی خود فیلدهایی مانند State (حالت) یا Status (وضعیت)دارید؟ اگر بله، به این معنا است که در حال کار با یک ماشین حالت هستید.
          - عموما فیلدهای Bit و Boolean، بیانگر حضور ماشین‌های حالت هستند. مانند IsPublished ، IsPaid و یا حتی داشتن یک فیلد timeStamp که می‌تواند NULL بپذیرد نیز بیانگر استفاده از ماشین حالت است؛ مانند فیلدهای published_at، paid_at و یا confirmed_at.
          - داشتن رکوردهایی که تنها در طول یک بازه زمانی خاص، معتبر هستند. برای مثال آبونه شدن در یک سایت در طول یک بازه زمانی مشخص.
          - اعمال چند مرحله‌ای؛ مانند ثبت نام در سایت و دریافت ایمیل فعال سازی. سپس فعال سازی اکانت از طریق ایمیل.


          مثالی ساده از یک ماشین حالت

          یک کلید برق را در نظر بگیرید. این کلید دارای دو حالت (states) روشن و خاموش است. زمانی که خاموش است، با دریافت رخدادی (event)، به وضعیت (state/status) روشن، منتقل خواهد شد (Transition) و برعکس.


          در اینجا حالات با مستطیل‌های گوشه گرد نمایش داده شده‌اند. انتقالات توسط فلش‌هایی انحناء دار که حالات را به یکدیگر متصل می‌کنند، مشخص گردیده‌اند. برچسب‌های هر فلش، مشخص کننده نام رویدادی است که سبب انتقال و تغییر حالت می‌گردد. با شروع یک ماشین حالت، این ماشین در یکی از وضعیت‌های از پیش تعیین شده‌اش قرار خواهد گرفت (initial state)؛ که در اینجا حالت خاموش است.
          این نوع نمودارها می‌توانند شامل جزئیات بیشتری نیز باشند؛ مانند برچسب‌هایی که نمایانگر اعمال قابل انجام در طی یک انتقال هستند.


          رسم ماشین‌های حالت در برنامه‌های وب، به کمک کتابخانه jsPlumb

          کتابخانه‌های زیادی برای رسم فلوچارت، گردش‌های کاری، ماشین‌های حالت و امثال آن جهت برنامه‌های وب وجود دارند و یکی از معروف‌ترین‌های آن‌ها کتابخانه jsPlumb است. این کتابخانه به صورت یک افزونه jQuery طراحی شده است؛ اما به عنوان افزونه‌ای برای کتابخانه‌های MooTools و یا YUI3/Yahoo User Interface 3 نیز قابل استفاده می‌باشد. کتابخانه jsPlumb در مرورگرهای جدید از امکانات ترسیم SVG و یا HTML5 Canvas استفاده می‌کند. برای سازگاری با مرورگرهای قدیمی‌تر مانند IE8 به صورت خودکار به VML سوئیچ خواهد کرد. همچنین این کتابخانه امکانات ترسیم تعاملی قطعات به هم متصل شونده را نیز دارا است (شبیه به طراح یک گردش کاری). البته برای اضافه شدن امکاناتی مانند کشیدن و رها کردن در آن نیاز به jQuery-UI نیز خواهد داشت.
          برای نمونه اگر بخواهیم مثال فوق را توسط jsPlumb ترسیم کنیم، روش کار به صورت زیر خواهد بود:
          <!doctype html>
          <html>
          <head>
              <title>State Machine Demonstration</title>
              <style type="text/css">
                  #opened
                  {
                      left: 10em;
                      top: 5em;
                  }
                  
                  #off
                  {
                      left: 12em;
                      top: 15em;
                  }
                  
                  #on
                  {
                      left: 28em;
                      top: 15em;
                  }
                  
                  .w
                  {
                      width: 5em;
                      padding: 1em;
                      position: absolute;
                      border: 1px solid black;
                      z-index: 4;
                      border-radius: 1em;
                      border: 1px solid #346789;
                      box-shadow: 2px 2px 19px #e0e0e0;
                      -o-box-shadow: 2px 2px 19px #e0e0e0;
                      -webkit-box-shadow: 2px 2px 19px #e0e0e0;
                      -moz-box-shadow: 2px 2px 19px #e0e0e0;
                      -moz-border-radius: 0.5em;
                      border-radius: 0.5em;
                      opacity: 0.8;
                      filter: alpha(opacity=80);
                      cursor: move;
                  }
                  
                  .ep
                  {
                      float: right;
                      width: 1em;
                      height: 1em;
                      background-color: #994466;
                      cursor: pointer;
                  }
                  
                  .labelClass
                  {
                      font-size: 20pt;
                  }
              </style>
              <script type="text/javascript" src="jquery.min.js"></script>
              <script type="text/javascript" src="jquery-ui.min.js"></script>
              <script type="text/javascript" src="jquery.jsPlumb-all-min.js"></script>
              <script type="text/javascript">
                  $(document).ready(function () {
          
                      jsPlumb.importDefaults({
                          Endpoint: ["Dot", { radius: 5}],
                          HoverPaintStyle: { strokeStyle: "blue", lineWidth: 2 },
                          ConnectionOverlays: [
          ["Arrow", { location: 1, id: "arrow", length: 14, foldback: 0.8}]
          ]
                      });
          
                      jsPlumb.makeTarget($(".w"), {
                          dropOptions: { hoverClass: "dragHover" },
                          anchor: "Continuous"
                      });
          
                      $(".ep").each(function (i, e) {
                          var p = $(e).parent();
                          jsPlumb.makeSource($(e), {
                              parent: p,
                              anchor: "Continuous",
                              connector: ["StateMachine", { curviness: 20}],
                              connectorStyle: { strokeStyle: '#42a62c', lineWidth: 2 },
                              maxConnections: 2,
                              onMaxConnections: function (info, e) {
                                  alert("Maximum connections (" + info.maxConnections + ") reached");
                              }
                          });
                      });
          
                      jsPlumb.bind("connection", function (info) {
                      });
          
                      jsPlumb.draggable($(".w"));
          
                      jsPlumb.connect({ source: "opened", target: "off" });
                      jsPlumb.connect({ source: "off", target: "on", label: "Turn On" });
                      jsPlumb.connect({ source: "on", target: "off", label: "Turn Off" });
                  });
              </script>
          </head>
          <body>
              <div class="w" id="opened">
                  Begin
                  <div class="ep">
                  </div>
              </div>
              <div class="w" id="off">
                  Off
                  <div class="ep">
                  </div>
              </div>
              <div class="w" id="on">
                  On
                  <div class="ep">
                  </div>
              </div>
          </body>
          </html>
          مستندات کامل jsPlumb را در سایت آن می‌توان ملاحظه نمود.
          در مثال فوق، ابتدا css و فایل‌های js مورد نیاز ذکر شده‌اند. توسط css، مکان قرارگیری اولیه المان‌های متناظر با حالات، مشخص می‌شوند.
          سپس زمانیکه اشیاء صفحه در دسترس هستند، تنظیمات jsPlumb انجام خواهد شد. برای مثال در اینجا نوع نمایشی Endpoint‌ها به نقطه تنظیم شده است. موارد دیگری مانند مستطیل نیز قابل تنظیم است. سپس نیاز است منبع و مقصدها به کتابخانه jsPlumb معرفی شوند. به کمک متد jsPlumb.makeTarget، تمام المان‌های دارای کلاس w به عنوان منبع و با شمارش divهایی با class=ep، مقصدهای قابل اتصال تعیین شده‌اند (jsPlumb.makeSource). متد jsPlumb.bind یک callback function است و هربار که اتصالی برقرار می‌شود، فراخوانی خواهد شد. متد jsPlumb.draggable تمام عناصر دارای کلاس w را قابل کشیدن و رها کردن می‌کند و در آخر توسط متدهای jsPlumb.connect، مقصد و منبع‌های مشخصی را هم متصل خواهیم کرد. نمونه نهایی تهیه شده برای بررسی بیشتر.


          برای مطالعه بیشتر
          Finite-state machine
          UML state machine
          UML 2 State Machine Diagrams
          مثال‌هایی در این مورد

          مطالب
          PersianDatePicker یک DatePicker شمسی به زبان JavaScript که از تاریخ سرور استفاده می‌کند
          PersianDatePicker  یک DatePicker شمسی برای نمایش تاریخ شمسی در صفحات وب است.

          مهمترین ویژگیها :
          • از تاریخ سرور برای نمایش روز جاری استفاده می‌کند.
          • به زبان جاوااسکریپت است و نیازی به سایر فریمورک‌ها مانند jQuery ندارد.
          • سبک و کم حجم است (3.5 کیلوبایت)
          • روزها به صورت عمودی لیست شده‌اند مانند برنامه هفتگی مدرسه که کاربران فارسی‌زبان با آن راحت‌ترند.

          طرز استفاده :

          PersianDatePicker.Show(textBox, today)
          textBox : کنترلی است که DatePicker برای آن نمایش داده می‌شود.
          today : تاریخ روز جاری است.

          برای مثال :
          <html>
          <head>
              <script type="text/javascript" src="Scripts/PersianDatePicker.min.js"></script>
              <link type="text/css" rel="stylesheet" href="Content/PersianDatePicker.min.css" />
          </head>
          <body>
              <input type="text" onclick="PersianDatePicker.Show(this, '1392/03/22');" />
          </body>
          </html>

          در ASP.NET Web Forms :
          <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>
          
          <!DOCTYPE html>
          
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head runat="server">
              <title></title>
              <script src="Scripts/PersianDatePicker.min.js"></script>
              <link href="Content/PersianDatePicker.min.css" rel="stylesheet" />
          </head>
          <body>
              <form id="form1" runat="server">
                  <div>
                      <asp:Label runat="server" Text="Label" AssociatedControlID="TextBox1">تاریخ : </asp:Label>
                      <asp:TextBox  runat="server" ID="TextBox1"></asp:TextBox>
                  </div>
              </form>
          </body>
          </html>

          public partial class WebForm1 : System.Web.UI.Page
          {
              protected void Page_Load(object sender, EventArgs e)
              {
                  var now = PersianDateTime.Now;
                  var today = now.ToString(PersianDateTimeFormat.Date);
          
                  TextBox1.Attributes["onclick"] = "PersianDatePicker.Show(this,'" + today + "');";
              }
          }

          در مثال بالا برای گرفتن تاریخ روز جاری از PersianDateTime استفاده شده است. 

          در ASP.NET MVC یا PHP یا هر زبان دیگری کافیست onclick کنترل متنی مورد نظر در سمت سرور مانند مثال بالا مقدار داده شود. یا می‌توان image کوچکی کنار textbox مورد نظر قرار داد و onclick آن تنظیم شود.

          برای استفاده از PersianDatePicker می‌توانید آنرا از NuGet دریافت کنید :
          PM> Install-Package PersianDatePicker

          همچنین یک مثال کامل ASP.NET MVC آن‌را می‌توانید از اینجا دریافت کنید:
          MvcAppPersianDatePicker.zip