您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程

异步调用Discuz!NT接口的实现方法

寒云2025-07-07Discuz教程已有人查阅

导读最近在做Discuz!NT论坛与网站整合的东西,于是便用到了Discuz提供的Discuz! Toolkit看了看源码,应该说这是个不错的工具库,提供了关于注册

最近在做Discuz!NT论坛与网站整合的东西,于是便用到了Discuz提供的Discuz! Toolkit看了看源码,应该说这是个不错的工具库,提供了关于注册、登录、 文章、积分等论坛操作的一篮子功能,而且配备了对应的Wiki只可惜,Discuz!NT终归是异构的系统,响应速度和突发异常并非如自己的代码一样可控,使用同步方式调用API就显得有那么些不智了
好在Toolkit是开源的,可以DIY,看看它提供的同步访问Web Service方法:
public static byte[] GetResponseBytes(string apiUrl, string method_name, string postData)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(apiUrl);
request.Method = "POST";
request.ContentType = "application/x- -form-urlencoded";
request.ContentLength = postData.Length;
request.Timeout = 20000;
HttpWebResponse response = null;
try
{
StreamWriter swRequestWriter = new StreamWriter(request.GetRequestStream());
swRequestWriter.Write(postData);
if (swRequestWriter != null)
swRequestWriter.Close();
response = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return Encoding.UTF8.GetBytes(reader.ReadToEnd());
}
}
finally
{
if (response != null)
response.Close();
}
}
要进行异步的调用,原本的同步流程会被切成两部分:
1、调用开始等待响应
2、响应触发调用完成。
演化成语言:一个方法以委托的方式,在这两部分之间传递,第1部分会将方法指针(委托)塞入请求里,在流程执行到第2部分时,方法被取出回调。
先设计委托原型:
public delegate void GetResponseGeneric<T>(T objects);
异步请求数据结构:
public class RequestState
{
public HttpWebRequest request;
public HttpWebResponse response;
}
扩展一下Util工具类,加上异步调用接口方法:
/// <summary>
/// 异步获取响应开始
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fun">泛型回调方法</param>
/// <param name="method_name"></param>
/// <param name="parameters"></param>
#region void GetResponseBegin<T>(GetResponseGeneric<T> fun,string method_name, params DiscuzParam[] parameters)
public void GetResponseBegin<T>(GetResponseGeneric<T> fun,string method_name, params DiscuzParam[] parameters)
{
DiscuzParam[] signed = Sign(method_name, parameters);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < signed.Length; i++)
{
if (i > 0)
builder.Append("&");
builder.Append(signed.ToEncodedString());
}
//异步获取字节流
GetResponseBytesBegin<T>(fun,Url, method_name, builder.ToString());
}
#endregion
/// <summary>
/// 异步获取响应完成
/// </summary>
#region void GetReponseEnd<T>(GetResponseGeneric<T> fun,byte[] response_bytes)
public void GetReponseEnd<T>(GetResponseGeneric<T> fun, byte[] response_bytes)
{
XmlSerializer response_serializer = GetSerializer(typeof(T));
try
{
T response = (T)response_serializer.Deserialize(new MemoryStream(response_bytes));
//回调 调用方 接收方法
fun(response);
}
catch
{
Error error = (Error)ErrorSerializer.Deserialize(new MemoryStream(response_bytes));
throw new DiscuzException(error.ErrorCode, error.ErrorMsg);
}
}
#endregion
/// <summary>
/// 异步获取字节流开始
/// </summary>
/// <param name="callback">回调方法</param>
/// <param name="apiUrl"></param>
/// <param name="method_name"></param>
/// <param name="postData"></param>
#region void GetResponseBytesBegin<T>(GetResponseGeneric<T> fun,string apiUrl, string method_name, string postData)
private void GetResponseBytesBegin<T>(GetResponseGeneric<T> fun, string apiUrl, string method_name, string postData)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(apiUrl);
request.Method = "POST";
request.ContentType = "application/x- -form-urlencoded";
request.ContentLength = postData.Length;
request.Timeout = 20000;
StreamWriter swRequestWriter = new StreamWriter(request.GetRequestStream());
swRequestWriter.Write(postData);
if (swRequestWriter != null)
swRequestWriter.Close();
RequestState myRequestState = new RequestState();
myRequestState.request = request;
//异步调用
request.BeginGetResponse(ar => GetResponseBytesEnd<T>(fun, ar), myRequestState);
}
#endregion
/// <summary>
/// 异步获取字节流完成
/// </summary>
/// <param name="asynchronousResult"></param>
#region void GetResponseBytesEnd<T>(GetResponseGeneric<T> fun,IAsyncResult asynchronousResult)
private void GetResponseBytesEnd<T>(GetResponseGeneric<T> fun, IAsyncResult asynchronousResult)
{
RequestState myRequestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
try
{
//接收完成
myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult);
using (StreamReader reader = new StreamReader(myRequestState.response.GetResponseStream(), Encoding.UTF8))
{
byte[] response_bytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
//回调 异步获取响应完成 方法
GetReponseEnd<T>(fun, response_bytes);
}
}
catch (WebException ex)
{
DiscuzLogger.WriteLog(typeof(Util), ex);
}
finally
{
if (myRequestState.response != null)
myRequestState.response.Close();
}
}
#endregion
/// <summary>
/// 异步 获取主题列表 开始
/// </summary>
/// <param name="fid"></param>
/// <param name="page_size"></param>
/// <param name="page_index"></param>
/// <returns></returns>
public void GetTopicListBegin(GetResponseGeneric<TopicGetListResponse> fun,
int fid, int page_size, int page_index, string typeIdList)
{
List<DiscuzParam> param_list = new List<DiscuzParam>();
if (session_info != null && !string.IsNullOrEmpty(session_info.SessionKey))
{
param_list.Add(DiscuzParam.Create("session_key", session_info.SessionKey));
}
param_list.Add(DiscuzParam.Create("type_id_list", typeIdList));
param_list.Add(DiscuzParam.Create("fid", fid));
param_list.Add(DiscuzParam.Create("page_size", page_size));
param_list.Add(DiscuzParam.Create("page_index", page_index));
//异步开始
util.GetResponseBegin<TopicGetListResponse>(fun, "topics.getList", param_list.ToArray());
}
调用方使用起来只需要定义好接收方法,剩下就是收数据(CacheObjectCollection.HomepageTopicList是一个缓存项的getter/setter):
/// <summary>
/// 异步获取论坛指定板块的帖子列表开始
/// </summary>
/// <param name="fid">板块ID</param>
/// <param name="pageSize">数量</param>
/// <param name="pageIndex">索引</param>
/// <param name="typeIdList">主题ID 以 , 为分隔符</param>
#region static void HomepageTopicGetBegin(int fid, int pageSize, int pageIndex, string typeIdList)
public static void HomepageTopicGetBegin(int fid, int pageSize, int pageIndex, string typeIdList)
{
if (CacheObjectConllection.HomepageTopicList == null)
{
try
{
DiscuzSession session = GetSession();
session.GetTopicListBegin(HomepageTopicGetEnd, fid, pageSize, pageIndex, typeIdList);
}
catch (DiscuzException ex)
{
Logger.WriteLog(typeof(DiscuzHelper),
string.Format("DISCUZ!NT异步获取论坛指定板块的帖子列表错误:\r\n{0}"
, ex.ToString()));
}
}
}
#endregion
/// <summary>
/// 异步获取论坛指定板块的帖子列表完成
/// </summary>
#region static void HomepageTopicGetEnd(TopicGetListResponse result)
public static void HomepageTopicGetEnd(TopicGetListResponse result)
{
CacheObjectConllection.HomepageTopicList = result;
}
#endregion
到此,异步调用框架完成,个人感觉很好。

