用c#开发微信 (13) 微统计 - 阅读分享统计系统 3 UI设计及后台处理

 

微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读、分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问、好友分享消息访问等。本系统实现了手机网页阅读、分享与来源统计及手机网页在朋友圈的传播路径分析。

本系统使用最传统的三层架构。本文是微统计的第三篇,主要介绍如下内容:

 

1. 为页面HighCharts画图控件提供数据

2. 接收分享记录信息并保存到数据库

3. 访问记录统计图

4. 阅读统计界面

5. 处理文字请求

前端开发框架使用Bootstrap,没有注明前台的页面表示前台不用显示任何内容

1. 为页面HighCharts画图控件提供数据 Data.aspx

public partial class Data : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                string result = "";
                string typeStr = System.Web.HttpContext.Current.Request.QueryString["type"];
                if (!string.IsNullOrEmpty(typeStr))
                {
                    switch (typeStr)
                    {
                        case "navChart": //页面访问图
                            result = JsonConvert.SerializeObject(GetPageNavStatistics());
                            break;
                        case "shareChart": //页面分享图
                            result = JsonConvert.SerializeObject(GetPageShareStatistics());
                            break;
                    }
                }
                //将HighCharts绘图所需的数据返回给页面
                HttpResponse response = System.Web.HttpContext.Current.Response;
                response.ContentType = "application/json";
                response.Write(result);
                response.End();
            }
 
            /// <summary>
            /// 获取页面访问统计信息
            /// </summary>
            /// <returns></returns>
            private ChartData GetPageNavStatistics()
            {
                //取过去两天的数据进行统计
                DateTime startTime = DateTime.Now.AddDays(-3);
                DateTime endTime = DateTime.Now.AddDays(1);
                List<PageNavEntity> temp = new PageNavBll().GetPageNavList();
                List<decimal> statistics = new List<decimal>();
                //HighCharts时间轴的起始时间
                ChartData chartData = new ChartData
                {
                    StartYear = startTime.Year,
                    StartDay = startTime.Day,
                    StartMonth = startTime.Month
                };
                //生成按小时统计的数据
                while (startTime < endTime)
                {
                    statistics.Add(temp.FindAll(e => e.VisitTime >= startTime && e.VisitTime < startTime.AddHours(1)).Count());
                    startTime = startTime.AddHours(1);
                }
                chartData.Statistics = statistics.ToArray();
                return chartData;
            }
 
            /// <summary>
            /// 获取页面分享统计信息
            /// </summary>
            /// <returns></returns>
            private ChartData GetPageShareStatistics()
            {
                //取过去两天的数据进行统计
                DateTime startTime = DateTime.Now.AddDays(-3);
                DateTime endTime = DateTime.Now.AddDays(1);
                List<PageShareEntity> temp = new PageShareBll().GetPageShareList();
                List<decimal> statistics = new List<decimal>();
                //HighCharts时间轴的起始时间
                ChartData chartData = new ChartData
                {
                    StartYear = startTime.Year,
                    StartDay = startTime.Day,
                    StartMonth = startTime.Month
                };
                //生成按小时统计的数据
                while (startTime < endTime)
                {
                    statistics.Add(temp.FindAll(e => e.ShareTime >= startTime && e.ShareTime < startTime.AddHours(1)).Count());
                    startTime = startTime.AddHours(1);
                }
                chartData.Statistics = statistics.ToArray();
                return chartData;
            }
        }

2. 接收分享记录信息并保存到数据库 Share.aspx

