作者: zhongdaiqi

  • 手机支付体验

    体验场景:下班后,在西二旗地铁站自助售货机购买饮料。结果如图所示:

    image

    在这场体验比赛中,显然是支付宝胜出。地铁站人流量大,手机网络不稳定的情况下,微信支付基本处于不可用的状态,支付宝却巧妙的避开了,为支付宝的实现思路点赞!

    正如图示展示的那样,微信支付依赖于手机网络,用户扫描完二维码之后,数据是通过手机网络来回倒腾。而支付宝当面付则完全不需要手机网络,此时支付宝当面付仅通过声波将数据传给售货机,售货机本身有“神秘的网络”,数据在畅通的网络下来往,这才是可用的手机支付啊。支付宝当面付相当于把自身变成了一张虚拟的支付卡,脱离网络下存在。点赞!

  • 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)—-非对称加密、BASE64加密、MD5等常用加密处理

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)—-非对称加密、BASE64加密、MD5等常用加密处理 (转)

    俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。

    本篇继续继续整理优化已有的共用类库,并继续发表随笔介绍公用类库的接口方法以及详细使用操作,力求给自己继续优化,积攒更丰富的公用类库资源,加深了解的同时,也给大家展现公用类库好的方面。

    本篇的公用类库的介绍主题是加密解密的部分,加解密算法包括DES加解密、Base64加解密、

    AES RijndaelManaged加解密、MD5加密、以及RSA非对称加密等操作。如果你对前面的类库介绍文章有兴趣,可以参考下面的连接了解。

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(7)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(4)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(3)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(2)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)

    1、非对称加密、解密、验证辅助类 RSASecurityHelper

    本人开发过很多共享软件,在共享软件注册方面积累了一些自己的经验,其中采用非对称加密方式实现注册码验证的操作,就是其中一个比较重要的步骤,由于其逻辑不可逆的特点,采用非对称加密方式,较一般的对称加密方式,能够隐藏授权的逻辑,因此具有更好的效果。 这个非对称的解密解密、验证操作,是我所有共享软件里面用到的授权操作,很早很多朋友就这个问题问过我很多次,现在奉献给大家注册码实现的思路及操作接口,希望大家能够在享受代码带来的便利外,也可以提高自己对知识产权的保护。

    一般来说,非对称加密方式,结合代码混淆和强名称验证,是比较好的实现注册授权机制的功能。

    实现效果

    1)本辅助类主要是用来方便实现非对称加密、解密、验证等相关操作。

    2)非对称加密有RSA、椭圆曲线等,最流行的是RSA。所谓的非对称,是因为它有两个密钥,一个称为公钥,一个称为私钥。公钥是可以对外发布的,而私钥是自己保存的。用公钥加密,必须用私钥解密,反之,用私钥加密必须用公钥解密。所以,我们可以在软件中保存公钥的内容,这个是可以公开的;私钥我们可以自己留着。别人拿不到私钥,根本计算不出注册码来。

    3)使用辅助类RSASecurityHelper实现注册机制如下:

    a. 注册码产生过程:

    注册信息(包括用户名等信息)—> RSA私钥加密 —> 注册码。

    b. 软件验证注册码过程:

    注册码 —> RSA公钥验证 —> 验证成功或失败。


    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary>
    /// 非对称加密生成的私钥和公钥
    /// </summary>
    /// <param name=”privateKey”>私钥</param>
    /// <param name=”publicKey”>公钥</param>
    public static void GenerateRSAKey(out string privateKey, out string publicKey)
    #region 非对称数据加密(公钥加密)
    /// <summary>
    /// 非对称加密字符串数据,返回加密后的数据
    /// </summary>
    /// <param name=”publicKey”>公钥</param>
    /// <param name=”originalString”>待加密的字符串</param>
    /// <returns>加密后的数据</returns>
    public static string RSAEncrypt(string publicKey, string originalString)
    /// <summary>
    /// 非对称加密字节数组,返回加密后的数据
    /// </summary>
    /// <param name=”publicKey”>公钥</param>
    /// <param name=”originalBytes”>待加密的字节数组</param>
    /// <returns>返回加密后的数据</returns>
    public static string RSAEncrypt(string publicKey, byte[] originalBytes)
    #endregion
    #region 非对称解密(私钥解密)
    /// <summary>
    /// 非对称解密字符串,返回解密后的数据
    /// </summary>
    /// <param name=”privateKey”>私钥</param>
    /// <param name=”encryptedString”>待解密数据</param>
    /// <returns>返回解密后的数据</returns>
    public static string RSADecrypt(string privateKey, string encryptedString)
    /// <summary>
    /// 非对称解密字节数组,返回解密后的数据
    /// </summary>
    /// <param name=”privateKey”>私钥</param>
    /// <param name=”encryptedBytes”>待解密数据</param>
    /// <returns></returns>
    public static string RSADecrypt(string privateKey, byte[] encryptedBytes)
    #endregion
    #region 非对称加密签名、验证
    /// <summary>
    /// 使用非对称加密签名数据
    /// </summary>
    /// <param name=”privateKey”>私钥</param>
    /// <param name=”originalString”>待加密的字符串</param>
    /// <returns>加密后的数据</returns>
    public static string RSAEncrypSignature(string privateKey, string originalString)
    /// <summary>
    /// 对私钥加密签名的字符串,使用公钥对其进行验证
    /// </summary>
    /// <param name=”originalString”>未加密的文本,如机器码</param>
    /// <param name=”encrytedString”>加密后的文本,如注册序列号</param>
    /// <returns>如果验证成功返回True,否则为False</returns>
    public static bool Validate(string originalString, string encrytedString)
    /// <summary>
    /// 对私钥加密的字符串,使用公钥对其进行验证
    /// </summary>
    /// <param name=”originalString”>未加密的文本,如机器码</param>
    /// <param name=”encrytedString”>加密后的文本,如注册序列号</param>
    /// <param name=”publicKey”>非对称加密的公钥</param>
    /// <returns>如果验证成功返回True,否则为False</returns>
    public static bool Validate(string originalString, string encrytedString, string publicKey)

    复制代码

    #endregion

    2) 辅助类RSASecurityHelper的使用例子代码如下所示

    复制代码

    //生成加解密私钥、公钥
    string publicKey = “”;
    string privateKey = “”;
    RSASecurityHelper.GenerateRSAKey(out privateKey, out publicKey);
    string originalString = “testdata”;
    string encryptedString = RSASecurityHelper.RSAEncrypt(publicKey, originalString);
    string originalString2 = RSASecurityHelper.RSADecrypt(privateKey, encryptedString);
    if (originalString == originalString2)
    {
    MessageUtil.ShowTips(“解密完全正确”);
    }
    else
    {
    MessageUtil.ShowWarning(“解密失败”);
    }
    string regcode = RSASecurityHelper.RSAEncrypSignature(privateKey, originalString);
    bool validated = RSASecurityHelper.Validate(originalString, regcode, publicKey);

    MessageUtil.ShowTips( validated ? “验证成功” : “验证失败”);

    复制代码

    3)实际项目使用的注册验证代码如下所示。

    复制代码

    /// <summary>
    /// 每次程序运行时候,检查用户是否注册
    /// </summary>
    /// <returns>如果用户已经注册, 那么返回True, 否则为False</returns>
    public bool CheckRegister()
    {
    // 先获取用户的注册码进行比较
    string serialNumber = string.Empty; //注册码
    RegistryKey reg = Registry.CurrentUser.OpenSubKey(UIConstants.SoftwareRegistryKey, true);
    if (null != reg)
    {
    serialNumber = (string)reg.GetValue(“SerialNumber”);
    Portal.gc.bRegisted = Portal.gc.Register(serialNumber);
    }
    return Portal.gc.bRegisted;
    }
    /// <summary>
    /// 调用非对称加密方式对序列号进行验证
    /// </summary>
    /// <param name=”serialNumber”>正确的序列号</param>
    /// <returns>如果成功返回True,否则为False</returns>
    public bool Register(String serialNumber)
    {
    string hardNumber = HardwareInfoHelper.GetCPUId();
    return RSASecurityHelper.Validate(hardNumber, serialNumber);
    }
    public string GetHardNumber()
    {
    return HardwareInfoHelper.GetCPUId();

    }

    复制代码

    2、 DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作辅助类 EncodeHelper

    实现效果

    1)本辅助类主要是用来方便实现DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作。

    2)本辅助类实现多种加解密处理,可以实现字符串、文件、文件流等加密处理。该加密辅助类汇集各种加密处理逻辑,是一个非常常用、方便应对各种加密处理的辅助类。

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary>
    /// 使用默认加密
    /// </summary>
    /// <param name=”strText”></param>
    /// <returns></returns>
    public static string DesEncrypt(string strText)
    /// <summary>
    /// 使用默认解密
    /// </summary>
    /// <param name=”strText”>解密字符串</param>
    /// <returns></returns>
    public static string DesDecrypt(string strText)
    /// <summary>
    /// 加密字符串,注意strEncrKey的长度为8位
    /// </summary>
    /// <param name=”strText”>待加密字符串</param>
    /// <param name=”strEncrKey”>加密键</param>
    /// <returns></returns>
    public static string DesEncrypt(string strText, string strEncrKey)
    /// <summary>
    /// 解密字符串,注意strEncrKey的长度为8位
    /// </summary>
    /// <param name=”strText”>待解密的字符串</param>
    /// <param name=”sDecrKey”>解密键</param>
    /// <returns>解密后的字符串</returns>
    public static string DesDecrypt(string strText, string sDecrKey)
    /// <summary>
    /// 加密数据文件,注意strEncrKey的长度为8位
    /// </summary>
    /// <param name=”m_InFilePath”>待加密的文件路径</param>
    /// <param name=”m_OutFilePath”>输出文件路径</param>
    /// <param name=”strEncrKey”>加密键</param>
    public static void DesEncrypt(string m_InFilePath, string m_OutFilePath, string strEncrKey)
    /// <summary>
    /// 解密数据文件,注意strEncrKey的长度为8位
    /// </summary>
    /// <param name=”m_InFilePath”>待解密的文件路径</param>
    /// <param name=”m_OutFilePath”>输出路径</param>
    /// <param name=”sDecrKey”>解密键</param>
    public static void DesDecrypt(string m_InFilePath, string m_OutFilePath, string sDecrKey)
    #endregion
    #region 对称加密算法AES RijndaelManaged加密解密
    /// <summary>
    /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法)
    /// </summary>
    /// <param name=”encryptString”>待加密字符串</param>
    /// <returns>加密结果字符串</returns>
    public static string AES_Encrypt(string encryptString)
    /// <summary>
    /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法)
    /// </summary>
    /// <param name=”encryptString”>待加密字符串</param>
    /// <param name=”encryptKey”>加密密钥,须半角字符</param>
    /// <returns>加密结果字符串</returns>
    public static string AES_Encrypt(string encryptString, string encryptKey)
    /// <summary>
    /// 对称加密算法AES RijndaelManaged解密字符串
    /// </summary>
    /// <param name=”decryptString”>待解密的字符串</param>
    /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
    public static string AES_Decrypt(string decryptString)
    /// <summary>
    /// 对称加密算法AES RijndaelManaged解密字符串
    /// </summary>
    /// <param name=”decryptString”>待解密的字符串</param>
    /// <param name=”decryptKey”>解密密钥,和加密密钥相同</param>
    /// <returns>解密成功返回解密后的字符串,失败返回空</returns>
    public static string AES_Decrypt(string decryptString, string decryptKey)
    /// <summary>
    /// 加密文件流
    /// </summary>
    /// <param name=”fs”>文件流</param>
    /// <returns></returns>
    public static CryptoStream AES_EncryptStrream(FileStream fs, string decryptKey)
    /// <summary>
    /// 解密文件流
    /// </summary>
    /// <param name=”fs”>文件流</param>
    /// <returns></returns>
    public static CryptoStream AES_DecryptStream(FileStream fs, string decryptKey)
    /// <summary>
    /// 对指定文件加密
    /// </summary>
    /// <param name=”InputFile”>输入文件</param>
    /// <param name=”OutputFile”>输出文件</param>
    /// <returns></returns>
    public static bool AES_EncryptFile(string InputFile, string OutputFile)
    /// <summary>
    /// 对指定的文件解压缩
    /// </summary>
    /// <param name=”InputFile”>输入文件</param>
    /// <param name=”OutputFile”>输出文件</param>
    /// <returns></returns>
    public static bool AES_DecryptFile(string InputFile, string OutputFile)
    #endregion
    #region Base64加密解密
    /// <summary>
    /// Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。
    /// 這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 ,
    /// 這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的
    /// 系統中而不同。
    /// Base64加密
    /// </summary>
    /// <param name=”str”>Base64方式加密字符串</param>
    /// <returns></returns>
    public static string Base64Encrypt(string str)
    /// <summary>
    /// Base64解密字符串
    /// </summary>
    /// <param name=”str”>待解密的字符串</param>
    /// <returns></returns>
    public static string Base64Decrypt(string str)
    #endregion
    #region MD5加密
    /// <summary>
    /// 使用MD5加密字符串
    /// </summary>
    /// <param name=”strText”>待加密的字符串</param>
    /// <returns>MD5加密后的字符串</returns>
    public static string MD5Encrypt(string strText)
    /// <summary>
    /// 使用MD5加密的Hash表
    /// </summary>
    /// <param name=”input”>待加密字符串</param>
    /// <returns></returns>
    public static string MD5EncryptHash(String input)
    /// <summary>
    /// 使用Md5加密为16进制字符串
    /// </summary>
    /// <param name=”input”>待加密字符串</param>
    /// <returns></returns>
    public static string MD5EncryptHashHex(String input)
    /// <summary>
    /// MD5 三次加密算法.计算过程: (QQ使用)
    /// 1. 验证码转为大写
    /// 2. 将密码使用这个方法进行三次加密后,与验证码进行叠加
    /// 3. 然后将叠加后的内容再次MD5一下,得到最终验证码的值
    /// </summary>
    /// <param name=”s”></param>
    /// <returns></returns>
    public static string EncyptMD5_3_16(string s)
    #endregion
    /// <summary>
    /// SHA256函数
    /// </summary>
    /// <param name=”str”>原始字符串</param>
    /// <returns>SHA256结果(返回长度为44字节的字符串)</returns>
    public static string SHA256(string str)
    /// <summary>
    /// 加密字符串(使用MD5+Base64混合加密)
    /// </summary>
    /// <param name=”input”>待加密的字符串</param>
    /// <returns></returns>
    public static string EncryptString(string input)
    /// <summary>
    /// 解密加过密的字符串(使用MD5+Base64混合加密)
    /// </summary>
    /// <param name=”input”>待解密的字符串</param>
    /// <param name=”throwException”>解密失败是否抛异常</param>
    /// <returns></returns>
    public static string DecryptString(string input, bool throwException)

    复制代码

    2) 辅助类EncodeHelper的使用例子代码如下所示

    复制代码

    /// <summary>
    /// 对字符串加密
    /// </summary>
    /// <returns></returns>
    private string EncodePassword(string passwordText)
    {
    return EncodeHelper.MD5Encrypt(passwordText);

    }

    复制代码

    复制代码

    private void btnEncrypt_Click(object sender, EventArgs e)
    {
    string original = “测试加密字符串”;
    Console.WriteLine(“original:” + original);
    string encrypt = EncodeHelper.SHA256(original);
    Console.WriteLine(“EncodeHelper.SHA256” + encrypt);
    //DES加解密
    encrypt = EncodeHelper.DesEncrypt(original);
    Console.WriteLine(“EncodeHelper.DesEncrypt:” + encrypt);
    string decrypt = EncodeHelper.DesDecrypt(encrypt);
    Console.WriteLine(“EncodeHelper.DesDecrypt:” + decrypt);
    //MD5加密
    encrypt = EncodeHelper.MD5Encrypt(original);
    Console.WriteLine(“EncodeHelper.MD5Encrypt:” + encrypt);
    encrypt = EncodeHelper.MD5EncryptHash(original);
    Console.WriteLine(“EncodeHelper.MD5EncryptHash:” + encrypt);
    encrypt = EncodeHelper.MD5EncryptHashHex(original);
    Console.WriteLine(“EncodeHelper.MD5EncryptHashHex” + encrypt);
    encrypt = EncodeHelper.EncyptMD5_3_16(original);
    Console.WriteLine(“EncodeHelper.EncyptMD5_3_16:” + encrypt);
    //Base64加解密
    encrypt = EncodeHelper.Base64Encrypt(original);
    Console.WriteLine(“EncodeHelper.Base64Encrypt” + encrypt);
    decrypt = EncodeHelper.Base64Encrypt(encrypt);
    Console.WriteLine(“EncodeHelper.Base64Encrypt” + decrypt);
    encrypt = EncodeHelper.AES_Encrypt(original);
    Console.WriteLine(“EncodeHelper.AES_Encrypt” + encrypt);
    decrypt = EncodeHelper.AES_Decrypt(encrypt);

    Console.WriteLine(“EncodeHelper.AES_Decrypt” + decrypt);

    复制代码

    3、 MD5各种长度加密字符、验证MD5等操作辅助类 MD5Util

    实现效果

    1)本辅助类主要是用来方便实现MD5各种长度加密字符、验证MD5等操作。

    2)MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计算机广泛使用的散列算法之一(又译摘要算法、哈希算法)。

    3)MD5已经广泛使用在为文件传输提供一定的可靠性方面。例如,服务器预先提供一个MD5校验和,用户下载完文件以后,用MD5算法计算下载文件的MD5校验和,然后通过检查这两个校验和是否一致,就能判断下载的文件是否出错

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary>
    /// 获得32位的MD5加密
    /// </summary>
    public static string GetMD5_32(string input)
    /// <summary>
    /// 获得16位的MD5加密
    /// </summary>
    public static string GetMD5_16(string input)
    /// <summary>
    /// 获得8位的MD5加密
    /// </summary>
    public static string GetMD5_8(string input)
    /// <summary>
    /// 获得4位的MD5加密
    /// </summary>
    public static string GetMD5_4(string input)
    /// <summary>
    /// 添加MD5的前缀,便于检查有无篡改
    /// </summary>
    public static string AddMD5Profix(string input)
    /// <summary>
    /// 移除MD5的前缀
    /// </summary>
    public static string RemoveMD5Profix(string input)
    /// <summary>
    /// 验证MD5前缀处理的字符串有无被篡改
    /// </summary>
    public static bool ValidateValue(string input)
    #region MD5签名验证
    /// <summary>
    /// 对给定文件路径的文件加上标签
    /// </summary>
    /// <param name=”path”>要加密的文件的路径</param>
    /// <returns>标签的值</returns>
    public static bool AddMD5(string path)
    /// <summary>
    /// 对给定路径的文件进行验证,如果一致返回True,否则返回False
    /// </summary>
    /// <param name=”path”></param>
    /// <returns>是否加了标签或是否标签值与内容值一致</returns>

    public static bool CheckMD5(string path)

    复制代码

    2) 辅助类

    MD5Util 的使用例子代码如下所示

    复制代码

    //为文件增加MD5编码标签,然后验证是否被修改
    string file = @”c:\test.xls”;
    bool flag2 = MD5Util.AddMD5(file);
    Console.WriteLine(flag2);
    //对给定路径的文件进行验证,如果一致返回True,否则返回False
    bool flag3 = MD5Util.CheckMD5(file);

    Console.WriteLine(flag3);

    复制代码

    4、基于Base64的加密编码辅助类 Base64Util

    实现效果

    1)本辅助类主要是用来方便实现基于Base64的加密编码。

    2)Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。Base64编码一般在电子邮件中可以查看到,打开一封Email,查看其原始信息(您可以通过收取、导出该邮件用文本编辑器查看)。加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。

    3)采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary>
    /// 使用默认的密码表加密字符串
    /// </summary>
    /// <param name=”input”>待加密字符串</param>
    /// <returns></returns>
    public static string Encrypt(string input)
    /// <summary>
    /// 使用默认的密码表解密字符串
    /// </summary>
    /// <param name=”input”>待解密字符串</param>
    /// <returns></returns>
    public static string Decrypt(string input)
    /// <summary>
    /// 获取具有标准的Base64密码表的加密类
    /// </summary>
    /// <returns></returns>

    public static Base64Util GetStandardBase64()

    复制代码

    2) 辅助类Base64Util的使用例子代码如下所示

    复制代码

    private void btnBase64_Click(object sender, EventArgs e)
    {
    string original = “这是一个测试的Base64加密字符串”;
    string encrypt = Base64Util.Encrypt(original);
    Console.WriteLine(encrypt);//输出内容:6L*Z5pi_5LiA5Liq5rWL6K*V55qEQmFzZTY05Yqg5b*G5b2X56ym5Liy
    string decrypt = Base64Util.Decrypt(encrypt);
    Debug.Assert(original == decrypt);//验证相等

    }

    复制代码

    5、QQ密码加密操作辅助类 QQEncryptUtil

    实现效果

    1)本辅助类主要是用来方便实现QQ密码加密操作。
    2)在QQ的很多模拟网页采集数据,需要输入用户账号、密码,其中密码是需要进行加密操作的,一般使用js脚本实现,这里把它转化为C#的代码操作,其实也就是把密码和验证码通过3次MD5加密实现的。

    实现代码

    1)辅助类提供的方法接口如下所示:

    /// <summary>
    /// QQ根据密码及验证码对数据进行加密
    /// </summary>
    /// <param name=”password”>原始密码</param>
    /// <param name=”verifyCode”>验证码</param>
    /// <returns></returns>

    public static string EncodePasswordWithVerifyCode(string password, string verifyCode)

    2) 辅助类QQEncryptUtil的使用例子代码如下所示

    复制代码

    private bool CheckLogin()
    {
    HttpHelper httpHelper = new HttpHelper();
    string refUrl = “http://ui.ptlogin2.qq.com/cgi-bin/login?appid=3000801&s_url=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&f_url=loginerroralert&lang=2052&bgcolor=ffffff&style=1&low_login=1&link_target=blank&target=self&hide_title_bar=1&dummy=1”;
    string verifyCode = this.txtVerify.Text;
    string postData = string.Format(“u={0}&p={1}&verifycode={2}&aid=3000801&u1=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert”,
    this.txtUsername.Text, QQEncryptUtil.EncodePasswordWithVerifyCode(this.txtPassword.Text, verifyCode), verifyCode);
    string result = httpHelper.GetHtml(“http://ptlogin2.qq.com/login?” + postData, Portal.gc.cookieQun, refUrl);
    string errorTxt = result;
    bool isLogin = result.Contains(“登录成功!”);
    return isLogin;

    }

    复制代码

    CHM帮助文档持续更新中,统一下载地址是: http://www.iqidi.com/download/commonshelp.rar

    最新公用类库DLL+XML注释文件下载地址是:http://files.cnblogs.com/wuhuacong/WHC.OrderWater.Commons.rar

    主要研究技术:代码生成工具、Visio二次开发、客户关系管理软件、送水管理软件等共享软件开发
    专注于Winform开发框架、Web开发框架、WCF开发框架的研究及应用。
    转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com

    标签: 公用类库使用帮助

  • JavaScript MVC 框架技术选型(转)

    你很喜欢Gmail和Trello之类的单页面应用,但是不太确定该从何开始。也许你的JavaScript代码是如此的杂乱无章,以致于你很想在下一个项目上尝试下JavaScript MVC库和框架,却苦于没有头绪?我正在撰写一本单页面应用的书,所以我阅读了大量网上的相关资料。在这里我尝试提供一些看法,希望可以帮助你下决定。

    简介

    JavaScript MVC frameworks

    这里讨论的是时下最热的框架,AngularJS、Backbone、Ember和Knockout。同时提到了Batman、CANjs、Meteor和Spine,但是没有详细展开。

    我们从多个不同的角度考察每个项目,包括社区、领导、成熟度、大小、依赖、互操作性、启发、理念和特性。

    社区

    社区是一个衡量任何开源项目健康程度的重要指数。以下表格显示了GitHub上每个项目的关注者数量。

    GitHub watchers

    你当然不该仅仅根据这些数据做决定,但是它们确实为你提供了关于这些框架的一些感性认识:

    最主流:

    • Backbone.js
    • AngularJS

    正在高速成长的:

    • AngularJS
    • Meteor
    • Ember
    • Knockout

    关注总量较低但是增长迅猛的:

    • CANjs
    增长性

    特别值得注意的是AngularJS 13个月以来的惊人增长(379%)。在你做决定的时候要考虑上这一点。下面的图表比较了13个月以来GitHub关注者的增长速度,可以看出某个项目的社区成长的速度。考虑到原先的社区大小,Meteor(130%)、Ember(104%)、Knockout(76%)和Backbone(64%)的增长速度也很惊人。

    Growth

    领导

    了解项目的核心开发者的背景,他们创建框架时尝试解决的问题,有助于你欣赏他们在设计上的决策和动机。例如,David Heinemeier Hansson,流行的Ruby on Rails框架的缔造者,是37signals的签约开发者,从事项目设计,每周只有10小时能花在开发框架上。Ruby on Rails事实上是从他和37signals的签约工作中提取出来的。这一背景有助于你理解为什么这个框架需要将开发效率提升到极限——这意味这使用大量的约定(已经做出的决定)和支架程序(生成的代码)。下面,我将介绍JavaScript MVC 框架的缔造者,也许也能激起你对他们的工作的欣赏。

    Backbone

    Jeremy Ashkenas和DocumentCloud

    Jeremy Ashkenas

    Jeremy Ashkenas是CoffeeScript编程语言、Backbone.js JavaScript框架和Underscore.js JavaScript工具库的创立者。根据维基百科,他现在在NYTimes/DocumentCloud从事互动新闻方面的开发。

    图片来自The Canadian University Software Engineering Conference。

    AngularJS

    iško Hevery和Adam Abrons

    AngularJS最初由Google的Miško Hevery和Adam Abrons于2009年开发,当时是一个在线JSON存储服务的一部分。Abrons后来离开了这个项目,但是在Google工作的Hevery继续开发,和Google的员工Igor Minár、Vojta Jína一起维护这个库。

    图片来自Devoxx 2012

    Knockout

    Steve Sanderson

    Steve Sanderson是Knockout的原作者。Steve Sanderson现在为微软工作,他所在的团队开发ASP.NET、IIS和其他web项目。他以前以外包开发者或顾问身份为Bristol周边的客户开发.NET下的软件,他还为Apress写了一些书,包括《Pro ASP.NET MVC框架》。

    图片来自Steve Sanderson的博客

    Ember

    Ember核心成员中最知名的公众人物是Yehuda Katz和Tom Dale。

    Yehuda Katz是Ember.js、Ruby on Rails和jQuery的核心开发者,他白天的时间花在他创办的创业公司,Tilde Inc.。Yehuda是畅销书《jQuery in Action》和《Rails 3 in Action》的作者之一。

    Tom Dale原先在SproutCore团队工作。他以前是苹果软件工程师,在开发MobileMe和iCloud应用时精通了前端JavaScript技能。

    Yehuda Tom Dale

    图片来自Ember Team

    Meteor

    Meteor的开发团队刚刚得到了1.12千万美金,所以他们可以全职开发。他们的团队有12名开发者,每个开发者的简历都让人印象深刻。这个团队拥有雄心勃勃的计划,超越了大多数专注于组织客户端代码和状态的JavaScript MVC框架。Meteor是一个全端框架,包括服务器架构和数据库。

    成熟度

    评估框架的成熟度可以帮助你理解在项目中使用新技术的风险。未经考验的新框架在文档、扩展性、稳定性(API改变)和支持(寻找了解该框架的开发者来维护代码)方面可能存在问题,这些问题可能导致出乎意料的结果,即使从其他方面看起来决策很明智。需要考虑的项目包括:多少生产环境下的应用使用这些框架?这些应用有多少用户?文档是否良好?例子和教程是否充足?例子是否过时?API是否稳定?其他开发者了解或正打算了解这门技术么?

    • Backbone(最成熟)
      • 大量3年以上的生产环境应用,包括GroupOn、 FourSquare、USAToday、DocumentCloud。
      • 良好的文档。
      • 良好的示例代码,但是很多都过时了。
      • API非常稳定。
      • GitHub上有大量关注者。
    • AngularJS(成熟)
      • Google将其用于生产环境,但是不像其他项目一样拥有长久的历史记录。
      • 良好且持续改进的文档。
      • 大量的示例代码。
      • GitHub上有大量关注者。
    • Knockout(成熟)
      • 用于生产环境至今已有2年。
      • 良好的文档,内含类似jsfiddle的代码样例。
      • API很稳定。
      • 大量的示例代码。
      • GitHub上有大量关注者。
    • Ember.js
      • 在两年的开发之后,第一个可用于生产的发布(1.0)在2013年8月30日放出。
      • 文档正在改善。
      • API在1.0之前都不稳定(这是有意的)。
      • 大量示例代码,由于1.0前的API变动,有些已经过时。
      • GitHub上有大量关注者。
    • Meteor
      • 处于开发的早期阶段,较多地用于示例应用
      • 文档不错,然而尚不完整
      • API仍处于变动之中。
      • 一些示例代码。
      • GitHub上有大量关注者。

    大小

    了解每个框架的大小,它会在你的应用中增加多少分量是很重要的。大小会影响性能,不过它同时也会暗示你这个框架的雄心有多大,你学习它可能需要花多少时间,以及它提供多少帮助你构建应用的方式(即特性和鲁棒性)。一个框架的野心越大,特性越多,通常也就意味更难在应用的页面上将它与其他部件组合。轻量的框架更像一个库,将他集成到你的项目中所耗费的精力也相对较小。

    size

    包括Backbone和Spine在内的一些项目为自己的轻量而自豪,这些项目更多地将自己视作库,而不是框架。通常这些小型的框架留下了空间,你可以使用你自己的库来实现特定功能,例如模板和路由。我在讨论这些框架的特性的时候将继续讨论这个话题。

    包括Ember和AngularJS在内的其他项目雄心勃勃,更适合叫做框架。它们通常拥有更多内建的特性,更少依赖外部库。

    下面的列表显示了我更倾向于将哪些项目归入库或框架:

    库
    框架

    Backbone
    Ember

    Knockout
    AngularJS

    Spine
    Batman

    CanJS
    Meteor

    依赖性

    使用这些项目构建真实世界的应用的时候还需要哪些库?以下的图表展示了为了保证开发效率每个库所需的依赖,以及这些依赖的大小。

    通过从cdnjs下载库,我们收集了这些数据。在实践中,大多数的项目会使用jQuery配合这些框架处理DOM,因为需要动画和AJAX。在移动应用中,使用Zepto.js来代替jQuery处理DOM不是什么稀奇的事。Zepto.js是一个比jQuery轻量得多的库。虽然Zepto.js不支持Internet Explorer,但是移动应用通常不需要为此操心。AngularJS包含了一个jQuery 的缩减版jQLite。但是如果你在项目中使用了jQuery的话,它会被覆盖。AngularJS团队鼓励开发者,如非必要,不要添加完整的jQuery库。为了帮助你做出正确的选择,下面的表格同时显示了移动版(假定使用Zepto.js)和web版(假定使用jQuery)。

    size of javascript mvc frameworks w dependencies web app

    size of javascript mvc frameworks w dependencies mobile app

    互操作性

    这一部分讨论是否框架设计为控制整个页面或者它可以被用于现存页面的一个部分——你可能想渐渐将新技术引入现有的项目。前面的库和框架的讨论基本可以体现每个项目的互操作性,库更倾向于很容易地集成到现存的项目,而框架为你做更多的事,但是不容易和其他项目配合。

    AngularJS

    AngularJS可以和其他库很好地配合,但是它鼓励开发者们考虑是否可以不用jQuery和jQueryUI.事实上Angular内置了一个jQuery的子集jqLite。遵循这一实践的理由是让单元测试更容易,因为很多依赖库和插件设计的时候没有考虑单元测试,相应地更难和单元测试配合。在实践中,大多数的开发者最终还是因为某些特性使用了jQuery.

    Backbone

    由于Backbone的小尺寸和无预设的架构,将其包含在众多流行的客户端库和服务器端技术中很容易。

    Ember.js

    被设计为在运行时控制整个页面,所以不太适合用于页面的部分。

    Knockout.js

    可以在项目中作为小组件使用,不控制整个页面。

    启发

    记者采访音乐家时最爱问的问题是“你在成长的时候听哪些艺术家的音乐,或者说,谁启发了你?”这个问题常常使得读者能够预期音乐家的声乐。这些框架中大部分的观念都不是全新的,而是来自于创造者以前工作的项目中喜欢的部分。这一部分总结了我从框架创造者的访谈中收集到的关于启发的信息。

    AngularJS

    HTML类的声明性的语言,Adobe和Flex、微软的WPF\Silverligt等RIA技术给AngularJS的影响很深。这些声明性技术没有”主体“方法,仅仅表达需要发生什么,而不指定具体实现。视图和模型中的数据双向绑定是这一声明式编程风格在绝佳例子。此外,在Google的服务器端Java代码中大量使用的依赖注入和IOC容器(特别是Juice)也启发了AngularJS的创造者。他们重视单元测试,需要框架被设计允许依赖注入,这样测试就可以从其他应用层剥离出来,运行起来也会更快。

    Ember

    Tom Dale在Quora上谈了Ember受到的影响:

    Ember.js刚开始开发的时候,我们从Cocoa等本地应用程序框架引入一些概念,不过后来我们觉得这些概念弊大于利,或者说它们和Web应用程序格格不入。因此,我们开始从Ruby on Rails和Backbone.js 等开源项目中寻找灵感。因此,Ember.js结合了本地应用的强大和现代web的轻量。

    此外,Ember.js是SproutCore JavaScript库的进化版,SproutCore停止仿效Cocoa而更多地借鉴jQuery的时候,Ember诞生了,理解这一点很重要。

    Knockout

    hanselminutes的播客提供了Steve Sanderson受到哪些方面启发的背景信息。总结一下,MVVM设计模式和微软的WPF、Sliverlight等声明性技术是最大的启发者。你可能会发现Knockout的最佳特性——声明性的数据双向绑定——和Anjular相似,因为两者的启发者是相似的。

    理念

    报纸在报道新闻的时候努力保持中立。唯一的例外是编者案,鼓励表达观点,作者通常在问题上占据一个强烈的立场。但是大多数情况,这两者既不是严格的中立报道,也不是强烈的意见表达,而是位于两者之间的连续统。技术框架也有类似的划分,即是否强主张。例如,Ruby on Rails推崇约定优于配置,并且为开发者做了大量决定,包括文件结构和数据访问。相应地,它被认为是强主张的。其他Sinatra类的服务器端框架更轻量,并不预设文件结构和数据访问。相应的,被看成是无主张的。服务端框架有理念,客户端JavaScript MVC框架同样有,我们讨论的框架也可以被置于强主张和无主张的连续统中考察。让我们看看每个项目,然后讨论他们的理念。

    Backbone: 无主张

    Backbone是最开明的框架,极度无主张,允许开发者做出自己的决定,有时这会导致代码差异过大而难以维护。唯一的例外是Backbone假定服务器端有一个REST服务,我会在特性部分详细讨论这一点。这一假定可以通过覆盖模型的sync方法来绕过。

    AngularJS: 强主张

    AngularJS有较强的主张,特别是它强调可测试性和依赖注入。此外,HTML类的声明性编程很棒的理念也在框架中广泛体现。

    Ember: 极度强主张

    Ember力求开发者仅对应用的特有部分作决定,其余全部交给约定和支架。这个理念和Ruby on Rails和jQuery很接近。这一理念最好的表达出现在emberjs.com的网站上:

    不要浪费时间做那些无关紧要的选择。Ember.js吸纳了常见的惯用法,因此你可以专注于应用的特殊部分,而不是重新发明轮子。

    Ember标准化了文件和url结构,当然,有必要的时候也允许你覆盖这些设定。你可以预期的是大量的代码会为你生成,大量的类似文件结构的约定。相应地,你需要做出的常规选择更少,因为框架已经为你选定了合理的默认值,你可以着手构建你的应用的特殊部分。

    Knockout: 无主张

    路由和数据存储留给开发者决定。不预设文件或URL结构。甚至允许用基于字符串的模板替换声明性的基于DOM的模板。

    特性

    我们可以将这些JavaScript MVC框架看成是帮助开发者构建单页应用的常用特性集合。每个框架实现这些特性的方式,或者不实现这些特性的方式(通过其他库来补全框架的功能)是值得留心的。

    JavaScript MVC框架的主要特性是什么?
    • HTML和客户端JavaScript对象模型的双向绑定
    • 视图模板
    • 数据存储(本地存储或者通过服务器存储到数据库)
    • URL路由(确保后退按钮和搜索引擎正常工作)

    除此以外,一些框架提供常用的语言层面的服务,例如通用的pub/sub事件模型和面向对象的继承支持。

    数据绑定

    这是最受吹捧的特性。你通过HTML input修改了数据,绑定到input的JavaScript对象马上更新,其他绑定的用户接口元素也随之更新。在很多框架中,反之亦然。如果你修改了JavaScript对象,html会自动刷新。这是一个web上的双向的数据绑定,我们在Flex、Windows Forms、WPF等富客户端应用框架中见过这类绑定。以下的表格显示了哪些框架支持数据绑定。

    data binding

    有些人可能持有异议,因为Backbone和Spine部分支持数据绑定。但是我觉得大量工作需要留给开发者,保险起见,不如说这些库不支持这些特性。

    视图模板

    客户端的JavaScript数据模型需要穿插在HTML中,这些框架采用两种方式解决问题。

    基于字符串的模板(目前最流行的是handlebars.js),将字符串、文本模板中的动态部分替换为模型中的数据。字符串常被提到也饱受争议的特性之一是性能。其缺点是调试控制语句类的逻辑很困难。

    基于DOM的模板拥抱标记语言的声明式本性,这是开了挂的html,通过html中的附加属性来描述需要的绑定和事件。这些库需要的代码大大减少,为开发者做了很多事情。

    view templates

    模型(可观察的:跟踪改动)

    一些框架(Backbone、Spine)更专注于模型,要求开发者在base模型的基础上扩展JavaScript类,通过.get()和.set()访问属性,这样就能跟踪改动,模型的变动也会触发事件。KnockoutJS让开发者在原始的JavaScript对象上应用可察封装,然后通过object.propertyName()访问属性(小心,别丢了括号)。

    其他库(AngularJS)对页面上的所有绑定的DOM元素作脏检查,因为没有标准的get和set访问器。因此将这些库用于大页面时将导致性能问题。这些库不仅需要更少的刷新模板的代码,也不需要你使用特定的get和set访问器来修改模型中的数据,所以你可以使用原始的JavaScript对象。这大大提升了开发效率,这一点在框架的初学者身上体现得尤为明显。

    数据存储

    这些框架通过以下方式将数据存储到服务器

    • 与REST服务自动同步
    • 需要开发者自行实现ajax调用,调用针对返回json的web服务
    • 同时允许以上两种方式
    REST

    一些框架默认预设后端有非常整洁的REST JSON服务,并且,至少在默认的情况下,前端与后端频繁交互,在后台异步更新数据,而用户界面响应流畅。这些框架内部使用jQuery或Zepto发送合适的AJAX请求给服务器。用户界面的HTML DOM元素监听应用的JavaScript对象模型的改动,同步机制得到模型属性的更改提醒,将改动发送给REST服务,确保模型和服务器同步。

    在线和离线

    Backbone默认在客户端保存数据之前发送请求,这样服务器端和客户端同步就很容易。和Backbone非常类似的Spine框架,采用了不同的方式,在异步发送请求到服务器前,先在客户端存储记录,这提供了更好的用户界面响应,在移动应用中常发生的离线状态下也能工作。如果你的项目需要支持离线,需要了解清楚框架对该特性的支持

    DIY

    这些框架要求开发者使用$.ajax(jQuery)来调用服务,或者添加兼容的开源库处理数据存储需求。

    数据存储特性

    Meteor之类精心制作的框架拥有更完整的数据存储方案,但是要求服务器端有MongoDB数据库。这类方案试图提供一个扩展性优异的默认解决方案,提供从头到尾的JavaScript开发体验。

    以下的表格总结了每个框架是如何处理数据存储的。

    路由

    将URL路由映射到JavaScript函数,可以支持浏览器的后退按钮。单页应用最大的缺点之一是由于页面无刷新,浏览器历史不会添加条目,所以后退按钮通常无法将用户带回页面的前一状态,除非开发者在主要的状态改变时做一些额外的工作,通过在URL后附加井号,或者,使用现代浏览器的push和pop状态,实现状态跟踪机制。总之,大多数项目都提供基本、初步而有用的功能。Knockout的做法很简单,允许你使用其他的第三方开源库。

    routing

    苹果对苹果

    考察各个框架的特性之后,我发现我并不是在做一个“苹果对苹果”的比较。一个更为公平的比较也许是将AngularJS和EmberJS之类全面的框架与配合第三方库使用的Backbone和KnockoutJS之类的MV*框架进行比较。具体来说,下面的比较会更有意义:

    • AngularJS
    • EmberJS
    • Backbone 搭配 Marionette
    • KnockoutJS 搭配 DurandalJS、HistoryJS或SammayJS。

    以后的博客中我会继续深入。

    告诉我更多

    为项目选择JavaScript MVC框架时有大量需要考虑的事项,我希望本文是一个良好的开始。请在评论中分享你使用这些框架的体验,包括它们的优异之处,也包括它们使用上的陷阱。


    原文 Choosing a JavaScript MVC Framework
    翻译 SegmentFault

    from:http://segmentfault.com/a/1190000000379723

  • ASP.NET impersonation

    采用问答式, 快餐式获取要点.

    如何查看当前线程正在什么用户权限上运行?

    ====================================

    string currentUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

    如何在ASP.NET应用程序中, 使用过了IIS验证的用户的权限来执行每一次请求?

    ====================================

    在web.config文件中, 做如下修改:

    <identity impersonate="true" />

    如何在ASP.NET应用程序中指定一个用户, 然后让所有的请求都按照这个用户的权限来执行?

    ====================================

    在web.config文件中, 做如下修改:

    <identity impersonate="true" userName="accountname" password="password" />

    如何在代码中进行impersonate?

    ====================================

    System.Security.Principal.WindowsImpersonationContext impersonationContext;
    impersonationContext =
        ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
    
    //Insert your code that runs under the security context of the authenticating user here.
    
    impersonationContext.Undo();

    一个具体的例子, 可以用在aspx中, 当然了用在cs中可以的.

    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;
    
    WindowsImpersonationContext impersonationContext;
    
    [DllImport("advapi32.dll")]
    public static extern int LogonUserA(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);
    
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);
    
    public void Page_Load(Object s, EventArgs e)
    {
        if (impersonateValidUser("username", "domain", "password"))
        {
            //Insert your code that runs under the security context of a specific user here.
            undoImpersonation();
        }
        else
        {
            //Your impersonation failed. Therefore, include a fail-safe mechanism here.
        }
    }
    
    private bool impersonateValidUser(String userName, String domain, String password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;
    
        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    if (impersonationContext != null)
                    {
                        CloseHandle(token);
                        CloseHandle(tokenDuplicate);
                        return true;
                    }
                }
            }
        }
        if (token != IntPtr.Zero)
            CloseHandle(token);
        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
        return false;
    }
    
    private void undoImpersonation()
    {
        impersonationContext.Undo();
    }

    资料来源:

    How to implement impersonation in an ASP.NET application

    http://support.microsoft.com/kb/306158

     

    转自:http://www.cnblogs.com/awpatp/archive/2010/02/02/1662277.html

  • SQL Server Reporting service ToolBarItemsDisplayMode

    定制Sharepoint 2013报表工具栏

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\template\layouts\ReportServer\RSViewerPage.aspx
    
    <RSWP:ReportViewerWebPart id="m_sqlRsWebPart" runat="server" SuppressWebPartChrome="true" Height="100%" Width="100%" 
    
    ToolBarItemsDisplayMode="Back,Export,Find,PageNavigation,Print,Refresh" />
    
  • Reporting services exp

    Reporting services 开发日志

    报表数据源使用sql语句传参数的时候,在参数前面使用“:”冒号接参数名,

    例如:想要把参数p_id传入下列语句中使用时,select * from user where userid=:p_id

    报表可以包含指向其他报表的链接。单击主报表中的链接时打开的报表称为“钻取报表”,钻取报表必须与主报表在同一报表服务器上,但可位于不同的文件夹。可以向具有“操作”属性的任何项添加钻取链接,

    添加钻取操作

    1. 在“设计”视图中,右键单击要添加链接的文本框、图像或图表,然后单击“属性”。

    2. 在该报表项的“属性”对话框中,单击“操作”。

    3. 选择“转到报表”。其他部分将显示在此选项的对话框中。

    4. 在“从列表中选择报表”中,键入或选择要跳转至的报表的名称。

      ms159847.note(zh-cn,SQL.100).gif注意:

      报表名称的列表包括了当前报表服务器项目中的所有报表。如果钻取报表在报表服务器上而不在项目中,请键入报表的名称。报表名称可以包含此报表的相对路径或服务器上的报表的绝对路径。相对路径的示例为:…\DrillthroughReport\Store。绝对路径的示例为:\SalesReports\DrillthroughReport\Store。

      在配置为本机模式的报表服务器上,不必使用文件扩展名 .rdl 指定钻取报表名称。

      在配置为 SharePoint 集成模式的报表服务器上,必须在表达式中指定报表名称,并包含文件扩展名 .rdl。例如,="http://site/subsite/Documents/DrillthroughReport.rdl"。

      如果必须为钻取报表指定参数,请执行下一个步骤。

    5. 在“使用这些参数运行报表”中,单击“添加”。将向参数网格添加一个新行。

      • 在“名称”文本框中,键入钻取报表中的报表参数的名称。如果钻取报表位于报表服务器项目中,则可从下拉列表中选择参数名称。

        ms159847.note(zh-cn,SQL.100).gif注意:

        参数列表中的名称必须与目标报表中的期望参数完全匹配。如果名称不匹配,或者并未列出某个预期的参数,则钻取报表将出错。

      • 在“值”中,键入或选择要传递给钻取报表中的参数的值。

        ms159847.note(zh-cn,SQL.100).gif注意:

        值可以包含其计算结果将传递到报表参数的表达式。值列表中的表达式包括当前报表的字段列表。

    6. 若要测试该链接,请运行报表,然后单击对其设置此链接的报表项。对于文本框,更改文本的颜色和效果有助于向用户指示该文本是一个链接。例如,通过在“文本框属性”对话框中设置“字体”属性,将颜色更改为蓝色,并对文本添加下划线。

    下面文章引自:http://www.cnblogs.com/wendy-lijie/archive/2009/05/27/1490806.html

    对Table中的详细内容,以不同的颜色间隔开相邻的两行。 A:选择Table的Detail行,选择属性中的BackgroundColor,值选择表达式,输入:=iif(RowNumber(Nothing) Mod 2, “White”, “Beige”)。
    2、设置每面显示Table表头或表尾
    A:选择Table Header或Table Footer,将属性中的RepeatOnNewpage设为True.
    3、在每页都显示放入的图片或标题头等信息。
    A:只须在Table Header中加行数,把你要显示的内容放到单元格中,然后再按第二条方式设置后就可以了。
    1.     分页的控制方式
    1.1. Reporting Services自动分页
    在报表的页眉或者页尾添加文本框,调用全局变量=Globals!PageNumber
    1.2. 根据记录条数来分页
    当每条记录呈现的高度不一致,我们又希望让每页呈现的记录条数一致,那么我们可以通过记录条数来分页。在通过记录条数分页时,通常是
    根据记录条数来分组,然后在组的结束位置添加分页符。
    在表、矩阵或者列表中添加一个组,然后在分组表达式中输入=(RowNumber(“ContainerName”) – 1) \ PageSize ( PageSize 用每页所包含的
    记录条数替代,ContainerName用包含这个组的表、矩阵或者列表的名称替代)。这个表达式是用记录的行号整除分页大小,也就是记录所在的
    页码数。最后选中“在结尾处分页”,在每个组实例的结尾处放置分页符。
    1.3. 按组分页
    插入组时,在<常规>的页签中,可以选择<在起始处分页>或者<在结尾处分页>
    2.     获取参数列表的方法
    ReportingService rService = new ReportingService();//创建报表服务实例
    rService.Credentials = System.Net.CredentialCache.DefaultCredentials;//设置默认系统凭据
       string historyID = null;
       bool forRendering = true;
       ParameterValue[] values = null; 
       DataSourceCredentials[] credentials = null;
       ReportParameter[] parameters;
       parameters = rService.GetReportParameters//获取报表参数集合
        (
        “/cfhrreport/pos”,
        historyID,
        forRendering,
        values,
        credentials     
        );
       ListItem item;
       foreach(ValidValue v in parameters[0].ValidValues)//遍历参数的有效值集合
       {
        item=new ListItem(v.Label ,v.Value );
        this.DropDownList1 .Items .Add (item);//填充到一个下拉框
       }
    3.     Reporting Services API
    首先添加web引用
    http://server/reportserver/reportservice.asmx
    ReportingService rService = new ReportingService();//创建报表服务实例
    rService.Credentials = System.Net.CredentialCache.DefaultCredentials;//默认系统凭据
    CatalogItem[] catalogItems;
    catalogItems = rService.ListChildren(“/”, true);//对根路径检索
    foreach(CatalogItem item in catalogItems)
    {
        if(item.Type ==ItemTypeEnum.Folder)
    {
    //遍历报表文件夹
    }
    }
    foreach(CatalogItem item in catalogItems)
    {
    if(item.Type ==ItemTypeEnum.Report)
    {
    //遍历报表
    }
    }
    //搜索报表
    ReportService.SearchCondition[] condition=new SearchCondition[1];
    condition[0]=new SearchCondition();
    condition[0].Name =”Name”;
    condition[0].Value =this.TextBox1.Text ;
    catalogItems=rs.FindItems (“/”,WebReportSample.ReportService .BooleanOperatorEnum .And ,condition);
    //发布报表
    byte[] reportData;
    System.IO .FileStream fs=System.IO .File.OpenRead (“c:\\Report1.rdl”);
    reportData=new byte [fs.Length ];
    fs.Read (reportData,0,fs.Length );
    rs.CreateReport (“New Report”,”/”,false,reportData,null);
    //删除报表
    rs.DeleteItem (“报表名称”);
    4.     报表Url分析
    报表 URL 包含 Web 服务器的名称、报表服务器虚拟目录的名称以及报表的完全限定名称。(完全限定的名称包含报表路径,并以报表本身的
    名称结束。)
    http://server/virtualroot?%5B/pathinfo%5D&prefix:param=value%5B&prefix:param=value%5D…n]
        常用前缀及其参数名:
    4.1. rc:toolbar=true/false 显示/不显示工具栏
    4.2. rs:command=render 呈现报表
    4.3. rs:format=PDF(DOC,XLS)导出报表格式
    4.4. rc:parameters=true/false 显示/不显示工具栏的参数选择区域
    4.5. @Parameter=value 直接传递参数值
    注意:在URL参数中如果有中文,将不能被正确识别,解决的方法是用HttpUtility.UrlEncode将其转换为uft-8,再附加到参数中即可。此外还
    要注意参数是大小写敏感的。
    5. ASP.NET中展现报表
    ASP.NET提供了多种技术来呈现Web形式的报表,通常的解决方法是用Iframe。将我们前面所掌握的URL赋值给Iframe的src,结合Javascritp脚
    本,我们便可以将报表集成在页面中。此外,我们还可以充分利用ASP.NET强大的控件功能,如日历控件、图像按钮等功能提高系统的易用性。
    小技巧:有时报表中的图片可能会显示不出来,这可能是Cookies的设置问题,你也可以通过让客户下载reg文件,把Reporting Services服务
    器加入本地计算机的信任站点中。此外,报表中的image有embed和external两种方式,建议使用external方式,这样可以有效地缩小报表的尺
    寸。
    6.报表中使用自定义嵌入式代码
    Reporting Service 只接受Microsoft Visual Basic .NET 中编写嵌入式代码, 代码准备好,您就可以使用全局定义的 Code 成员在报表表达
    式中调用它。例如,如果您编写了一个名为 GetValue 的嵌入式代码函数,就可以使用下列语法从您的表达式中调用它:
    6.1.在报表<属性>中,选择<代码>页签,输入自定义代码
    Function GetValue(value As Object) As Object
    if Value is Nothing then
    return 0
    else
    return value
    end if
    End Function
        6.2.调用方法:
    =Code.GetValue(Code.GetValue(Fields!字段名.Value))

    from:http://www.cnblogs.com/xiarifeixue/archive/2009/12/28/1634311.html