本文标签:

很赞哦! ()

相关教程

相关源码

  • pbootcms模板PC+WAP娱乐新闻资讯类博客网站源码该模板基于PbootCMS内核开发,专为娱乐新闻、健康生活类资讯网站设计,同时支持快速适配其他行业(如企业官网、博客门户等),仅需替换图文内容即可完成转型。查看源码
  • (自适应)蓝色建材亚克力板材装饰材料pbootcms网站模板这款基于PbootCMS开发的响应式模板为建材板材行业优化设计,适用于亚克力板材、建筑装饰材料等企业展示需求。采用HTML5技术实现手机/PC跨终端适配,管理员通过统一后台即可同步查看源码
  • 帝国cms7.5自适应手机端在线课程教育网站源码基于帝国CMS后台管理系统,支持在线修改支付参数、联系方式等配置信息,操作界面直观便捷。专注于在线教育视频领域,提供完整的视频课程展示、付费购买及在线支付解决方案。支持多种支付渠道,满足教育培训机构的运营需求。查看源码
  • (PC+WAP)蓝色新能源环保太阳能光伏模板pbootcms下载新能源环保行业网站解决方案为太阳能光伏系统企业打造的专业网站模板,助力新能源企业高效展示产品与服务PbootCMS内核开发,源码开放可修改PC与手机端自适应设计查看源码
  • 帝国cms7.5商城模板带图片视频广告位功能本模板基于帝国CMS7.5内核开发,为内容电商平台设计,集成文章、图片、视频多媒体展示与广告位管理功能。采用智能响应式技术,确保商品内容在不同设备上获得较优呈现效果,帮助快速构建专业的内容营销平台。查看源码
  • (自适应)游泳馆泳池水处理器设备pbootcms网站模板免费下载专注服务于泳池水处理设备制造商、泳池系统工程商等企业用户。模板预设设备分类体系、技术参数展示模块和解决方案呈现页面,满足行业特有展示需求。查看源码
分享笔记 (共有 篇笔记)
验证码:

本栏推荐