ساخت نظرسنجی و نمایش نتایج با استفاده از Highcharts و SingnalR

ساخت نظرسنجی و نمایش نتایج با استفاده از Highcharts و SingnalR ، در مقاله قبلی، ما هسته اصلی اپلیکیشن سیستم نظرسنجی آنلاین را تنظیم کردیم؛

در این مقاله میخواهیم راجب نتایج نظرسنجی بلادرنگ با استفاده از ، webbb api 2، jQuery و highcharts صحبت کنیم.

از ایجاد یک دیتابیس و جدول های موردنیاز آن از ابتدا تا نمایش آرا به صورت بلادرنگ با استفاده از ASP.NET SignalR شروع کردیم.

در این سری آموزشی، به چگونگی پیاده سازی نتیجه ساخت نظرسنجی بلادرنگ در قالب یک نمودار نگاهی می اندازیم.

از تکنولوژی هایی همچون  SignalR 2، Web API۲، jQuery و Highchart برای پیاده سازی آن استفاده می کنیم.

اضافه کردن VoteResultViewModel

اولین کاری که باید انجام دهیم برای ساخت نظرسنجی ، اضافه کردن یک ViewModel جدید است.

برای این کار، روی فولدر “Models/ViewModels” راست کلیک کرده و سپس Add > Class را انتخاب می کنیم.

نام کلاس را “VoteResultViewModel” می گذاریم و سپس کد زیر را در آن می نویسیم:

namespace ASPNETCoreSignalRDemo.Models.ViewModels  
{  
    public class VoteResultViewModel  
    {  
        public string Choice { get; set; }  
        public int Vote { get; set; }  
    }  
}  

کد بالا چیزی نیست؛ جز اینکه کلاسی است که دو property را در خود جای داده است. توجه داشته باشید که ما همه propertyهایی که در

مدل PollOption هستند، را اضافه نکردیم: به عنوان یک قانون کلی ViewModel خود را تا جایی که ممکن است سبک نگه می داریم،

فقط هر آنچه که در View/UI نیاز است تعریف می کنیم.این property ها در View ما برای نمایش نتایج رای استفاده می شود.

تغییر دادن اینترفیس IPollManager

حالا، ما باید اینترفیس IPollManager برای اضافه کردن چند متد تغییر دهیم. کد ما باید به شکل زیر باشد:

[/csharp] using System.Collections.Generic;
using ASPNETCoreSignalRDemo.Models.ViewModels;

namespace ASPNETCoreSignalRDemo.Models
{
public interface IPollManager
{
bool AddPoll(AddPollViewModel pollModel);
IEnumerable GetActivePoll();
void UpdatePollOptionVotes(int pollOptionID);
IEnumerable GetPollVoteResults(int pollID);
}
}
[/csharp]

در کد بالا دو متد اصلی اضافه کردیم: متد UpdatePollOptionVotes() که pollOptionID را به عنوان پارامتر می گیرد و متد

GetPollVoteResults() که یک pollID را به عنوان پارامتر می گیرد که یک IEnumerable از VoteResultViewModel برمی گرداند.

تغییر کلاس PollManager

از آن جایی که ما اینترفیس را تغییر داده ایم، باید کلاس مرتبطی که اینترفیس را پیاده سازی می کند نیز تغییر دهیم.

درواقع، ما می خواهیم متدهای تازه اضافه شده از اینترفیس خود را در کلاس PollManager پیاده سازی کنیم.

حالا، ادامه داده و فایل PollManager.cs را باز کرده و کد زیر را اضافه می کنیم:

private int GetPollOptionVotes(int pollOptionID)  
{  
    return _db.PollOption  
            .Where(o => o.PollOptionId.Equals(pollOptionID))  
            .Select(o => o.Vote).FirstOrDefault();  
  
}  
  
public void UpdatePollOptionVotes(int pollOptionID)  
{  
    var option = _db.PollOption.Where(o => o.PollOptionId.Equals(pollOptionID));  
    if (option.Any())  
    {  
        int currentVotes = GetPollOptionVotes(pollOptionID);  
  
        if (currentVotes == 0)  
            currentVotes = 1;  
        else  
            currentVotes++;  
  
        PollOption PO = option.SingleOrDefault();  
        PO.Vote = currentVotes;  
        _db.SaveChanges();  
    }  
}  
  