public partial class Share : System.Web.UI.Page

    {
        ILog m_Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
        protected void Page_Load(object sender, EventArgs e)
        {
            string typeStr = Request.QueryString["type"];
 
            m_Log.Info("share type: " + typeStr);
            m_Log.Info("share url: " + Request["url"]);
 
            if (!string.IsNullOrEmpty(typeStr))
            {
                //识别分享类型
                ShareType type = ShareType.Unknown;
                switch (typeStr)
                {
                    case "timeline":
                        type = ShareType.Timeline;
                        break;
                    case "friend":
                        type = ShareType.Friend;
                        break;
                }
                //构造分享记录
                var pageShare = new PageShareEntity()
                {
                    Id = Guid.NewGuid(),
                    Url = GetOrigenalUrl(Request["url"]),
                    ParentShareOpenId = Request["s"],
                    ShareOpenId = Request["u"],
                    From = type,
                    ShareTime = DateTime.Now
                };
                //保存分享记录
               bool insertShare = new PageShareBll().InsertPageShare(pageShare);
 
               m_Log.Info("insert share: " + insertShare.ToString());
            }
        }
 
        /// <summary>
        /// 获取不含统计相关参数的页面地址
        /// </summary>
        /// <param name="url">网址</param>
        /// <returns>不含统计相关参数的页面地址</returns>
        private string GetOrigenalUrl(string url)
        {
            url = System.Web.HttpUtility.UrlDecode(url);
            Uri uri = new Uri(url);
            StringBuilder urlBuilder = new StringBuilder();
            //获取不含QueryString的URL
            urlBuilder.Append("http://")
                .Append(uri.Host)
                .Append(uri.AbsolutePath)
                .Append("?");
            //构造移除统计相关参数的Query
            Dictionary<string, string> queryString = uri.Query.Replace("?", "").Split(‘&‘).Where(p => !string.IsNullOrEmpty(p)).ToDictionary(p => p.Split(‘=‘)[0], p => p.Split(‘=‘)[1].Split(‘#‘)[0]);
            foreach (var key in queryString.Keys)
            {
                if (key != "s" && key != "u" && key != "from" && key != "code" && key != "state")
                {
                    urlBuilder.Append(key).Append("=").Append(queryString[key]).Append("&");
                }
            }
            return urlBuilder.ToString();
        }
    }

当发送朋友或朋友圈时保存分享数据。

 

3. 访问记录统计图 StatisticsPage.aspx

前台:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="StatisticsPage.aspx.cs" Inherits="Statistics.StatisticsPage" %>
 
<!DOCTYPE html>
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>统计</title>
    <%-- Bootstrap --%>
    <link href="Css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="Scripts/bootstrap.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-1.9.1.min.js" type="text/javascript"></script>
    <%-- HighCharts用于图表显示 --%>
    <link href="Css/highcharts/charts.css" rel="stylesheet" type="text/css" />
    <script src="Scripts/HighCharts/highcharts.js" type="text/javascript"></script>
    <script src="Scripts/HighCharts/highcharts-more.js" type="text/javascript"></script>
    <script src="Scripts/HighCharts/publiclinecharts.js" type="text/javascript"></script>
</head>
<body>
    <div class="container">
        <div class="row-fluid">
            <div class="span12">
                <h3>访问记录</h3>
                <%-- 访问记录统计图 --%>
                <div class="box">
                    <div class="box-content">
                        <div class="row" style="margin-top: 30px; ">
                            <div class="area">
                                <div id="page-nav-chart">
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <%-- 访问记录列表 --%>
                <div class="maincontentinner1" >
                    <div id="Div12" class="dataTables_wrapper">
                        <table id="page-nav-table" class="table table-bordered responsive dataTable">
                            <%-- 访问记录列表列名 --%>
                            <thead>
                                <tr>
                                    <th>页面地址
                                    </th>
                                    <th>访问来源
                                    </th>
                                    <th>访问者openid
                                    </th>
                                    <th>分享自openid
                                    </th>
                                    <th>访问时间
                                    </th>
                                </tr>
                            </thead>
                            <tbody id="page-nav-table-body">
                                <%-- 一行一行生成访问记录列表 --%>
                                <% foreach (Statistics.ViewEntity.PageNavEntity entity in (ViewState["NavList"] as List<Statistics.ViewEntity.PageNavEntity>))
                                   { %>
                                <tr class="gradeX odd">
                                    <td>
                                        <%= entity.Url%>
                                        </td>
                                    <td class=" ">
                                        <%= entity.From.ToString()%>
                                        </td>
                                    <td class=" ">
                                        <%= entity.NavOpenId%>
                                        </td>
                                    <td class=" ">
                                        <%= entity.ShareOpenId%>
                                        </td>
                                    <td class=" ">
                                        <%= entity.VisitTime.ToString()%>
                                        </td>
                                </tr>
                                <% } %>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script>
        //图表参数
        var pageNavChartOpts = {
            getStatisticsUrl: ‘Data.aspx?type=navChart‘, //读取数据的访问地址
            titletext: "",
            ytext: "",
            startyear: 0,
            startmonth: 0,
            startday: 0,
            lineinterval: 3600 * 1000, //竖线以1小时为间隔显示
            pointInterval: 3600 * 1000,//点以1小时为间隔显示
            countArray: [],
            formid: "page-nav-chart", //图表容器ID
            seriesname: "访问次数",
            unit: "次"
        };
        jQuery(function () {
            //使用HighCharts绘制图表
            highcharts.extFunction.PreDrawMethod = function (repJson) {
                pageNavChartOpts.startyear = repJson.StartYear;
                pageNavChartOpts.startmonth = repJson.StartMonth;
                pageNavChartOpts.startday = repJson.StartDay;
                highcharts.displayMode = repJson.DisplayMode;
                pageNavChartOpts.lineinterval = repJson.LineInterval;
                pageNavChartOpts.pointInterval = repJson.PointInterval;
            };
            highcharts.init(pageNavChartOpts);
        });
    </script>
</body>
</html>

用HighCharts来图表显示数据。

 

后台:

protected void Page_Load(object sender, EventArgs e)
{
    //传递给页面显示的记录列表
    ViewState["NavList"] = new PageNavBll().GetPageNavList();
    ViewState["ShareList"] = new PageShareBll().GetPageShareList();
}

通过业务逻辑层获取数据。

 

4. 阅读统计界面 WeixinPageIndex.aspx

前台:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WeixinPageIndex.aspx.cs" Inherits="Statistics.WeixinPageIndex" %>
 
<!DOCTYPE html>
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.9.1.min.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
</head>
<body>
    <form id="form1" type="post" runat="server">
        <div>
            <%-- 所有的跳转页面,加上访问者与分享者的OpenId --%>
            <a href="WeixinPageSubPage.aspx?u=<%= ViewState["navOpenId"] as string %>&s=<%= ViewState["shareOpenId"] as string %>">WeixinPageSubPage</a>
 
        </div>
    </form>
</body>
</html>
<script>
    var url = location.href;
    alert(url);
    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: ‘<%= appID %>‘, // 必填,公众号的唯一标识
        timestamp: ‘<%= timestamp %>‘, // 必填,生成签名的时间戳
        nonceStr: ‘<%= nonceStr %>‘, // 必填,生成签名的随机串
        signature: ‘<%= signature %>‘,// 必填,签名,见附录1
        // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        jsApiList: [
        ‘onMenuShareAppMessage‘
        ]
    });
 
    friendcallback = function (res) {
        var shareUrl = "Share.aspx?type=friend&url=" + encodeURIComponent(url) + "&u=" + "<%= ViewState["navOpenId"] as string %>" + "&s=" + "<%= ViewState["shareOpenId"] as string %>";
 
        //AJAX请求
        $.ajax({
            type: "get",
            url: shareUrl,
            beforeSend: function () {
            },
            success: function () {
            },
            complete: function () {
            },
            error: function () {
            }
        });
    };
 
    wx.ready(function () {
        wx.onMenuShareAppMessage({
            title: ‘用c#开发微信 系列汇总‘,
            desc: ‘网上开发微信开发的教程很多,但c#相对较少。这里列出了我所有c#开发微信的文章,方便自己随时查阅。如果可能,我尽量附上源码,这样就可以直接发布运行看效果,更好地理解原理。‘,
            link: url,
            imgUrl: ‘http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg‘,
            trigger: function (res) {
            },
            success: function (res) {
                friendcallback(res);
            },
            cancel: function (res) {
            },
            fail: function (res) {
                alert(JSON.stringify(res));
            }
        });
        wx.onMenuShareTimeline({
            title: ‘用c#开发微信 系列汇总‘,
            desc: ‘网上开发微信开发的教程很多,但c#相对较少。这里列出了我所有c#开发微信的文章,方便自己随时查阅。如果可能,我尽量附上源码,这样就可以直接发布运行看效果,更好地理解原理。‘,
            link: url,
            imgUrl: ‘http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg‘,
            trigger: function (res) {
            },
            success: function (res) {
                friendcallback(res);
            },
            cancel: function (res) {
            },
            fail: function (res) {
                alert(JSON.stringify(res));
            }
        });
    });
 
