65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.36/5 (20投票s)

2007年11月18日

4分钟阅读

viewsIcon

110456

downloadIcon

2820

一篇关于如何使用 ASP.NET 客户端回调创建支持 AJAX 的投票系统的文章。

引言

在您的网站上创建投票系统可以帮助您更深入地了解用户的兴趣。我最近在 KofeeKoder 中添加了一个每周投票系统。在本文中,我将解释如何使用 ASP.NET 客户端回调创建支持 AJAX 的投票系统。

数据库架构

数据库模式只包含两个表

  1. PollQuestions:此表包含投票的所有问题
  2. 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';
}

您可以在屏幕右上角 实时查看 投票控件。嘿!当您在那里时,请务必投下您的一票!

希望您喜欢这篇文章,祝您编程愉快!

© . All rights reserved.