public IEnumerable<VoteResultViewModel> GetPollVoteResults(int pollID = 0)  
{  
    if (pollID == 0)  
    {  
        var poll = _db.Poll.Where(o => o.Active.Equals(true));  
        if (poll.Any())  
            pollID = poll.FirstOrDefault().PollId;  
    }  
  
    var pollOption = _db.PollOption.Where(o => o.PollId.Equals(pollID));  
    if (pollOption.Any())  
    {  
        return pollOption.Select(o => new VoteResultViewModel  
        {  
            Choice = o.Answers,  
            Vote = o.Vote  
        });  
    }  
    return Enumerable.Empty<VoteResultViewModel>();  
}  

در این کد ما ۳ متد را اضافه کردیم: یک متد private به نام GetPollOptionVotes() و متدهای puplic ای که ما باید از اینترفیس پیاده سازی نماییم.

حالا ببینیم ما در هر متد چه کارهایی انجام دادیم:

متد GetPollOptionVotes() یک pollOptionID را به عنوان پارامتر می گیرد. این متد با توجه به pollOptionID از نگارش LINQ برای

دریافت مقدار رای مربوطه از دیتابیس استفاده می کند.

UpdatePollOptionVotes() نیز یک pollOptionID به عنوان پارامتر می گیرد. کاری که انجام می دهد این است که با توجه به

pollOptionID رکورد PollOption مشخصی از دیتابیس را دریافت می نماید.

اگر کوئری LINQ هر نتیجه ای را برگرداند، سپس تعداد رای فعلی را با فراخوانی متد GetPollOptionVotes() می گیرد.

اگر نتیجه ۰ باشد، مقدار برای رای فعلی روی ۱ قرار می گیرد، در غیر این صورت، آن را یکی اضافه می کند.

سپس مقدار رای را در مدل تغییر داده و _db.SaveChanges() را برای انعکاس تغییرات به دیتابیس فراخوانی می کند.

GetPollVoteResults() یک pollID را به عنوان پارامتر اختیاری می گیرد.

زمانی که فراخواننده هیچ پارامتر خاصی را مشخص نکرده باشد، با توجه به پرچم فعال (Active flag) pollID را با کوئری زدن روی

جدول Poll از دیتابیس دریافت می نماید.

سپس آیتم های PollOption مربوطه را واکشی می کند و یک VoteResultViewModel را برمی گرداند که شامل Choice و Vote برای یک

Poll مشخص می باشد.

تغییر PollController API

حالا، وقت آن است که متدهای API موردنیاز برای نمایش نتایج ساخت نظرسنجی بلادرنگ را ایجاد کنیم. فایل API/PollController.cs را بازکرده و متدهای زیر را اضافه می کنیم:

[HttpPost("{id}")]  
public IActionResult AddVote(int id)  
{  
    _pollManager.UpdatePollOptionVotes(id);  
    return new OkResult();  
}  
  
[HttpGet("{id}")]  
public IEnumerable<VoteResultViewModel> GetVoteResults(int id)  
{  
    return _pollManager.GetPollVoteResults(id).ToList();  
}  

هر دو متد تعریف شده از مسیریابی مبتنی بر صفت استفاده می کنند، همانطور که مشاهده می کنید با این صفت [HttpPost(“{id}”)] در متد طراحی شد.

متد AddVote() یک ID(PollOptionID) به عنوان پارامتر می گیرد. این متد در حین درخواست POST از طریق AJAX، زمانی که کاربر رای

خود را اعلام می کند، فراخوانی می شود.

GetVoteResults() یک ID(PollID) را به عنوان پارامتر می گیرد. همانطور که نام متد نشان می دهد، این متد نتایج رای را با فراخوانی

متد GetPollVoteResults() از دیتابیس دریافت می کند، که آن را قبل تر در کلاس PollManager تعریف کردیم.

تغییر PollHub

ما باید یک متد Hub اختصاصی برای نمایش نتایج تعریف کنیم. اضافه کردن کد در کلاس PollHub:

public void FetchVoteResult()  
{  
    IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PollHub>();  
    context.Clients.All.viewResults();  
}  

Hub بخش مرکزی SignalR است. مانند Controller در ASP.NET MVC، Hub وظیفه دریافت یک ورودی و تولید خروجی برای کلاینت را به عهده دارد.

این بار، ما به طور خاص زمانی که کاربر رای خود را ثبت می کند متد FetchVoteResult() را فراخوانی می کنیم.

تغییر Index View

وقت آن است که منطق مربوط به زمانی که کاربران رای های خود را ثبت می کنند، را در ساخت نظرسنجی پیاده سازی کنیم. کد زیر Index.cshtml تغییریافته را نشان می دهد.

<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>  
<script src="../Scripts/jquery.signalR-2.2.0.js"></script>  
<script src="../signalr/hubs"></script>  
  