</script>

利用JS-SDK来获取分享者,并通过Share页面来保存分享数据。

 

 

后台:

public partial class WeixinPageIndex : System.Web.UI.Page
    {
        static ILog m_Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
        public string timestamp = string.Empty;
        public string nonceStr = string.Empty;
        public string signature = string.Empty;
 
        /// <summary>
        /// 从微信公众平台获取的开发者凭据
        /// </summary>
        public readonly string appID = ConfigurationManager.AppSettings["appID"];
        /// <summary>
        /// 从微信公众平台获取的开发者凭据
        /// </summary>
        readonly string appSecret = ConfigurationManager.AppSettings["appSecret"];
 
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                #region 1. Get wx.config
 
                string ticket = string.Empty;
                timestamp = JSSDKHelper.GetTimestamp();
                nonceStr = JSSDKHelper.GetNoncestr();
                JSSDKHelper jssdkhelper = new JSSDKHelper();
 
                try
                {
                    ticket = JsApiTicketContainer.TryGetTicket(appID, appSecret);
                    signature = jssdkhelper.GetSignature(ticket, nonceStr, timestamp, Request.Url.AbsoluteUri.ToString());
                }
                catch (ErrorJsonResultException ex)
                {
                    m_Log.Error("errorcode:" + ex.JsonResult.errcode.ToString() + "  errmsg: " + ex.JsonResult.errmsg, ex);
                }
 
                #endregion
 
                NameValueCollection parameters = System.Web.HttpContext.Current.Request.Params;
 
                m_Log.Info("URL: " + Request.Url.ToString());
 
                //取得链接中的分享者OpenId
                string shareOpenId = parameters["s"];
                //获取访问者的OpenId
                string navOpenId = GetNavOpenId();
 
                if (navOpenId != null)
                {
                    NavStatistics(navOpenId, shareOpenId);
                    //传递给页面的访问者OpenId
                    ViewState["navOpenId"] = navOpenId;
                    //传递给页面的分享者OpenId
                    ViewState["shareOpenId"] = shareOpenId;
                }
 
                m_Log.Info("timestamp: " + timestamp + " nocestr: " + nonceStr + " singnature: " + signature);
                m_Log.Info("nav open id: " + navOpenId + " share open id: " + shareOpenId);
            }
        }
 
        /// <summary>
        /// 记录页面访问
        /// </summary>
        /// <param name="navOpenId">访问者微信openid</param>
        /// <param name="shareOpenId">当访问来源为朋友圈时的分享者微信openid</param>
        private void NavStatistics(string navOpenId, string shareOpenId)
        {
            //获取访问来源
            NavFrom fromType = GetNavFromType();
            //构造访问记录
            var pageNav = new PageNavEntity()
            {
                Id = Guid.NewGuid(),
                Url = GetOrigenalUrl(),
                NavOpenId = navOpenId,
                ShareOpenId = navOpenId == shareOpenId ? "" : shareOpenId,
                From = fromType,
                VisitTime = DateTime.Now
            };
            //访问记录写入数据库
            new PageNavBll().InsertPageNav(pageNav);
        }
 
        /// <summary>
        /// 判断页面访问来源类型
        /// </summary>
        /// <returns></returns>
        private static NavFrom GetNavFromType()
        {
            //网址中的参数集合
            NameValueCollection parameters = System.Web.HttpContext.Current.Request.Params;
            string fromStr = parameters["from"]; //发送给朋友、分享到朋友圈的链接会含有from参数
 
            m_Log.Info("from: " + fromStr);
 
            NavFrom fromType;
            if (!Enum.TryParse<NavFrom>(fromStr, true, out fromType)) //通过判断from参数,识别页面访问是来自于发送给朋友的链接还是分享到朋友圈的链接
            {
                //获取HTTP访问头中的User-Agent参数的值
                string agent = System.Web.HttpContext.Current.Request.Headers["User-Agent"];
                if (agent.Contains(NavFrom.MicroMessenger.ToString())) //判断页面是否是在微信内置浏览器中打开
                    fromType = NavFrom.MicroMessenger;
                else
                    fromType = NavFrom.Other;
            }
            return fromType;
        }
 
        /// <summary>
        /// 获取不含统计相关参数的页面地址
        /// </summary>
        /// <returns>不含统计相关参数的页面地址</returns>
        private string GetOrigenalUrl()
        {
            StringBuilder urlBuilder = new StringBuilder();
            //获取不含QueryString的URL
            urlBuilder.Append("http://")
                .Append(System.Web.HttpContext.Current.Request.Url.Host)
                .Append(System.Web.HttpContext.Current.Request.Url.AbsolutePath)
                .Append("?");
            //构造移除统计相关参数的Query
            foreach (var key in System.Web.HttpContext.Current.Request.QueryString.AllKeys)
            {
                if (key != "s" && key != "u" && key != "from" && key != "code" && key != "state")
                {
                    urlBuilder.Append(key).Append("=").Append(System.Web.HttpContext.Current.Request.QueryString[key]).Append("&");
                }
            }
            return urlBuilder.ToString();
        }
 
        /// <summary>
        /// 获取访问者openId
        /// </summary>
        private string GetNavOpenId()
        {
            NameValueCollection parameters = System.Web.HttpContext.Current.Request.Params;
            //获取链接中的openId
            string navOpenId = parameters["u"];
            #region 如果是从微信浏览器浏览,获取真实的微信OpenId
            if (!string.IsNullOrEmpty(appID) && !string.IsNullOrEmpty(appSecret))
            {
                string accessSource = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
 
                if (accessSource.Contains("MicroMessenger")) //如果是从微信打开页面
                {
                    string[] cookieKeys = new[] { CookieHelper.COOKIE_NAME };
                    Dictionary<string, string> realIdCookie = CookieHelper.GetLoginCookies(cookieKeys); //获取保存在Cookie中的OpenId
                    //如果Cookie中不存在OpenId,或者链接中的openId与Cookie中的OpenId不一致,链接中的openId为分享者的OpenId,需要获取当前用户的真实OpenId
                    if (NeedGetReadOpenId(parameters, realIdCookie))
                    {
                        if (parameters["code"] == null)
                        {
                            // 先去获取code,并记录分享者
                            string snsapi_baseUrl = GoCodeUrl(navOpenId);
                            if (!string.IsNullOrEmpty(snsapi_baseUrl))
                            {
                                CookieHelper.CleanLoginCookie(cookieKeys);
                                //跳转到微信网页授权页面
                                System.Web.HttpContext.Current.Response.Redirect(snsapi_baseUrl, true);
                                System.Web.HttpContext.Current.Response.End();
                                return null;
                            }
                        }
                        else
                        {
                            m_Log.Info("code: " + parameters["code"].ToString());
 
                            OAuthAccessTokenResult tokenResult = GetRealOpenId(parameters["code"].ToString());
                            if (null != tokenResult && !string.IsNullOrEmpty(tokenResult.openid))
                            {
                                m_Log.Info("tokenResult.openid: " + tokenResult.openid);
 
                                navOpenId = tokenResult.openid;
                                // 获取到的当前访问者的OpenId保存到cookie里
                                CookieHelper.CleanLoginCookie(cookieKeys);
                                realIdCookie[CookieHelper.COOKIE_NAME] = tokenResult.openid;
                                CookieHelper.WriteLoginCookies(realIdCookie, DateTime.MinValue);
                            }
                        }
                    }
                }
            }
            #endregion
            return navOpenId;
        }
 
        /// <summary>
        /// 如果Cookie中存在OpenId且链接中的openId与Cookie中的OpenId一致
        /// 则不需要调用网页授权接口,链接中的openId即为当前访问者的真实OpenId
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="realIdCookie"></param>
        /// <returns></returns>
        private bool NeedGetReadOpenId(NameValueCollection parameters, Dictionary<string, string> realIdCookie)
        {
            string referer = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_REFERER"];
            string openId = null;
            if (realIdCookie != null)
            {
                if (realIdCookie.ContainsKey(CookieHelper.COOKIE_NAME))
                {
                    openId = realIdCookie[CookieHelper.COOKIE_NAME];
                }
            }
 
            m_Log.Info("NeedGetReadOpenId openid: " + openId + " referer: " + referer + " u: " + parameters["u"].ToString());
 
            if (!string.IsNullOrEmpty(referer) && openId == parameters["u"].ToString())
                return false;
            else
                return true;
        }
 
        /// <summary>
        /// 网页授权接口第一步
        /// 跳转到获取code的url
        /// </summary>
        /// <param name="shareOpenId">当访问来源为朋友圈时的分享者微信openid</param>
        private string GoCodeUrl(string shareOpenId)
        {
            string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri + "&s=" + shareOpenId; //添加分享者OpenId
            return OAuthApi.GetAuthorizeUrl(appID, url, "STATE", OAuthScope.snsapi_base);
        }
 
        /// <summary>
        /// 网页授权接口第二步
        /// 解析code并获取当前访问者真正的openId
        /// </summary>
        /// <param name="parameters">url参数</param>
        /// <returns>真正的openId</returns>
        private OAuthAccessTokenResult GetRealOpenId(string code)
        {
            OAuthAccessTokenResult result = new OAuthAccessTokenResult();
            try
            {
                result = OAuthApi.GetAccessToken(appID, appSecret, code);
            }
            catch (Exception ex)
            {
                m_Log.Error(ex.Message, ex);
            }
            return result;
        }
    }

