用c#开发微信 (8) 微渠道 - 推广渠道管理系统 3 UI设计及后台处理
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息。这样就可以统计和分析不同推广渠道的推广效果。
前面二篇《用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建》, 《用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现》分别介绍了数据访问层和业务逻辑层。 本文是微渠道的第三篇,主要介绍如下内容:
1. 接收二维码扫描事件
2. 推广渠道类型管理
3. 推广渠道管理
4. 推广渠道二维码扫描记录列表
5. 下载渠道二维码
6. 微信用户列表
下面是详细的实现方法:
1. 接收二维码扫描事件
可参考前面的 《用c#开发微信 (4) 基于Senparc.Weixin框架的接收事件推送处理 (源码下载)》,这里就不过多讲解了:
/// <summary>
/// 自定义MessageHandler
/// 把MessageHandler作为基类,重写对应请求的处理方法
/// </summary>
public partial class CustomMessageHandler : MessageHandler<MessageContext<IRequestMessageBase, IResponseMessageBase>>
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="inputStream"></param>
/// <param name="maxRecordCount"></param>
public CustomMessageHandler(Stream inputStream, int maxRecordCount = 0)
: base(inputStream, null, maxRecordCount)
{
//这里设置仅用于测试,实际开发可以在外部更全局的地方设置,
//比如MessageHandler<MessageContext>.GlobalWeixinContext.ExpireMinutes = 3。
WeixinContext.ExpireMinutes = 3;
}
public override void OnExecuting()
{
//测试MessageContext.StorageData
if (CurrentMessageContext.StorageData == null)
{
CurrentMessageContext.StorageData = 0;
}
base.OnExecuting();
}
public override void OnExecuted()
{
base.OnExecuted();
CurrentMessageContext.StorageData = ((int)CurrentMessageContext.StorageData) + 1;
}
/// <summary>
/// 处理扫描请求
/// 用户扫描带场景值二维码时,如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_ScanRequest(RequestMessageEvent_Scan requestMessage)
{
int sceneId = 0;
int.TryParse(requestMessage.EventKey, out sceneId);
if (sceneId > 0)
{
new ChannelScanBll().SaveScan(requestMessage.FromUserName, sceneId, ScanType.Scan);
}
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "扫描已记录";
return responseMessage;
}
/// <summary>
/// 处理关注请求
/// 用户扫描带场景值二维码时,如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
if (!string.IsNullOrWhiteSpace(requestMessage.EventKey))
{
string sceneIdstr = requestMessage.EventKey.Substring(8);
int sceneId = 0;
int.TryParse(sceneIdstr, out sceneId);
if (sceneId > 0)
{
new ChannelScanBll().SaveScan(requestMessage.FromUserName, sceneId, ScanType.Subscribe);
}
}
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "扫描已记录";
return responseMessage;
}
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
//所有没有被处理的消息会默认返回这里的结果
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "这条消息来自DefaultResponseMessage。";
return responseMessage;
}
}
前端开发框架使用Bootstrap,没有注明前台的页面表示前台不用显示任何内容
2. 推广渠道类型管理
主要是对推广渠道类型的新增、修改、删除及列表显示等
1) 渠道新增、修改页面
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>修改渠道类型</title>
</head>
<body>
<form id="Form1" class="form-horizontal" type="post" runat="server">
<%if (ViewState["channelType"] != null)
{%>
<%-- 修改表单 --%>
<input type="hidden" name="ID" value="<%=(ViewState["channelType"] as ChannelSystem.ViewEntity.ChannelTypeEntity).ID%>" />
<div class="control-group">
<label class="control-label" for="Name"><strong>渠道类型名称</strong></label>
<div class="controls">
<input type="text" name="Name" value="<%=(ViewState["channelType"] as ChannelSystem.ViewEntity.ChannelTypeEntity).Name%>" />
</div>
</div>
<%}
else
{%>
<%-- 新增表单 --%>
<div class="control-group">
<label class="control-label" for="Name"><strong>渠道类型名称</strong></label>
<div class="controls">
<input type="text" name="Name" />
</div>
</div>
<%}%>
<%-- 提交按钮 --%>
<button class="btn btn-large btn-primary" type="submit">保存</button>
</form>
</body>
</html>
后台:
/// <summary>
/// 新增或修改渠道类型
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//修改渠道类型,首先获取渠道类型数据
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
ViewState["channelType"] = new ChannelTypeBll().GetEntityById(id);
}
}
else
{
//将渠道类型新增或修改的数据保存到数据库
var entity = new ChannelTypeEntity()
{
ID = Request.Form["ID"] == null ? 0 : int.Parse(Request.Form["ID"]),
Name = Request.Form["Name"]
};
new ChannelTypeBll().UpdateOrInsertEntity(entity);
//回到渠道类型列表页面
Response.Redirect("ChannelTypeList.aspx");
Response.End();
}
}
2) 渠道类型列表页面
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>渠道类型列表</title>
</head>
<!-- #Bootstrap -->
<link href="Css/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/bootstrap.min.js"></script>
<!-- #Jquery -->
<script src="Scripts/jquery-1.9.1.min.js"></script>
<body>
<div class="container">
<form id="Form1" class="form-horizontal" type="post" runat="server">
<h2 class="form-signin-heading">渠道类型列表</h2>
<a class="btnGrayS vm doaddit" href="ChannelTypeEdit.aspx">添加</a> <a class="btnGrayS vm doaddit" href="ChannelList.aspx">渠道列表</a>
<table id="listTable" class="table table-bordered table-hover dataTable" style="width: auto">
<thead>
<tr>
<th style="border-color: #ddd; color: Black">ID
</th>
<th style="border-color: #ddd; color: Black">渠道类型名称
</th>
<th style="border-color: #ddd; color: Black">操作
</th>
</tr>
</thead>
<tbody>
<% foreach (ChannelSystem.ViewEntity.ChannelTypeEntity channelType in (ViewState["ChannelTypeList"] as List<ChannelSystem.ViewEntity.ChannelTypeEntity>))
{ %>
<tr>
<td><%= channelType.ID%>
</td>
<td><%= channelType.Name%>
</td>
<td>
<p>
<a class="btnGrayS vm doaddit" href="ChannelTypeEdit.aspx?id=<%= channelType.ID%>">编辑</a>
<a href="javascript:void(0)" data="<%= channelType.ID%>" class="dodelit deleteChannelType">删除</a>
</p>
</td>
</tr>
<% } %>
</tbody>
</table>
</form>
</div>
<script>
$(function () {
$(".deleteChannelType").click(function () {
if (confirm("确定删除吗?")) {
var id = $(this).attr("data");
$.ajax({
url: "ChannelTypeDelete.aspx?id=" + id,
type: "get",
success: function (repText) {
if (repText && repText == "True") {
window.location.reload();
} else {
alert(repText.ErrorMsg);
}
},
complete: function (xhr, ts) {
xhr = null;
}
});
}
});
});
</script>
</body>
</html>
后台:
/// <summary>
/// 渠道类型列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道类型列表数据
ViewState["ChannelTypeList"] = new ChannelTypeBll().GetEntities();
}
3) 渠道类型删除页面
后台:
/// <summary>
/// 删除渠道类型
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道类型ID
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
//删除渠道类型并返回删除结果
bool result = new ChannelTypeBll().DeleteEntityById(id);
Response.Write(result.ToString());
Response.End();
}
}
3. 推广渠道管理
主要是对推广渠道的新增、修改、删除及列表显示等
1) 渠道新增、修改页面
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>修改渠道</title>
</head>
<body>
<form id="Form1" class="form-horizontal" type="post" runat="server">
<%if (ViewState["channel"] != null)
{%>
<%-- 修改表单 --%>
<input type="hidden" name="ID" value="<%=(ViewState["channel"] as ChannelSystem.ViewEntity.ChannelEntity).ID%>" />
<div class="control-group">
<label class="control-label" for="Name"><strong>渠道名称</strong></label>
<div class="controls">
<input type="text" name="Name" value="<%=(ViewState["channel"] as ChannelSystem.ViewEntity.ChannelEntity).Name%>" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="ChannelTypeId"><strong>所属渠道类型</strong></label>
<div class="controls">
<%-- 构造渠道类型下拉框 --%>
<select name="ChannelTypeId">
<% foreach (ChannelSystem.ViewEntity.ChannelTypeEntity channelType in (ViewState["ChannelTypeList"] as List<ChannelSystem.ViewEntity.ChannelTypeEntity>))
{ %>
<%if (channelType.ID == (ViewState["channel"] as ChannelSystem.ViewEntity.ChannelEntity).ChannelTypeId)
{%>
<%-- 设置渠道类型下拉框初始选中项目 --%>
<option value="<%=channelType.ID %>" selected="selected"><%=channelType.Name %></option>
<%}
else
{%>
<option value="<%=channelType.ID %>"><%=channelType.Name %></option>
<%}%>
<% } %>
</select>
</div>
</div>
<%}
else
{%>
<%-- 新增表单 --%>
<div class="control-group">
<label class="control-label" for="Name"><strong>渠道名称</strong></label>
<div class="controls">
<input type="text" name="Name" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="ChannelTypeId"><strong>所属渠道类型</strong></label>
<div class="controls">
<%-- 构造渠道类型下拉框 --%>
<select name="ChannelTypeId">
<% foreach (ChannelSystem.ViewEntity.ChannelTypeEntity channelType in (ViewState["ChannelTypeList"] as List<ChannelSystem.ViewEntity.ChannelTypeEntity>))
{ %>
<option value="<%=channelType.ID %>"><%=channelType.Name %></option>
<% } %>
</select>
</div>
</div>
<%}%>
<%-- 提交按钮 --%>
<button class="btn btn-large btn-primary" type="submit">保存</button>
</form>
</body>
</html>
后台:
/// <summary>
/// 新增或修改渠道
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//获取渠道类型列表数据
ViewState["ChannelTypeList"] = new ChannelTypeBll().GetEntities();
//修改渠道,首先获取渠道数据
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
ViewState["Channel"] = new ChannelBll().GetEntityById(id);
}
}
else
{
//将渠道新增或修改的数据保存到数据库
var entity = new ChannelEntity()
{
ID = Request.Form["ID"] == null ? 0 : int.Parse(Request.Form["ID"]),
Name = Request.Form["Name"],
ChannelTypeId = int.Parse(Request.Form["ChannelTypeId"])
};
new ChannelBll().UpdateOrInsertEntity(entity);
//回到渠道列表页面
Response.Redirect("ChannelList.aspx");
Response.End();
}
}
2) 渠道列表页面
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>渠道类型列表</title>
</head>
<!-- #Bootstrap -->
<link href="Css/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/bootstrap.min.js"></script>
<!-- #Jquery -->
<script src="Scripts/jquery-1.9.1.min.js"></script>
<body>
<div class="container">
<form id="Form1" class="form-horizontal" type="post" runat="server">
<h2 class="form-signin-heading">渠道类型列表</h2>
<a class="btnGrayS vm doaddit" href="ChannelTypeEdit.aspx">添加</a> <a class="btnGrayS vm doaddit" href="ChannelList.aspx">渠道列表</a>
<table id="listTable" class="table table-bordered table-hover dataTable" style="width: auto">
<thead>
<tr>
<th style="border-color: #ddd; color: Black">ID
</th>
<th style="border-color: #ddd; color: Black">渠道类型名称
</th>
<th style="border-color: #ddd; color: Black">操作
</th>
</tr>
</thead>
<tbody>
<% foreach (ChannelSystem.ViewEntity.ChannelTypeEntity channelType in (ViewState["ChannelTypeList"] as List<ChannelSystem.ViewEntity.ChannelTypeEntity>))
{ %>
<tr>
<td><%= channelType.ID%>
</td>
<td><%= channelType.Name%>
</td>
<td>
<p>
<a class="btnGrayS vm doaddit" href="ChannelTypeEdit.aspx?id=<%= channelType.ID%>">编辑</a>
<a href="javascript:void(0)" data="<%= channelType.ID%>" class="dodelit deleteChannelType">删除</a>
</p>
</td>
</tr>
<% } %>
</tbody>
</table>
</form>
</div>
<script>
$(function () {
$(".deleteChannelType").click(function () {
if (confirm("确定删除吗?")) {
var id = $(this).attr("data");
$.ajax({
url: "ChannelTypeDelete.aspx?id=" + id,
type: "get",
success: function (repText) {
if (repText && repText == "True") {
window.location.reload();
} else {
alert(repText.ErrorMsg);
}
},
complete: function (xhr, ts) {
xhr = null;
}
});
}
});
});
</script>
</body>
</html>
后台:
/// <summary>
/// 渠道列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道列表数据
ViewState["ChannelList"] = new ChannelBll().GetEntities();
}
3) 渠道删除页面
后台:
/// <summary>
/// 删除渠道
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道ID
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
//删除渠道并返回删除结果
bool result = new ChannelBll().DeleteEntityById(id);
Response.Write(result.ToString());
Response.End();
}
}
4. 推广渠道二维码扫描记录列表
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>扫描记录列表</title>
</head>
<!-- #Bootstrap -->
<link href="Css/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/bootstrap.min.js"></script>
<!-- #Jquery -->
<script src="Scripts/jquery-1.9.1.min.js"></script>
<body>
<div class="container">
<form id="Form1" class="form-horizontal" type="post" runat="server">
<h2 class="form-signin-heading">扫描记录列表</h2>
<table id="listTable" class="table table-bordered table-hover dataTable" style="width: auto">
<thead>
<tr>
<th style="border-color: #ddd; color: Black">ID
</th>
<th style="border-color: #ddd; color: Black">扫描类型
</th>
<th style="border-color: #ddd; color: Black">扫描时间
</th>
<th style="border-color: #ddd; color: Black">所属渠道ID
</th>
<th style="border-color: #ddd; color: Black">微信用户OpenId
</th>
<th style="border-color: #ddd; color: Black">头像
</th>
<th style="border-color: #ddd; color: Black">昵称
</th>
<th style="border-color: #ddd; color: Black">性别
</th>
<th style="border-color: #ddd; color: Black">国家
</th>
<th style="border-color: #ddd; color: Black">省
</th>
<th style="border-color: #ddd; color: Black">市
</th>
<th style="border-color: #ddd; color: Black">关注时间
</th>
</tr>
</thead>
<tbody>
<% foreach (ChannelSystem.ViewEntity.ChannelScanDisplayEntity channelScanDisplay in (ViewState["ChannelScanDisplayList"] as List<ChannelSystem.ViewEntity.ChannelScanDisplayEntity>))
{ %>
<tr>
<td><%= channelScanDisplay.ScanEntity.ID%>
</td>
<td><%= channelScanDisplay.ScanEntity.ScanType.ToString()%>
</td>
<td><%= channelScanDisplay.ScanEntity.ScanTime.ToString()%>
</td>
<td><%= channelScanDisplay.ScanEntity.ChannelId.ToString()%>
</td>
<td><%= channelScanDisplay.ScanEntity.OpenId%>
</td>
<td>
<img width="50px" src="<%= channelScanDisplay.UserInfoEntity.HeadImgUrl%>" />
</td>
<td><%= channelScanDisplay.UserInfoEntity.NickName%>
</td>
<td><%= channelScanDisplay.UserInfoEntity.Sex.ToString()%>
</td>
<td><%= channelScanDisplay.UserInfoEntity.Country%>
</td>
<td><%= channelScanDisplay.UserInfoEntity.Province%>
</td>
<td><%= channelScanDisplay.UserInfoEntity.City%>
</td>
<td><%= channelScanDisplay.UserInfoEntity.SubscribeTime.ToShortDateString()%>
</td>
</tr>
<% } %>
</tbody>
</table>
</form>
</div>
</body>
</html>
后台:
/// <summary>
/// 渠道扫描记录列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道ID
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
//获取渠道扫描记录列表数据
ViewState["ChannelScanDisplayList"] = new ChannelScanBll().GetChannelScanList(id);
}
}
5. 下载渠道二维码
后台:
/// <summary>
/// 下载渠道二维码
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
//获取渠道ID
int id;
if (int.TryParse(Request.QueryString["id"], out id))
{
var entity = new ChannelBll().GetEntityById(id);
//将数据库中Base64String格式图片转换为Image格式,返回给浏览器
string base64Image = File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/") + entity.Qrcode);
byte[] arr = Convert.FromBase64String(base64Image);
MemoryStream ms = new MemoryStream(arr);
Response.ContentType = "image/jpeg";
ms.WriteTo(Response.OutputStream);
Response.End();
}
}
6. 微信用户列表
前台:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>微信用户列表</title>
</head>
<!-- #Bootstrap -->
<link href="Css/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/bootstrap.min.js"></script>
<!-- #Jquery -->
<script src="Scripts/jquery-1.9.1.min.js"></script>
<body>
<div class="container">
<form id="Form1" class="form-horizontal" type="post" runat="server">
<h2 class="form-signin-heading">微信用户列表</h2>
<table id="listTable" class="table table-bordered table-hover dataTable" style="width: auto">
<thead>
<tr>
<th style="border-color: #ddd; color: Black">OpenId
</th>
<th style="border-color: #ddd; color: Black">头像
</th>
<th style="border-color: #ddd; color: Black">昵称
</th>
<th style="border-color: #ddd; color: Black">性别
</th>
<th style="border-color: #ddd; color: Black">国家
</th>
<th style="border-color: #ddd; color: Black">省
</th>
<th style="border-color: #ddd; color: Black">市
</th>
<th style="border-color: #ddd; color: Black">注册时间
</th>
</tr>
</thead>
<tbody>
<% foreach (ChannelSystem.ViewEntity.WeixinUserInfoEntity weixinUserInfo in (ViewState["WeixinUserInfoList"] as List<ChannelSystem.ViewEntity.WeixinUserInfoEntity>))
{ %>
<tr>
<td><%= weixinUserInfo.OpenId%>
</td>
<td>
<img width="50px" src="<%= weixinUserInfo.HeadImgUrl%>" />
</td>
<td><%= weixinUserInfo.NickName%>
</td>
<td><%= weixinUserInfo.Sex.ToString()%>
</td>
<td><%= weixinUserInfo.Country%>
</td>
<td><%= weixinUserInfo.Province%>
</td>
<td><%= weixinUserInfo.City%>
</td>
<td><%= weixinUserInfo.SubscribeTime.ToShortDateString()%>
</td>
</tr>
<% } %>
</tbody>
</table>
</form>
</div>
</body>
</html>
后台:
protected void Page_Load(object sender, EventArgs e)
{
//获取微信用户列表数据
ViewState["WeixinUserInfoList"] = new WeixinUserInfoBll().GetEntities();
}
上一篇,讲过同步微信用户的线程只会在这个页面第一次打开时被调用。
同样地,我们也要建一个Index页面作为入口:
private readonly string Token = ConfigurationManager.AppSettings["token"];//与微信公众账号后台的Token设置保持一致,区分大小写。
protected void Page_Load(object sender, EventArgs e)
{
string signature = Request["signature"];
string timestamp = Request["timestamp"];
string nonce = Request["nonce"];
string echostr = Request["echostr"];
if (Request.HttpMethod == "GET")
{
//get method - 仅在微信后台填写URL验证时触发
if (CheckSignature.Check(signature, timestamp, nonce, Token))
{
WriteContent(echostr); //返回随机字符串则表示验证通过
}
else
{
WriteContent("failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, Token) + "。" +
"如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。");
}
Response.End();
}
else
{
//post method - 当有用户想公众账号发送消息时触发
if (!CheckSignature.Check(signature, timestamp, nonce, Token))
{
WriteContent("参数错误!");
return;
}
//设置每个人上下文消息储存的最大数量,防止内存占用过多,如果该参数小于等于0,则不限制
var maxRecordCount = 10;
//自定义MessageHandler,对微信请求的详细判断操作都在这里面。
var messageHandler = new CustomMessageHandler(Request.InputStream, maxRecordCount);
try
{
//测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。
messageHandler.RequestDocument.Save(
Server.MapPath("~/App_Data/" + DateTime.Now.Ticks + "_Request_" +
messageHandler.RequestMessage.FromUserName + ".txt"));
//执行微信处理过程
messageHandler.Execute();
//测试时可开启,帮助跟踪数据
messageHandler.ResponseDocument.Save(
Server.MapPath("~/App_Data/" + DateTime.Now.Ticks + "_Response_" +
messageHandler.ResponseMessage.ToUserName + ".txt"));
WriteContent(messageHandler.ResponseDocument.ToString());
return;
}
catch (Exception ex)
{
//将程序运行中发生的错误记录到App_Data文件夹
using (TextWriter tw = new StreamWriter(Server.MapPath("~/App_Data/Error_" + DateTime.Now.Ticks + ".txt")))
{
tw.WriteLine(ex.Message);
tw.WriteLine(ex.InnerException.Message);
if (messageHandler.ResponseDocument != null)
{
tw.WriteLine(messageHandler.ResponseDocument.ToString());
}
tw.Flush();
tw.Close();
}
WriteContent("");
}
finally
{
Response.End();
}
}
}
private void WriteContent(string str)
{
Response.Output.Write(str);
}
最后整个View就如下图:
未完待续!!!
用c#开发微信 系列汇总
用c#开发微信 (8) 微渠道 - 推广渠道管理系统 3 UI设计及后台处理的更多相关文章
- 用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 上次介绍了 ...
- 用c#开发微信 (11) 微统计 - 阅读分享统计系统 1 基础架构搭建
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享 ...
- C#开发微信门户及应用(10)--在管理系统中同步微信用户分组信息
在前面几篇文章中,逐步从原有微信的API封装的基础上过渡到微信应用平台管理系统里面,逐步介绍管理系统中的微信数据的界面设计,以及相关的处理操作过程的逻辑和代码,希望从更高一个层次,向大家介绍微信的应用 ...
- 用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本系统使用 ...
- 用c#开发微信 (9) 微渠道 - 推广渠道管理系统 4 部署测试 (最终效果图)
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本文是微渠 ...
- 用c#开发微信 (15) 微活动 1 大转盘
微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...
- 用c#开发微信 (16) 微活动 2 刮刮卡
微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...
- 用c#开发微信 (12) 微统计 - 阅读分享统计系统 2 业务逻辑实现
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享 ...
- 用c#开发微信 (13) 微统计 - 阅读分享统计系统 3 UI设计及后台处理
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读. ...
随机推荐
- 学习java第7天
关于继承还需要留意的是,子类中的所有构造方法都默认访问父类的无参构造,注意是无参,而且是必须的,如果父类没有无参子类就会报错.如果你不想给父类无参构造,那么在子类中加上super(),显式的调用有参构 ...
- 多媒体(4):JPEG图像压缩编码
(重要的事放前面)此JPEG的C++实现见 https://github.com/chencjGene/SoftEngineering/tree/master/JPEG 目录 多媒体(1):MCI接口 ...
- C++STL算法速查
非变易算法 /* 第21章 非变易算法 Non-modifying sequence operations 21.0 advance, distance 为了了解模板,先了解一下这两个迭代器操作函 ...
- hdu 2196 computer
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- HDU 5410 CRB and His Birthday(完全背包变形)
CRB and His Birthday Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- urllib.request
[urllib.request] 1.urlopen结果保存在内存. 2.ulrretrieve结果保存到文件. 3.response有read方法. 4.可以创建Request对象. 5.发送Pos ...
- 关于生物信息学与R的相关资料和网站
生物信息学的相关论坛:http://www.omicshare.com/forum/ 糗世界:http://qiubio.com:8080/ 统计之都网站 绘制QQ图和曼哈顿图:http://www. ...
- mysql学习(二)
(1)存储过程:存储过程是SQL语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理: (2)存储过程优点:增强SQL语句的功能和灵活性,实现较快的执行速度,减少网络流量: (3)存储过程结构 ...
- XE3随笔10:TSuperType
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- 王爽-汇编语言-综合研究一-搭建简易C环境
(一) 学习过程: 整个过程分为两个部分: 第一:将TC2.0的环境使用虚拟软盘复制到DOS虚拟机中: 打开WinImage,fileànew,由于TC2.0的环境解压后为2.02M,所以我们在Sta ...