<script>  
    var poll = $.connection.pollHub;  
    $(function () {  
        poll.client.displayPoll = function () {  
            LoadActivePoll();  
        };  
  
        $.connection.hub.start();  
        LoadActivePoll();  
  
        $("#btnSubmit").on("click", function () {  
            var selectedOption = $('input[name=poll]:checked', '#tblPoll');  
            if (selectedOption.val()) {  
                var row = $(selectedOption).closest('tr');  
                var choice = row.find("td:eq(0)").html().trim();  
                AddVote(choice);  
            }  
            else {  
                alert("Please take your vote.");  
            }  
        });  
  
        $("#lnkView").on("click", function () {  
            this.href = this.href + '?pollID=' + $("#hidPollID").val();  
        });  
    });  
  
    function LoadActivePoll() {  
        var $div = $("#divQuestion");  
        var $tbl = $("#tblPoll");  
        var $hid = $("#hidPollID");  
        var $btn = $("#btnSubmit");  
        $.ajax({  
            url: '../api/poll',  
            type: 'GET',  
            datatype: 'json',  
            success: function (data) {  
                if (data.length > 0) {  
                    $btn.show();  
                    $div.html('<h3>' + data[0].question + '</h3>');  
                    $hid.val(data[0].pollID);  
                    $tbl.empty();  
                    var rows = [];  
                    var poll = data[0].pollOption;  
  
                    $tbl.append('<tbody>');  
                    for (var i = 0; i < poll.length; i++) {  
                        rows.push('<tr>'  
                                  +'<td style="display:none;">' + poll[i].pollOptionId + '</td>'  
                                  +'<td>' + poll[i].answers + '</td>'  
                                  +'<td><input name="poll" type="radio"/></td>'  
                                  +'</tr>');  
                    }  
                    $tbl.append(rows.join(''));  
                    $tbl.append('</tbody>');  
                }  
            }  
        });  
    }  
  
    function AddVote(pollOptionID) {  
        $.ajax({  
            url: '../api/poll/AddVote',  
            type: 'POST',  
            datatype: 'json',  
            data: { id: pollOptionID },  
            success: function (data) {  
                poll.server.fetchVoteResult();  
                alert("Thank your for voting!");  
            }  
        });  
  
    }  
  
</script>  
  
<h2>ASP.NET Core Online Poll System with SignalR 2</h2>  
<div id="divQuestion"></div>  
<table id="tblPoll"></table>  
<button type="button" id="btnSubmit" style="display:none">Vote</button>  
<input type="hidden" id="hidPollID" />  
@Html.ActionLink("View Results", "Result", "Home",null,new {  @id="lnkView"})  

در این قسمت تغییرات زیادی اعمال کردیم. در ادامه نگاهی به آن ها می اندازیم.اجازه دهید از HTML شروع کنیم. ما ۳ المنت اضافه

کرده ایم:

یک المنت Button، یک المنت Hidden و یک ActionLink. Button به کاربران اجازه می دهد که رای های خود را ثبت کنند.

المنت Hidden به عنوان ذخیره سازی داده ها برای PollID استفاده می شود. مقدار PollID از طریق صفحه Result به وسیله query

string ارسال می شود.

ActionLink برای هدایت کاربران به Result View استفاده می شود. توجه داشته باشید که از قرارداد MVC پیروی می کند – ارسال

Result به عنوان نام Action و Home به عنوان نام Controller.

همچنین ما صفت HTML نیز به آن اضافه کردیم، بنابراین می توانیم یک ID برای ActionLink خود قرار دهیم.

ما به آن ID نیاز داریم بنابراین می توانیم برای ارسال مقدار یک query string قبل از مسیریابی به Result View یک رویداد “click” به آن

اضافه کنیم.

ساخت نظرسنجی

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

به عبارت دیگر، ما می توانیم داده ها را تنها با انتخاب Poll ای که پرچم فعال بودن (Active flag) آن True باشد، کوئری بزنیم.

ما این کار را انجام می دهیم، بنابراین شما ایده ای خواهید داشت که چگونه یک مقدار را در محتوای ASP.NET MVC از یک View به

دیگری ارسال نمایید.لازم است بدانید که روش های بسیاری برای ارسال مقادیر بین Viewها وجود دارد و چیزی که در این مقاله مشاهده