保存访问者记录,识别访问者和分享者。

 

5. 处理文字请求

在CustomMessageHandler里处理文字请求,详细的使用方法可参考《用c#开发微信(2)扫描二维码,用户授权后获取用户基本信息 (源码下载)》:

public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
        {
            var responseMessage = CreateResponseMessage<ResponseMessageNews>();
            responseMessage.Articles.Add(new Article()
            {
                Title = "首页",
                Description = "点击进入首页",
                PicUrl = "",
                Url = System.Configuration.ConfigurationManager.AppSettings["site"] + "/WeixinPageIndex.aspx?u=" + requestMessage.FromUserName
            });
            return responseMessage;
        }

这里把访问者的OpenId带上,为了方便识别访问者和分享者。

 

 

所有界面如下:

未完待续!!!

 

 

用c#开发微信 系列汇总
时间: 2024-10-29 19:08:35

用c#开发微信 (13) 微统计 - 阅读分享统计系统 3 UI设计及后台处理的相关文章

用c#开发微信 (11) 微统计 - 阅读分享统计系统 1 基础架构搭建

微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享与来源统计及手机网页在朋友圈的传播路径分析. 本系统使用最传统的三层架构.本文是微统计的第一篇,主要介绍如下内容: 1. 数据库设计 2. 数据访问框架层及数据实体层 3. 数据访问层 4. 视图实体定义层   下面是详细实现步骤: 1. 数据库设计 阅读记录 PageNav 分享记录 PageSh

