آموزش ارسال دیدگاه به صورت Ajax در Asp.Net MVC

آموزش ارسال دیدگاه به صورت Ajax در Asp.Net MVC

در این آموزش قصد دارم کد مربوط به ارسال دیدگاه یا کامنت رو به صورت Ajax در Asp.net MVC4 آموزش بدم. هر سایتی به قابلیت ارسال دیدگاه نیاز دارد تا بتواند بازخوردها و نظرات مربوط به مطالب خود را دریافت نمایید و باعث تعامل بهتر با کاربران شود.

برای مشاهده لینک وارد شود

ما در asp.net mvc4 این قایت را پیاده سازی خواهیم کرد. شکل نهایی آن را در زیر می بینید:

Shot1

برای دسترسی و پیاده سازی پایگاه داده از Entity Framework نسخه ۶.۱ استفاده می کنیم.

مدل مربوط به Comment را در زیر مشاهده می نمایید:

Models/CommentModel.cs:

public class CommentModel
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int Id { get; set; }
  [MaxLength(256)]
  public string Name { get; set; }
  [MaxLength(1024)]
  public string Message { get; set; }
  public string Avatar { get; set; }
  public int ParentId { get; set; }
  public DateTime DateCreated { get; set; }
}

خاصیت Id به عنوان کلید دسترسی به کامنت ها در کلاس و پایگاه داده استفاده خواهد شد و به همین دلیل به عنوان کلید معرفی شده است ([Key]). همچنین نوع کلید عددی و به صورت خودکار تولید خواهد شد(DatabaseGenerated(DatabaseGeneratedOption.Identity)).

دیدگاه ها هر کدام دارای پاسخ خواهند بود و بایستی پاسخ مربوط به هرکدام را زیر دیدگاه مربوط به آن نمایش داد. اصطلاحا نمایش به صورت موجی یا wave comment خواهد بود. برای این منظور خاصیت ParentId را خواهیم داشت که کلید مریوط به دیدگاه والد خود را ذخیره می کنید. بعد از پیاده سازی مدل، نویت استفاده از آن و ذخیره سازی آن می رسد. با استفاده از قابلیت Entity Framework می توان کلاس را مستقیما رو پایگاه داد نگاشت (mapping). کلاس مربوط به نگاشت پایگاه داده Context نام دارد و کد مربوط به آن را در زیر می بینید:

EntitiesContext/Context.cs:

public class Context:DbContext
{
  public DbSet Comments { get; set; }

  public Context()
      : base("DefaultConnection")
  {
  }
}

DefaultConnection آدرس پایگاه داده است و در web.config ذخیره شده است:

web.config:


اکنون برای نمایش نظرات به صورت موجی، یک Layout خالی در مسیر App_Code با نام CommentHelper.cshtml ایجاد می کنیم. این Layout حاوی Helper های مربوط به پاده سازی دیدگاه ها به صورتی که در شکل می بینید خواهد بود. Helper ها توایعی هستند که خروجی آن ها به صورت Html می باشد. تابع DisplayComment برای نمایش جزئیات یک کامنت است که در زیر می بینید:

@helper DisplayComment(WebTemplate_01.Models.CommentModel comment)
{
  • @comment.Name
    @WebTemplate_01.Helper.DateTimeHelper.WaveTime(comment.DateCreated)
    @System.Web.Mvc.MvcHtmlString.Create(comment.Message.Replace(“\\n”, ”
    “))

    پاسخ

     

}

تابع WaveTime در کلاس DateTimeHelper می باشد و وظیفه آن برای نمایش تاریخ به صورتی متنی است. کد آن را در زیر می بینید:

Helper/DateTimeHelper.cs:

public static class DateTimeHelper
{
  public static string WaveTime(DateTime dt)
  {
    TimeSpan timeSince = DateTime.Now.Subtract(dt);

    if (timeSince.TotalMilliseconds < 1)
        return "همین الان";
    if (timeSince.TotalMinutes < 1)
        return "چند لحظه قبل";
    if (timeSince.TotalMinutes < 2)
        return "1 دقیقه قبل";
    if (timeSince.TotalMinutes < 60)
        return string.Format("{0} دقیقه قبل", timeSince.Minutes);
    if (timeSince.TotalMinutes < 120)
        return "1 ساعت قبل";
    if (timeSince.TotalHours < 24)
        return string.Format("{0} ساعت قبل", timeSince.Hours);
    if (timeSince.TotalDays == 1)
        return "دیروز";
    if (timeSince.TotalDays < 7)
        return string.Format("{0} روز قبل", timeSince.Days);
    if (timeSince.TotalDays < 14)
        return "هفته قبل";
    if (timeSince.TotalDays < 21)
        return "2 هفته قبل";
    if (timeSince.TotalDays < 28)
        return "3 هفته قبل";
    if (timeSince.TotalDays < 60)
        return "ماه قبل";
    if (timeSince.TotalDays < 365)
        return string.Format("{0} ماه قبل", Math.Round(timeSince.TotalDays / 30));
    if (timeSince.TotalDays < 730)
        return "سال قبل";

    //last but not least...
    return string.Format("{0} سال قبل", Math.Round(timeSince.TotalDays / 365));
  }
}

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