می نمایید تنها یکیاز آن هاست.زمانی که ما با کلیک کردن دکمه یک رای را ثبت می کنیم، رویداد کلیک جی کوئری $(“#btnSubmit”)

فراخوانی خواهد شد. با این کار آیتم انتخاب شده را از المنت ورودی Radio Button دریافت می کند.

سپس PollOptionID را برای آیتم انتخاب شده مربوطه با استفاده از jQuery دریافت کرده و مقدار را به متد AddVote() ارسال می کند.

همچنین اگر کاربر هیچ گزینه ای را از لیست انتخاب نکرده باشد، ما یک اعتبارسنجی بسیار ساده را به صورت پیغام هشدار اضافه

میکنیم.

رویداد کلیک $(“#lnkView”)، جایی است که مقدار PollID ضمیمه می شود، به عنوان یک مقدار query string در المنت ورودی

HiddenField مرتب می شود.

زمانی که کاربر روی لینک “مشاهده نتایج” کلیک می کند، این رویداد فراخوانی می شود.

تابع AddVote() یک PollOptionID را به عنوان پارامتر می گیرد.

این تابع جایی است که ما یک درخواست AJAX POST برای ثبت رای در دیتابیس می فرستیم.

توجه داشته باشید که فراخوانی به poll.server.fetchVoteResult(); – این خط کد Hub و کلاینت های متصل را فراخوانی می کند که به

اشتراک آن درآمده اند و تغییرات را دریافت خواهند کرد.

تغییراتی که ما در تابع LoadActivePoll() انجام داده ایم به شکل زیر می باشد:

  •  مرتب کردن PollID در المنت Hidden
  •  نمایش المنت Button درصورتی که هر داده Pollای وجود داشته باشد.
  • اضافه کردن مقدار PollOptionID روی HTML تولید شده

تغییر کلاس HomeController

ما باید یک action method جدید برای برگرداندن Result View در HomeController خود اضافه کنیم. حالا، کد را در کنترلری که ذکر

کردیم اضافه می کنیم:

public IActionResult Result(int pollID = 0)  
{  
    ViewBag.PollID = pollID;  
    return View();  
}  

Action method بالا، یک PollID را به عنوان پارامتر اختیاری می گیرد. مقدار QueryString، که پیشتر ارسال کردیم در پارامتر pollID

ذخیره خواهد شد – ASP.NET MVC به اندازه کافی هوشمند است تا بدون دستکاری های اضافی در سمت ما آن را حل کند.

می توانیم مشاهده کنیم، مقدار PollID را در یک ViewBag ذخیره می کنیم، بنابراین می توانیم مقدار درون Result View را رفرنس

دهیم که به زودی آن را ایجاد خواهیم کرد.

اضافه کردن Result View و HighCharts

روی فولدر Views/Home راست کلیک کرده و Add > New Item را انتخاب می کنیم. از پنجره باز شده، “MVC View Page” را مانند شکل زیر انتخاب می نماییم:

ساخت نظرسنجی

نام View را “Result.cshtml” می گذاریم. حالا، روی Add کلیک می کنیم تا فایل را تولید کرده و کدهای زیر را در آن می نویسیم:

<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>  
<script src="../Scripts/jquery.signalR-2.2.0.js"></script>  
<script src="../signalr/hubs"></script>  
<script src="http://code.highcharts.com/highcharts.js"></script>  
  
  
<script>  
    var poll = $.connection.pollHub;  
    $(function () {  
        poll.client.viewResults = function () {  
            LoadResults(0);  
        };  
  
        $.connection.hub.start();  
  
        var pollID = @ViewBag.PollID;  
        LoadResults(pollID);         
    });  
  
    function LoadResults(pollID) {  
        var $chart = $("#container");  
  
        $.ajax({  
            url: '../api/poll/GetVoteResults',  
            type: 'GET',  
            datatype: 'json',  
            data: { id: pollID },  
            success: function (data) {  
                if (data.length > 0) {  
                    var choices = [];  
                    var votes = [];  
                     
                    for (var i = 0; i < data.length; i++) {  
                        choices.push(data[i].choice);  
                        votes.push(data[i].vote);  
                         
                    }  
  
                    $('#container').highcharts({  
                        chart: {  
                            type: 'bar'  
                        },  
                        title: {  
                            text: 'Poll Vote Results'  
                        },  
                        xAxis: {  
                            categories: choices  
                        },  
                        yAxis: {  
                            title: {  
                                text: 'Best DOTA Heroes'  
                            }  
                        },  
                        series: [{  
                            name: 'Votes',  
                            data: votes  
                        }]  
                    });  
                }  
            }  
        });  
    }  
</script>  
  
<div id="container" style="min-width: 310px; max-width: 600px; height: 400px; margin: 0 auto"></div>  

حالا ببینیم که در کد بالا چه کارهایی انجام دادیم.

درست مثل Index View، ما می خواهیم از jQuery CDN برای رفرنس دادن به کتابخانه jQuery استفاده کنیم.

به ترتیب اضافه کردن رفرنس های اسکریپت ها توجه کنید.

jQuery باید اول از همه اضافه شود، سپس SignalR Core JavaScript و SignalR Hubc script. درنهایت، از طریق

code.highcharts.com به اسکریپت های HighCharts رفرنس می دهیم.

به خاطر داشته باشید، همچنین می توانیم از NPM یا مرورگر برای مدیریت منابع سمت کلاینت مانند HighCharts، jQuery و دیگر

کتابخانه ها استفاده کنیم.

برای این آموزش ساخت نظرسنجی ، می خواهیم از HighCharts برای نمایش نمودارها در صفحه خود استفاده کنیم.

ما تمایل داریم از HighCharts در ساخت ساخت نظرسنجی استفاده کنیم، زیرا نمودارهای جالبی را فراهم می کند که می توانیم نمودارهای ساده تا پیچیده را از بین

آن ها انتخاب نماییم.

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

http://www..highcharts.com/

در اولین خط، درون تگ <script>، یک اتصال به PollHub خود تعریف کردیم.

کد درون تابع آماده داکیومنت jQuery ($(function(){});) جایی است که ما یک function delegate برای اشتراک (subscribe) به PollHub خود ایجاد کردیم.

با اشتراک به Hub، ASP.NET SignalR همه کارهای پیچیده برای پیاده سازی به روزرسانی های بلادرنگ بدون نیاز به هیچ کار اضافه ای

در سمت ما را انجام می دهد.

زمانی که یک کاربر یک رای ثبت می کند، function delegate با نام poll.client.viewResults() فراخوانی خواهد شد و به طور اتوماتیک

با فراخوانی تابع LoadResult() داده ها را از دیتابیس واکشی می کند.

مقدار ۰ را در تابع LoadResult() ارسال کردیم چرا که کد سمت سرور ما به دریافت PollID با توجه به پرچم فعال بودن اهمیت می دهد .

متد GetPollVoteResults() در کلاس PollManager را مشاهده نمایید.

فراخوانی دیگر به تابع LoadResult() زمانی اجرا می شود که کاربر روی لینک “مشاهده نتایج” از Index View کلیک کند.

به خاطر داشته باشید، ما یک رویداد کلیک سفارشی برای ارسال PollID به عنوان مقدار QueryString تنظیم می کنیم و سپس مقدار

PollID را برای این منظور در یک ViewBag ذخیره می کنیم.

تابع LoadResults() جایی است که با توجه به PollID ما یک درخواست AJAX GET برای دریافت داده ها می فرستیم.

اگر درخواست داده ای برگرداند، براساس نتیجه JSON آرایه ای از گزینه ها و رای ها ایجاد می کند.

سپس یک نمودار میله ای ساده می سازیم و آرایه های داده ها را به محورهای X و Y نمودار اختصاص دهیم: آرایه ای از گزینه ها محور X

و آرایه رای ها محور Y ها هستند.

همانطور که از کد بالا مشاهده می کنید، نمودار در المنت div با آی دی “container” رسم خواهد شد.

توجه داشته باشید که نمودار بعد از اینکه کاربری رای ثبت می کند، تغییر می کند.

محدودیت ها

تا کنون، ما ساخت نظرسنجی بلادرنگ ساده را به اتمام رسانده ایم.

توجه داشته باشید که این فقط یک پیاده سازی بسیار ساده از چگونگی ساخت نظرسنجی بلادرنگ و نمایش نظرسنجی بلادرنگ است.

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

شاید لازم باشد که شما از cookie یا چیزی شبیه به آن برای جلوگیری ثبت چندین رای از کاربران استفاده نمایید.

مدیریت چندین نوع نظرسنجی نیز پوشش داده نشده و درنهایت مدیریت رای کامل نیست.

عدم توانایی تغییر یک نظرسنجی ، غیرفعال کردن و حذف نظرسنجی موجود نیز سایر محدودیت های این سری آموزش است.

خلاصه

در این مقاله ساخت نظرسنجی ، ما پیاده سازی اولیه نمایش نتایج نظرسنجی بلادرنگ با استفاده از قدرت ASP.NET SignalR را به صورت بلادرنگ یاد گرفتیم.

یاد گرفتیم که چگونه از jQuery و jQuery AJAX برای ارتباط با متدهای Web API استفاده کنیم.

همچنین آموختیم که چگونه یک نمودار داینامیک ساده در HighCharts ایجاد کنیم.

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

جهت دانلود سورس کد نظرسنجی آنلاین میتوانید به لینک مراجعه کنید.همچنین جهت دانلود سورس .NET Core میتوانید به لینک مراجعه کنید.

  • پسورد: www.mspsoft.com
زهره سلطانیان

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.