用c#开发微信 (14) 微统计 - 阅读分享统计系统 4 部署测试 (最终效果图)

微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享与来源统计及手机网页在朋友圈的传播路径分析. 本文是微统计的第四篇,主要介绍如下内容:   1. 部署 2. 测试   下面是详细的实现方法: 一.部署 1. Entity Framework 错误 如果出现下面的错误: The EntityContainer name must be unique

用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现

我们可以使用微信的"生成带参数二维码接口"和 "用户管理接口",来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 上次介绍了<用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建>,主要介绍了数据访问层的实现.本文是微渠道的第二篇,主要介绍如下内容: 1. 各个实体具体业务实现 2. 同步微信个人用户信息   下面是详细的实现方法: 1. 各个实体具体业务实现

用c#开发微信 (8) 微渠道 - 推广渠道管理系统 3 UI设计及后台处理

我们可以使用微信的"生成带参数二维码接口"和 "用户管理接口",来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 前面二篇<用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建>, <用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现>分别介绍了数据访问层和业务逻辑层. 本文是微渠道的第三篇,主要介绍如下内容: 1. 接收二维码扫

用c#开发微信 (9) 微渠道 - 推广渠道管理系统 4 部署测试 (最终效果图)

我们可以使用微信的"生成带参数二维码接口"和 "用户管理接口",来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本文是微渠道的第四篇,主要介绍如下内容: 1. 部署 2. 测试   下面是详细的实现方法: 一.部署 1. Entity Framework 错误 如果出现下面的错误: The EntityContainer name must be unique. An EntityCont