اکنون نوبت به تابع پیمایش دیدگاه ها و نمایش آن ها به صورتی موجی یا درختی است. نام این تابع ProgressComments است. این تایع در صورت وجود فرزند یا پاسخ برای هر دیدگاه که توسط تابع GetCommentChilds برگشت داده می شود، فرزندان آنها را نیز پشمایش خواهد کرد. این تابع به صورت تو در تو فراخوانی می شود. کد مربوط به هر دو تابع را در زیر می بینید:

@helper ProgressComments(WebTemplate_01.Models.CommentModel comment)
{
  if (comment != null) {
    @DisplayComment(comment)
    var childs = GetCommentChilds(comment.Id);
    if (childs != null)
    {
    • @foreach (var childComment in childs)
      {
      @ProgressComments(childComment)
      }

     

} } } @functions{ public static List GetCommentChilds(int id) { var context = new WebTemplate_01.EntitiesContext.Context(); return context.Comments.Where(comment => comment.ParentId == id) .OrderBy(comment => comment.DateCreated).ToList(); } }

تابع نهایی ما ShowAllComments خواهد بود که برای ایجاده نهایی و کامل دیدگاه ها است. کد مربوط به آن در زیر آمده است:

@helper ShowAllComments()
{
  var context = new WebTemplate_01.EntitiesContext.Context();
    @foreach (var comment in context.Comments.Where(c => c.ParentId == 0).OrderBy(comment => comment.DateCreated)) { @ProgressComments(comment); }

 

}

اکنون برای نمایش صحیح المنت های Html ایجاده شده در صفحه نیاز به کدهای CSS داریم. کدهای CSS مربوط در زیر آورده شده است:

Content/comment.css:

ul{list-style:none}
.comments {
  direction: rtl;
  text-align: right;
  font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;
  background-color:#fff;
  position:relative;
  padding:5px;
}
.comment-wave .sender-name{
  color:#2c8dd7;
  font-weight:bold;
  font-size:14px;
}
.comment-wave .sender-date{
  color:#a8a8a8;
  font-size:12px;
  left: 10px;
  position: absolute;
}
.comment-wave .replay{
  position: absolute;
  bottom: 5px;
  left: 5px;
  font-size: 12px;
  text-decoration: none;
  padding: 5px;
  color:#fff;
  background-color: #59b0fa;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -webkit-border-radius: 5px;
  -o-border-radius: 5px;
}
.comment-wave .comment-content{
  color:#808080;
  font-size:12px;
  display: block;
  line-height: 20px;
  margin: 10px;
}
.comment-wave .avatar {
  display: inline-block;
  box-shadow: 1px 1px 5px #E7E4E4;
  border: 1px solid #DBDBDB;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -webkit-border-radius: 5px;
  -o-border-radius: 5px;
  position:absolute;
  width:60px;
  height:60px;
  top: 0px;
  right: -70px;
}
.comment-wave .avatar img {
  display: inline-block;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 10px;
  top: 5px;
  right: 5px;
}
.comment-wave .child .wave-comment{
  width: 560px;
}
.comment-wave .wave-comment{
  display:inline-block;
  background-color:#fff;
  box-shadow: 1px 1px 5px #E7E4E4;
  border: 1px solid #DBDBDB;
  min-height: 50px;
  margin: 5px 5px;
  padding: 5px;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -webkit-border-radius: 5px;
  -o-border-radius: 5px;
  width: 600px;
  position: relative;
  margin-right: 70px;
}
.add-comment{
  width:98% !important;
  margin:0 !important;
}
.add-comment .comment-input{
  width: 81%;
  max-width: 81%;
  padding-left:95px;
}
.comment-area{
  box-shadow: 1px 1px 5px #E7E4E4;
  border: 1px solid #DBDBDB;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -webkit-border-radius: 5px;
  -o-border-radius: 5px;
  width: 680px;
  margin-right: 40px;
  position:relative;
  background-color:#fff;
}
.comment-send {
  position: absolute;
  left: 15px;
  top: 55px;
  background-color: #62AEBD;
  padding: 5px;
}
.comment-cancel {
  position: absolute;
  left: 70px;
  top: 55px;
  background-color: #62AEBD;
  padding: 5px;
}
.comment-send a,.comment-cancel a {
  text-decoration: none;
  background-color: transparent;
  color: #fff;
}
.comment-input{
  border:none;
  width: 590px;
  max-width: 590px;
  margin-right: 5px;
  padding-left:70px;
}
.comment-label{
  display: inline-block;
  min-width: 50px;
}
.sender-name-input{
  width: 96%;
  margin-right: 8px;
  border: none;
  font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;
  font-size:12px;
  clip-path:none;
}
.error-input{
  background-color: rgb(255, 224, 224);
  color:#fff;
}
.loading{
  background:transparent url("/Images/ajax-loader.gif" ) no-repeat 0 4px;
  width:16px;
  height:16px;
  display:inline-block;
}

 برای ارسال و دریافت و همچنین نمایش ارسال دیدگاه زیر هر دیدگاه به کدهای جاوااسکریت نیاز دارم که با استفاده از کتابخانه JQuery آن را پیاده سازی می کنیم:

Shot2

اکنون کد های مربوطه را توضیح می دهیم:

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

function addComment(w,p)
{
  var $e;
  if (!w)
    $e = $('comment-area');
  else {
    $e = $(w).closest('.wave-comment');
    $('.comment-area').fadeOut('slow');
  }

  $('.comments').find('.add-comment').remove();

  if (!parent) parent = '0';
  $('.wave-comment').fadeIn('slow');
  var comment = '\
\ \

\

\ \

‘; $e.append(comment); return false; }

تابع cancelComment برای لغو ارسال در حقیقت برای حذف محل نوشتن دیدگاه می باشد.

function cancelComment(el) {
  $(el).closest('.wave-comment').remove();
  $('.comment-area').fadeIn('slow');
  return false;
}

تابع addSubmit برای ارسال دیدگاه به صورت Ajax و دریافت نتیجه ارسال خواهد بود. ابتدا نام کاربر و دیدگاه او را بررسی می کند که در صورت خالی بود به او اخطار می دهد (با افزودن error-input و بردن focus روی کنترل). در صورت عدم خالی بودن آن ها، به صورت Ajax به سرور ارسال و نتیجه در یافت میشود. نتیجه شامل پیغام خطا در صورت موجود و بدنه دیدگاه ثبت شده در پایگاه داده می باشد که بعد از دریافت در صورت عدم وجود خطا در مکان مناسب خود نمایش داده می شود. کد مربوط به تابع را در زیر می بینید:

function addSubmit(el, p) {
  var senderName ;
  var commentContext ;
  var parent ;

  if (p === '0')
      parent = $(el).closest('.comment-area');
   else
      parent = $(el).closest('.wave-comment');
  

  senderName = parent.children('.sender-name-input');
  commentContext = parent.children('.comment-input');

  if (senderName.val().length == 0)
  {
      senderName.addClass('error-input');
      senderName.focus();
      return;
  }

  if (commentContext.val().length == 0) {
      commentContext.addClass('error-input');
      commentContext.focus();
      return;
  }

  var loading = $('

‘); $(el).before(loading); $.ajax({ url: ‘/Home/Comment’, data: { name: senderName.val(), cc: commentContext.val(), parent: p } }).done(function (data) { if (data.error == “fail”) { alert(“خطا سمت سرور. لطفا بعدا سعی نمایید.”); } else { if (p === ‘0’) $(“.parent”).append(data.Body); else $(“.comment-” + p).parent().after(data.Body); cancelComment(el); senderName.val(”); commentContext.val(”); } loading.remove(); return false; }).fail(function () { alert(“خطا در ارسال اطلاعات به سرور. لطفا بعدا سعی نمایید.”); }); return false; }

اکنون کد زیر که کد انتهایی jquery است رو توضیح می دهم. المنت های مربوط به دیدگاه در ابتدا وجود نداشته و به صورت پویا ایجاد می شوند پس برای نوشت رخداد هرکدام از المنت های پویا از on استفده می کنیم. در اینجا برای رفع خطای خالی بودن کنترل وقتی مقداری در آن تایپ شود استفاده میکنیم که با حذف کلاس error-input اتفاق می افتد.

