使用 ASP.NET 2.0 回调创建投票系统






4.36/5 (20投票s)
2007年11月18日
4分钟阅读

110456

2820
一篇关于如何使用 ASP.NET 客户端回调创建支持 AJAX 的投票系统的文章。
引言
在您的网站上创建投票系统可以帮助您更深入地了解用户的兴趣。我最近在 KofeeKoder 中添加了一个每周投票系统。在本文中,我将解释如何使用 ASP.NET 客户端回调创建支持 AJAX 的投票系统。
数据库架构
数据库模式只包含两个表
- PollQuestions:此表包含投票的所有问题
- PollChoices:此表包含投票问题选项
看看下面显示的模式
 
 
存储过程
CREATE PROCEDURE usp_GetLastestPoll
AS
DECLARE @pqID int
SELECT @pqID = MAX(PollQuestionID) FROM PollQuestions
PRINT @pqID
SELECT q.PollQuestionID,q.[Text] AS PollText,c.PollChoiceID,
  c.[Text] ChoiceText,c.Total FROM PollQuestions q JOIN PollChoices c
  ON q.PollQuestionID = c.PollQuestionID WHERE q.PollQuestionID = @pqID
GO
投票控件架构
我想创建投票用户控件,使其不依赖于页面。让我们来看看下面的类图
 
 
现在,我将详细解释每个类
- IPoll<code>:- IPoll是一个接口,所有投票类都将使用它
- WeeklyPoll:这是负责创建每周投票的类。它实现了- IPoll接口
- PollQuestion:这是一个实体类,映射到数据库中的- PollQuestions表
- PollChoice:这是一个实体类,映射到数据库中的- PollChoices表
- PollTableHelper:这是一个辅助类,用于生成动态 HTML 表
- ControlToHtmlConvertor:此类包含将控件转换为纯 HTML 的辅助方法
- DataAccess:此类充当- DataAccess类,用于从数据库- INSERT和- SELECT投票
实现
让我们深入探讨实现细节。本文将介绍几个重要的类。有关完整的实现,您可以使用本文顶部的代码。
IPollInterface
所有希望公开投票功能的类都实现了 IPollInterface 。
public interface IPoll
    {
        string Create();
        string GetStats();
    }
WeeklyPoll
WeeklyPoll 是实现 IPoll 接口的类之一。实现如下所示
public class WeeklyPoll : IPoll
    {
        public string Create()
        {
            PollQuestion poll = PollQuestion.GetPoll();
            return PollTableHelper.GenerateTableForPoll(poll);
        }
        public string GetStats()
        {
            PollQuestion poll = PollQuestion.GetPoll();
            return PollTableHelper.GetPollStats(poll);
        }
    }
我将不讨论 PollTableHelper 类,因为代码仅用于构建表。您可以下载本文顶部提供的完整源代码并查看实现。
PollControl.ascx
PollControl.ascx 是一个用户控件,用于向用户显示投票。让我们先看看 PollControl.ascx 控件的 HTML 代码。
是的,就是这样!
现在,让我们看看代码隐藏文件
protected void Page_Load(object sender, EventArgs e)
        {
               RegisterCallbacks();
        }
        private void RegisterCallbacks()
        {
        string sbReference = Page.ClientScript.GetCallbackEventReference
            (this, "arg", "ReceiveServerData", "context");
        string cbScript = String.Empty;
        // check if the script is already registered or not
        if (!Page.ClientScript.IsClientScriptBlockRegistered("CallServer"))
        {
            cbScript = @" function CallServer(arg,context) 
                { " + sbReference + "} window.setTimeout(CallServer,100); ";
            Page.ClientScript.RegisterClientScriptBlock
                (this.GetType(), "CallServer", cbScript, true);
        }
        }
在上面的代码中,我只是注册了回调。如果您有兴趣了解更多关于如何注册页面/用户控件以使用回调,请查看 本文。
注册回调方法的所有内容都相同,除了调用 window.setTimeout 函数。我之所以进行此调用,是为了在将 CallServer 方法注册到页面后立即触发它。我知道您可能在想为什么不在回调注册过程结束时直接调用 CallServer('', '')。不幸的是,这种方法不起作用,因为 CallServer 需要来自页面的参数。
为了使回调正常工作,您必须实现 ICallbackEventHandler 接口,如下所示
public partial class PollControl : 
    System.Web.UI.UserControl, ICallbackEventHandler
ICallbackEventHandler 接口包含两个方法:GetCallbackResult 和 RaiseCallbackEvent 。让我们看看下面的实现
public void RaiseCallbackEvent(string eventArgument)
        {
            // update the polls
            string[] selection = eventArgument.Split(':');
            if (selection.Length > 1)
            {
                PollQuestion.Update(Int32.Parse(selection[0]), 
                    Int32.Parse(selection[1]));
                // create a cookie for the user
                CreatePollCookie();
            }
        }
当用户单击“投票”按钮进行投票时,会触发 RaiseCallbackEvent 。我检查用户是否选择了某个选项,如果选择了,则在数据库中更新该选项。更新选项后,我还会创建一个 cookie,以便用户在一段时间内无法再次投票。
我还可以使用 IP 地址来跟踪哪个用户已投票,但使用 IP 地址存在一些缺点。如果一个人在防火墙后面的局域网中,那么他或她进行的投票将是整个局域网的投票,因为连接到局域网的计算机位于防火墙后面,它们具有相同的 IP 地址。
CreatePollCookie 用于创建 HttpCookie
private void CreatePollCookie()
    {
        HttpCookie pollCookie = new HttpCookie("PollCookie");
        pollCookie.Value = "PollCookie";
      pollCookie.Expires = DateTime.Now.AddDays(7);
        Response.Cookies.Add(pollCookie);
    }
在将内容发送到客户端之前,会触发 GetCallbackResult 方法。
public string GetCallbackResult()
        {
            string result = String.Empty;
            IPoll poll = new WeeklyPoll();
            if (DoesCookieExists())
            {
                result = poll.GetStats();
            }
            else
            {
                result = poll.Create();
            }
            return result;
        }
DoesCookieExists 方法确保,如果客户端已经投票,则您需要向她或他显示投票统计信息,否则显示投票。这是通过检查 cookie 的存在来完成的。
  private bool DoesCookieExists()
        {
            if (Request.Cookies["PollCookie"] != null) return true;
            else return false;
        }
JavaScript 代码
所有 JavaScript 代码都存储在 Site.js 文件中。网站的所有页面都必须引用 JS 文件才能使投票控件正常工作。
function vote()
{
    var pollWidget = document.getElementById("divPoll");
    var inputElements = pollWidget.getElementsByTagName("INPUT");
    var userSelection;
    for(i=0; i<inputElements.length;i++)
    {
        if(isRadioButton(inputElements[i]))
        {
            if(inputElements[i].checked)
            {
                userSelection = inputElements[i].id;
                break;
            }
        }
    }
    // call the server method to note the changes
    CallServer(userSelection,'');
}
function ReceiveServerData(rValue)
{
    document.getElementById("divPoll").innerHTML = rValue;
}
function isRadioButton(target)
{
    return target.type == 'radio';
}
您可以在屏幕右上角 实时查看 投票控件。嘿!当您在那里时,请务必投下您的一票!
希望您喜欢这篇文章,祝您编程愉快!