用c#开发微信 (16) 微活动 2 刮刮卡

微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公众账号关注.对于企业来说,做微信推广重要的一个方面就是提高用户和公众账号之间的黏度,而微信刮刮卡就是其中最为常见的活动. 下面详细介绍: 一.使用 1. 新建一个刮刮卡的活动: 2. 奖项设置 3. 保存后,在微信里给公众号发一个“刮刮卡”的消息, 就会收到刮刮卡的内容,进入活动后,就可以刮奖了 二

用c#开发微信 (17) 微活动 3 投票活动 (文本投票)

前面介绍了微活动<大转盘> 和 <刮刮卡>,这次介绍下微投票,微投票分二种,一种是文本投票, 一种是图片投票.   下面介绍文本投票的详细步骤: 1. 新建文本投票活动     代码实现: <div class="tab-content" > <dl> <dt>投票标题:</dt> <dd> <asp:TextBox runat="server" ID="title&

用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建

我们可以使用微信的"生成带参数二维码接口"和 "用户管理接口",来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本系统使用最传统的三层架构.本文是微渠道的第一篇,主要介绍如下内容: 1. 数据库设计 2. 数据访问框架层及数据实体层 3. 数据访问层 4. 视图实体定义层   下面是详细实现步骤: 1. 数据库设计 微信用户信息表 WeixinUserInfo 推广渠道类型表 Channe

用c#开发微信 (10) JS-SDK 基本用法- 分享接口&ldquo;发送到朋友&rdquo;

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享.扫一扫.卡券.支付等微信特有的能力,为微信用户提供更优质的网页体验. 本文以介绍了分享接口里的"发送给朋友"事件的基本用法,其它的类推. JSSDK使用步骤 1:绑定域名 先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安