$(function () {
  $('.comments').on("keypress",".sender-name-input", function () {
      $(this).removeClass('error-input');
  })

  $('.comments').on("keypress", ".comment-input", function () {
      $(this).removeClass('error-input');
  })
})

اکنون نیاز به کد سمت سرور می باشد که برای دریافت ارسال ها و ثبت در پایگاه داده و برگشت نتیجه خواهد بود. تابع Comment موجود در کنترلر Home این وظیفه را بر عهده دارد. کد مربوط به آن را در زیر می بینید:

public ActionResult Comment(string name,string cc, int parent = 0)
{
  string CommentDisplay=@"

{۲} {۳} {۴} پاسخ

“; if (parent != 0) CommentDisplay = ”

    • ” + CommentDisplay + “

 

“; else CommentDisplay = ”

  • ” + CommentDisplay + “

 

“; if (Request.IsAjaxRequest()) { string error = “”, errorMessage=””; try { var comment = new Models.CommentModel() { DateCreated = DateTime.Now, Message = cc.Replace(“\n”,”\\n”), Name = name, ParentId = parent, Avatar = “avatar_02.jpg” }; db.Comments.Add(comment); db.SaveChanges(); CommentDisplay = String.Format(CommentDisplay, comment.Id, comment.Avatar, comment.Name, WebTemplate_01.Helper.DateTimeHelper.WaveTime(comment.DateCreated), comment.Message.Replace(“\\n”,”\n”)); } catch(Exception ex) { error = “fail”; errorMessage = ex.Message+ex.Source; CommentDisplay = “”; } return Json(new { Body = CommentDisplay, Error = error,ErrorMessage=errorMessage }, JsonRequestBehavior.AllowGet); }else { return RedirectToAction(“Index”, “Home”); } }

متغیر CommentDisplay بدنه دیدگاه ثبت شده است که برای نمایش برگشت داده خواهد شد. متغییر های error و errorMessage برای نشان دادن وجود خطا و جزئیات خطا هستند. بعد از ثبت داده در پایگاه داده ها نتیجه به صورت JSON برگشت داده می شود.

امیدوارم استفاده لازم را برده باشید.

تمام.

+11
0


هرگونه انتشار مطالب اختصاصي و محصولات اين سايت بجز با درج لينک مستقيم شرعا حرام بوده و پيگرد قانوني دارد.
طبق ماده 12 فصل سوم قانون جرائم رايانه هرگونه کپي برداري ممنوع بوده و پيگرد قانوني دارد. براي اطلاعات بيشتر کليک کنيد.

درباره‌ی رضا

کارشناس نرم افزار. با هفت سال سابقه برنامه نویسی. در خدمت شما دوستان عزیز...

۱۴ دیدگاه ها

  1. سلام
    عرض ادب
    از آموزشش های خوبتون متشکرم.
    لطفا نحوه ایجاد ارسال دیدگاه در زبان asp هم آموزش دهید
    ممنون

  2. با سلام . میشه خواهش کنم سورس کد این پروژه را بگذارید
    مرسی

    • دوست عزیز سورس کد این پروژه به درخواست خود نویسنده برای فروش گذاشته شده است.شما با خرید کردن میتوانید به سورس درسترسی داشته باشید.

  3. بسیار خب . از کجا باید خرید؟

  4. سلام دوست عزیز سبد خریدتون مشکل داره پول از حسابم برداشت شده اما خطا میده.خواهشا رسیدگی کنید. ممنون

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

  5. سلام
    لطفا نحوه ی ثبت نام با mvc را اموزش دهید
    مثل فراموشی رمز عبور -ثبت نام -لاگین

  6. سایتتون فوق العادست.واقعا بی نظیرید.خیلی از مطالبتون استفاده می کنم و لازمه یه تشکر ویژه داشته باشم.

  7. سلام خسته نباشید . من ارسال دیدگاه را پیاده سازی کردم و مشکلی ندارد اما میخوام ارسال نطر برای هر مطلب باشد . امکان ثبت نظر برای هر مطلب.
    میشه راهنمایی کنید .

    • سلام،ممنون از شما بابت انتخاب برنامه نویسان نوین پندار

      شما برای ارسال نظر برای هر مطلب باید با استفاده از یک کلید خارجی(ID) بین مطلب و کامنت روت(اولین کامنت) ارتباط برقرار کنید.

دیدگاه خود را برای مجتبی بنویسید انصراف از پاسخ

آدرس پست الکترونیک شما منتشر نخواهد شد.خانه های ضروری نشانه گذاری شده اند. *

*


هفت − = 3

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>