ASP.NET系统整合DiscuzNT3.6之注意事项

  最近在做一个ASP.NET的系统,需要与Discuz整合实现双向登录、注册、修改密码这些简单的集成。

  查了一些资料,最后还是选择了官方提供的DiscuzToolkit,由于是开源的,所以用起来也方便,可以根据自己的需求做一些调整,在此也感谢DZ团队。

  第一步,当然还是将论坛安装好,调试好,一切正常。

  第二步,学习官方提供API文档,http://nt.discuz.net/showtopic-66493.aspx

  第三步,查看官方提供的示例文档,http://nt.discuz.net/showtopic-81187.aspx

  第四步,项目中引入Discuz.Toolkit.dll(可直接将开源的项目添加到项目中)在网站中增加同步登录或注册BBS帐号的方法,登录后或注册完成时,如下:

View Code
//......登录代码,登录成功后。

//将登录信息同步论坛,若没有此会员则 注册
try
{
    DiscuzSession ds = DiscuzSessionHelper.GetSession();
    Discuz.Toolkit.User user = null;
    try
    {
        user = ds.GetLoggedInUser().GetUserInfo();
    }
    catch { }
    if (user == null || user.UserName != _user.UserName)
    {
        int uid = ds.GetUserID(_user.UserName);
        if (uid < 1)
        {
            //注册新用户
            uid = ds.Register(_user.UserName, password, _user.Email, true);
            //填充基本信息
            UserForEditing ufe = new UserForEditing();
            ufe.RealName = _user.ActualName;
            ufe.IdCard = _user.IdCard;
            ufe.Mobile = _user.Phone;
            ufe.Phone = _user.Tel;
            ufe.Gender = _user.Gender.ToString();
            ufe.NickName = _user.ActualName;
            ufe.GroupId = 10;//会员等级,可能采用特殊组来做一些其它应用。
            ds.SetUserInfo(uid, ufe);
        }
        //同步登录
        ds.Login(uid, password, true, 0, "");
    }
}
catch (Exception ex)
{
    LogHelper.WriteLog(ex); //错误日志
} 
注册或修改密码对应的方法中,同步方法如下:
View Code
DiscuzSession ds = DiscuzSessionHelper.GetSession();
int uid = 0;
try
{
    //user = ds.GetLoggedInUser().GetUserInfo();
    uid = ds.GetUserID(oldm.UserName);

    if (uid > 0)
    {
        //TODO:Discuz.Web.Services.Actions.Users 与 Discuz.Toolkit.User要对应起来  UserForEditing也一样
        //填充基本信息
        UserForEditing ufe = new UserForEditing();
        ufe.RealName = model.ActualName;
        ufe.IdCard = model.IdCard;
        ufe.Mobile = model.Phone;
        ufe.Phone = model.Tel;
        ufe.Gender = model.Gender.HasValue ? model.Gender.ToString() : "0";
        ufe.NickName = model.ActualName;
        ufe.Password = model.Password;
        ufe.GroupId = model.Level.Value + 16;
        ufe.UserName = model.UserName;
        ufe.Email = model.Email;
        ufe.WebSite = "";
        ufe.Location = "";
        ds.SetUserInfo(uid, ufe);
    }
}
catch(Exception ex) {
    LogHelper.WriteLog(ex);
} 

   以上GroupId、UserName属性,在官方提供的开源项目UserForEditing类中没有这两个属性,我们可以手动加入一下,同时要注意Discuz.Web.Services.Actions.Users 与 Discuz.Toolkit.User要对应起来  UserForEditing也一样,如下: 

View Code
//Discuz.Web.Services.API下UserForEditing类中增加:

[JsonPropertyAttribute("group_id")]
public int? GroupId; //用户组ID

[JsonPropertyAttribute("user_name")]
public string UserName; //用户名



//Discuz.Web.Services.API.Actions下Users类的SetInfo()方法中增加:

//组别

if (ufe.GroupId.HasValue)
{
    userinfo.Groupid = ufe.GroupId.Value;
}
//用户名
if (ufe.UserName != null && ufe.UserName!="")
{
    userinfo.Username = ufe.UserName;
}

 如果Services中与前面调用的类属性不一致的话,会出现序列化异常。  

至此,我们已经实现了网站到论坛的同步登录、注册、修改基本信息功能。


接下来就是实现,论坛到网站的同步登录、注册、修改了,在这里仅以登录为例,其它都差不多。 
  在这部分,我们就要使用官方提供的API操作了。

  第一步,需要在后台“扩展” - “整合设置” 那里加上调用URL,如图:

  上面,同步数据的URL地址为网站中的一个处理页面,主要就是在这个页面里实现同步操作。

  第二上,了解参数类型,DZ的同步机制是,在论坛有登录、注册等动作操作后,通过javascript脚本,向指定的URL地址传递参数的方式实现通信,参数的基本格式为uid=1&user_name=test&time=1270283913981&action=login&sig=dskljoiwjelkjskdjfoiwelkjsifs。可以在官方提供的API说明中了解这些参数的作用,特别是sig的生成。

  第三步,了解Discuz.Forum.Sync类中各种action的值及参数,方便在网站的api页面中处理。

  接下来,我们来实现登录同步,如下:

View Code
private DiscuzSession ds;
private string action = "", user_name, password;
private int uid = 0;
protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        ds = DiscuzSessionHelper.GetSession();
        if (!IsPostBack)
        {
            action = Handler.RequestQueryString("action");
            uid = Handler.RequestQueryInt("uid");
            user_name = Handler.RequestQueryString("user_name");
            password = Handler.RequestQueryString("password");
            if (action != "" && check_sig()) //验证sig是否合法
            {
                switch (action)
                {
                    case "login": //同步登录:uid,user_name,time,action 正序后 + secret(密钥) Md5后 算出sig
                        Login();
                        break;
                    case "logout": //同步退出
                        LoginOut();
                        break;
                    case "updatepwd": //同步修改密码
                        break;
                }
            }
        }
    }
    catch (Exception ex) {
        LogHelper.WriteLog(ex);
    }
}

/// <summary>
/// 登录
/// </summary>
private void Login() {
    Discuz.Toolkit.User user= ds.GetUserInfo(uid);
    if (user != null)
        MemberOp.ValidateLogin(user.UserName, user.Password, true);
}
/// <summary>
/// 退出
/// </summary>
private void LoginOut()
{
    MemberOp.LoginOut(false);
} 

  以上check_sig()方法里,主要就是验证sig是否正确,这个值是通过参数排序后md5出来的,具体过程可以参考方法:Discuz.Forum.Sync.GetUrl()。

  注意密钥apikey、secret、url这几个值一定要配置正确。至此已实现论坛到网站的同步登录和退出。 

DiscuzToolkit线程同步,相信这两个问题肯定会碰到:

(1)在注册用户时,碰到以下异常:当前会话所提交的call_id没有大于前一次的call_id

(2)注册用户时,碰到以下异常:An item with the same key has already been added.

解决办法:http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html

解决方案中,有一处线程锁的问题:

lock (_syncRoot)  可直接用 lock (this)

原文地址:https://www.cnblogs.com/greatwang/p/2711804.html