# Thursday, January 31, 2008

在C#中有个较为重要,而常被一些人忽视的符号——问号(?)。在这里整理一下它在C#的几种情况:

  1. 可空类型修饰符“T?”:可空类型的基础类型可以是任何非可空值类型或任何具有struct约束的类型参数,但不能是可空类型或引用类型。例如:int?代表是可空的整形,而int??则是无效类型。即可空类型可以表示其基础类型的所有值和一个额外的空值。语法T?是System.Nullable<T>的缩写形式。可空类型具有一个HasValue的bool类型只读属性,当可空类型实例的该属性为true时,则表示该实例是非空实例,包含一个已知值Value;HasValue为false时,访问Value属性将导致System.InvalidOperationException。可空类型T?具有一个类型为T的单个参数的公共构造函数,如new int?(123)将获得一个值为123的int?类型实例。从T?到由T实现的任何接口都存在装箱转换,并且从由T实现的任何接口都存在到T?的拆箱转换。但是任何情况下可空类型都不满足接口约束,即使基础类型实现了该特定接口
  2. 条件运算符“x ? y : z” : “x ? y : z”的意思大部分程序员应该都熟悉,稍微啰嗦一下:) 如果表达式x为true,则计算y;如果x为false,则计算z。省却if{}else{}的简单形式了。
  3. 空合并运算符“??”:该运算符是在泛型出现后,C#词法语法中新增加的标记,同时出现的还有一个“::”(命名空间别名限定符)。形式为“a??b”的空合并表达式要求a为可空类型或引用类型。如果a为非空则表达式“a??b”返回的结果为a;否则返回b。空合并运算符为结合运算符,即操作时从右向左进行组合的。如,“a??b??c”的形式按“a??(bb??cc)”计算。

曾有人说过“细节决定胜负”,我们程序员应该更好的把握编程语言的细节才能更好的保证软件质量。

特此整理存档:D

posted on Thursday, January 31, 2008 4:31:34 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Friday, October 19, 2007

youku0.3     近日党的十七大召开,而我没有电视看,就喜欢到优酷网上看看别人上传的相关视频,部分视频希望能在机器上有所保留,但优酷自己并不提供文件的下载功能。找了个维棠FLV视频下载软件,却发现它无法完整下载较长的优酷视频,我稍作了原因分析后,发现是优酷的一些较长的视频是采用多文件连播的方式,也就是一个视频由多个文件共同组成,于是乎自己花了一大袋烟的工夫用c#写了这个小工具,直接将视频所在的网页地址复制到该软件的指定位置,然后点击“Go!”按钮就开始下载了,哈哈……
    鉴于支持和促进和谐社会发展,俺也把这个自写小工具共享出来给朋友们使用。由于时间仓促,有一些不完善的地方敬请原谅,抽空俺也会继续更新这个小工具的:D

声明:本软件仅因个人爱好而开发,跟优酷网无任何关系:)

名     称:优荡
当前版本:0.5
环     境:Windows ,Microsoft .NET Framework 2.0
作     者:衣明志(网名:qihangnet)
最近更新:
             2007年10月19日(0.5.0.0版):
                          代码进行进一步优化
                          加快了视频分析速度
                          显示视频文件总大小
                          显示当前已下载文件文件大小
                          显示下载总进度的进度条
                          添加了单视频的多文件自动合并功能(一些视频优酷使用多文件存储的,本软件下载后将同一视频的多文件进行的无缝合并,并随后删除原始文件)
                          修复了多项小Bug
             2007年10月17日(0.3.0.1版):
                          修复了2个界面上的小bug
下载地址:http://www.qihangnet.com/content/binary/YouDown.exe

posted on Friday, October 19, 2007 1:52:30 AM (China Standard Time, UTC+08:00)  #    Comments [3]
# Wednesday, June 13, 2007

asp.net 2.0中引入的Membership机制给我们做web开发带来很多便利,使得我们在做很多项目开发时处理用户和角色及权限问题时减少了相当的工作量。不过我们开发中可能会碰到一个小小的问题如下:

我们知道MembershipUser中有如下重载的方法

  • MembershipUser.ResetPassword () :将用户密码重置为一个自动生成的新密码。
  • MembershipUser.ResetPassword (String passwordAnswer) :将用户密码重置为一个自动生成的新密码。

msdn中有如下描述:

ResetPassword 调用 ProviderName 属性所引用的成员资格提供程序的 MembershipProvider.ResetPassword 方法,以将成员资格用户的密码重置为自动生成的新密码。然后将该新密码返回到调用方。

如果 EnablePasswordReset 为 false,则成员资格提供程序将返回一个异常。

如果 RequiresQuestionAndAnswer 为 true,则必须使用以密码提示问题答案作为参数的 ResetPassword 重载方法,并提供成员资格用户的密码。如果需要密码答案并提供了不正确的密码答案,成员资格提供程序将引发 MembershipPasswordException。

而另外一个方法MembershipUser.ChangePassword(String oldPassword, String newPassword) 又必须提供原始密码,那么这里就产生了一个矛盾:我们希望用户能够通过安全问题和答案来作为找回密码,又希望管理员可以重置某用户的密码怎么办?上述方法均无法直接使用,要么使用MembershipUser.ResetPassword ()而无安全问题和答案验证,要么必须知道问题答案或者原始密码,我们知道这些安全相关的东西我们都是加密的,而且往往采用单向编码的方式,也是说我们不可能轻易的通过读取数据库数据知道用户的答案和旧密码!那么好,如何解决这个问题呢?下面我来提供一个小的解决方案:

Membership的数据库中包含有一个设置用户密码的存储过程:

CREATE PROCEDURE aspnet_Membership_SetPassword
(

 @ApplicationName nvarchar(256),

 @UserName nvarchar(256),

 @NewPassword nvarchar(128),

 @PasswordSalt nvarchar(128),

 @CurrentTimeUtc datetime,

 @PasswordFormat int = 0
)

返回值:成功返回 0;
用户不存在,返回 1;

那么ok,我们开始解决我们的需求吧!思路很简单我们先设置用户一个默认的密码,然后以该密码为旧密码使用MembershipUser.ChangePassword(String oldPassword, String newPassword) 修改用户的密码。下面的代码是在以DataAccess.RunProcedure方法是已经实现的执行存储过程的方法为前提编写的:

public class MembershipSafe
 {
     public static string ResetPassword(string username)
     {
         //将用户密码修改为8位且包含一个特殊符号的随机密码
         return ResetPassword(username, Membership.GeneratePassword(8,1));
    }
  
     public static string ResetPassword(string username, string newpassword)
     {
         //先将用户密码修改为123123
  
         SqlParameter[] _sp = {
                              new SqlParameter("@ApplicationName",Membership.ApplicationName)
                             ,new SqlParameter("@UserName",username)
                             ,new SqlParameter("@NewPassword","1M4h3eZLAKW1WbVTTwYJiJZa33w=")
                             ,new SqlParameter("@PasswordSalt","rcVy3pCccZ9tXW7NHp1Maw==")
                             ,new SqlParameter("@CurrentTimeUtc",DateTime.Now)
                             ,new SqlParameter("@PasswordFormat",1)
         };
         bool op = DataAccess.RunProcedure("aspnet_Membership_SetPassword", _sp) == 0;
         //以123123为原始密码,修改为新密码
         Membership.GetUser(username).ChangePassword("123123", newpassword);
         return newpassword;
     }
 }

注:以上代码仅做参考,不一定是符合您具体项目的需求,比如有人可能会继续问修改了密码怎么告诉用户啊,答案是发邮件或者电话通知啊,哈哈~~

推荐浏览:

posted on Wednesday, June 13, 2007 2:41:02 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Saturday, May 05, 2007

    最近不少Web技术圈内的朋友在讨论协议方面的事情,有的说web开发者应该熟悉web相关的协议,有的则说不用很了解。个人认为这要分层次来看待这个问题,对于一个新手或者刚入门的web开发人员而言,研究协议方面的东西可能会使得web开发失去趣味性、抹煞学习积极性,这类人应该更多的了解基本的Web技术使用。而对于在该行业工作多年的老鸟来说,协议相关的内容、标准相关内容应该尽量多些的了解,因为只有这样才能使得经手的web系统更加优秀(安全、漂亮、快速、兼容性好、体验好……)。本文我们来说一下MIME 协议的一个扩展Content-disposition。

    我们在开发web系统时有时会有以下需求:

  • 希望某类或者某已知MIME 类型的文件(比如:*.gif;*.txt;*.htm)能够在访问时弹出“文件下载”对话框
  • 希望以原始文件名(上传时的文件名,例如:山东省政府1024号文件.doc)提供下载,但服务器上保存的地址却是其他文件名(如:12519810948091234_asdf.doc)
  • 希望某文件直接在浏览器上显示而不是弹出文件下载对话框
  • ……………………

    要解决上述需求就可以使用Content-disposition来解决。第一个需求的解决办法是

Response.AddHeader "content-disposition","attachment; filename=fname.ext"
 
将上述需求进行归我给出如下例子代码:
public static void ToDownload(string serverfilpath,string filename)
{
    FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
    long fileSize = fileStream.Length;
    HttpContext.Current.Response.ContentType = "application/octet-stream";
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + UTF_FileName(filename) + "\";");
    ////attachment --- 作为附件下载
    ////inline --- 在线打开
    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
    byte[] fileBuffer = new byte[fileSize];
    fileStream.Read(fileBuffer, 0, (int)fileSize);
    HttpContext.Current.Response.BinaryWrite(fileBuffer);
    fileStream.Close();
    HttpContext.Current.Response.End();
}

public static void ToOpen(string serverfilpath, string filename)
{
    FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
    long fileSize = fileStream.Length;
    HttpContext.Current.Response.ContentType = "application/octet-stream";
    HttpContext.Current.Response.AddHeader("Content-Disposition", "inline; filename=\"" + UTF_FileName(filename) + "\";");
    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
    byte[] fileBuffer = new byte[fileSize];
    fileStream.Read(fileBuffer, 0, (int)fileSize);
    HttpContext.Current.Response.BinaryWrite(fileBuffer);
    fileStream.Close();
    HttpContext.Current.Response.End();
}

private static string UTF_FileName(string filename)
{
    return HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8);
}

 

简单的对上述代码做一下解析,ToDownload方法为将一个服务器上的文件(serverfilpath为服务器上的物理地址),以某文件名(filename)在浏览器上弹出“文件下载”对话框,而ToOpen是将服务器上的某文件以某文件名在浏览器中显示/打开的。注意其中我使用了UTF_FileName方法,该方法很简单,主要为了解决包含非英文/数字名称的问题,比如说文件名为“衣明志.doc”,使用该方法客户端就不会出现乱码了。

 需要注意以下几个问题:

  1. Content-disposition是MIME协议的扩展,由于多方面的安全性考虑没有被标准化,所以可能某些浏览器不支持,比如说IE4.01
  2. 我们可以使用程序来使用它,也可以在web服务器(比如IIS)上使用它,只需要在http header上做相应的设置即可

可参看以下几篇文档:

posted on Saturday, May 05, 2007 3:03:14 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Tuesday, January 02, 2007

 将VS2003下的一个Web项目升级到VS2005后,去除明显错误后编译测试运行。某页面发现一个问题:

“/”应用程序中的服务器错误。

分析器错误

说明: 在分析向此请求提供服务所需资源时出错。请检查下列特定分析错误详细信息并适当地修改源文件。

分析器错误信息: 发现不明确的匹配。

这个问题发生原因一般情况是:

aspx页面里面的控件有与您的aspx.cs里的类变量重名(不区分大小写)的ID

那么我发现在代码中有如下的声明:

protected System.Web.UI.WebControls.Label BlogID;
protected System.Web.UI.WebControls.Label blogID;

blogID在前台控件中不存在,仅在cs代码中声明了,因此产生了上述的问题。

 

由此看来虽然,C#等语言中允许我们使用大小写不同来声明不同的变量,但是我们应该尽量避免这样的情况,使用完全不同的名字区分不同的变量为好啊。

posted on Tuesday, January 02, 2007 10:50:23 PM (China Standard Time, UTC+08:00)  #    Comments [2]
# Sunday, August 27, 2006

String.Split 方法:标识此实例中的子字符串(它们由数组中指定的一个或多个字符进行分隔),然后将这些子字符串放入一个 String 数组中。

Regex.Split 方法:在由正则表达式匹配项定义的位置将输入字符串拆分为一个子字符串数组。

上面的两个Split方法,在使用单字符拆分字符串的时候效果一样。然而在使用多个字符拆分字符串时,就有所区别了:

Srting.Split(字符串.ToCharArray())得到的结果往往不是我们希望的结果。所以在此推荐使用Regex.Split方法处理使用多字符拆分字符串。

posted on Sunday, August 27, 2006 11:45:34 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Friday, November 11, 2005

VS2005目前还没有官方正式的简体中文版本,这个安装包是我从SQL2005CTP版的安装包里抽取出来的,中文化已经非常高了,特别是在vs2005的起始页的社区文档也成了调用msdn中文网站的了。很不错。

点击下载(约55M)

下载完以后请将文件的扩展名.zip修改为.iso,然后运行其中的vs_setup.msi文件。

注意:安装过程没有进度窗口,安装完毕会显示一个安装完成的提示窗口。

posted on Friday, November 11, 2005 12:59:32 PM (China Standard Time, UTC+08:00)  #    Comments [7]
# Friday, October 28, 2005

孙展波的博客上看到了一个则令人激动的消息:

2005年10月27日上午微软RTM了Visual Studio 2005和.NET Framework 2.0。

MSDN订户将可以在今天晚些时候下载Visual Studio 2005的各个版本。非MSDN订户可以在Microsoft Download Center下载.NET Framework及其SDK。在11月7日之后,非MSDN订户还可以下载Visual Basic, Visual C#, Visual C++, Visual Web Developer, Visual J#, 和SQL Server的Express版本。

我激动不已,于是下载VS2005旧版卸载软件将Beta2的卸载了,可惜卸载完毕才想起来还没有搞到RTM版的安装程序呢:(

只好等开心下个月给俱乐部带来VSTSBeta3再说吧,~~如果是MVP多好啊:)

posted on Friday, October 28, 2005 11:02:41 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Thursday, August 25, 2005
在实际开发Asp.Net项目时,程序可能会出现一些异常,那么我们应该怎么去获得尽量多的系统异常,以便后期维护过程能够尽可能重现异常,及时分析、发现和修复Bug。为了处理这个问题,我写了一个小程序来帮助实现我的需求。
posted on Thursday, August 25, 2005 2:40:44 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Thursday, July 28, 2005

    在博客园管理员dudu以及博客堂开心就好宝玉的支持和帮助下,烟台.NET 俱乐部也成立啦.
    希望烟台、威海及其周边地区.NET爱好者能积极的加入.
    希望加入此团队的博客园成员可以在本文的评论中回复或EmailTo : qihangnet(AT)hotmail.com。
    请说明你的Blog帐号和所在城市,特长/兴趣(最好详细点)。

    继北京,上海,广州,杭州,郑州,济南等城市成立后。我们烟台也要努力了。
    Let's Do Our Best!

烟台.Net俱乐部博客园团队Blog:http://www.cnblogs.com/team/dotsail.html
烟台.NET俱乐部官方网站:http://qihang.net
烟台.NET俱乐部QQ群:6718824
烟台.NET俱乐部博客园聊天室:http://chat.cnblogs.com/CuteSoft_Client/CuteChat/CH_MainForm.Aspx?ChannelId=45f4536b-39fc-44d5-af07-1715e7b2097e

posted on Thursday, July 28, 2005 9:31:12 PM (China Standard Time, UTC+08:00)  #    Comments [1]
# Thursday, May 19, 2005
去年开发一个小型的网络系统时,编写了一个对指定目录的本地文件(实际上别人机器上共享文件也可以)进行遍历和I/O监控的控件,近来有人问及相关问题,就把他贴出来吧,很简单的程序,高手勿进哦 :)代码见详细内容
posted on Thursday, May 19, 2005 10:06:47 PM (China Standard Time, UTC+08:00)  #    Comments [2]
# Tuesday, April 05, 2005
Cω是微软研究院对下一代语言的探索。它扩展了C#的功能,更好的支持数据访问(SQL和XML)和并发控制。 Cω的希望能方便的开发出更加可靠且维护性更好的软件,其中一个重要的概念就是"尽早的发现错误"。 在下面的一个数据库查询的例子中将很好的体现出这一点。
posted on Tuesday, April 05, 2005 11:24:39 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Saturday, March 26, 2005
Snippet Compiler、Regulator、CodeSmith、NUnit、FxCop、.NET Reflector、NDoc、NAnt、两个转换工具
posted on Saturday, March 26, 2005 11:30:40 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Wednesday, March 23, 2005
一个程序详细研究DataReader,同时显示Command用法; 功能:演示DataReader的各项操作; 说明:如果需要文字说明请查看我的BLOG里面关于ado.net的文章; 作者:雪冬寒; BOLG:http://blog.csdn.net/bineon
posted on Wednesday, March 23, 2005 5:08:34 PM (China Standard Time, UTC+08:00)  #    Comments [0]
在系统开发时我们经常需要对数据进行加密,本文用C#描述了.net中的加密技术,以下就是是使用了不同的加密方法加密/解密字符串:DES HMACSHA1 SHA1 RC2 MD5 等,待续 ……
posted on Wednesday, March 23, 2005 4:50:09 PM (China Standard Time, UTC+08:00)  #    Comments [0]
DotNet专业词汇英中对照表,从微软MSDN的文档中转载过来的。希望能对各位DOTNET技术人员有用:)
posted on Wednesday, March 23, 2005 4:47:37 PM (China Standard Time, UTC+08:00)  #    Comments [3]
本文集合了很多精彩的C#入门代码集,包含了常用的C#功能例程。希望对DotNet技术新手或爱好者有所帮助和启示。
posted on Wednesday, March 23, 2005 4:44:26 PM (China Standard Time, UTC+08:00)  #    Comments [1]
刚学C#写的一个小程序,来列举本地的进程,两种模式:
1.列举出进程的starttime和title。
2.列举出进程的执行文件完全路径。
编译环境:Windows 2003+Microsoft.NET Framework v1.1.4322
附上源码:

程序代码:

//List all processes on local system(two modes) 

//Kill the specified process 

//By sfzhi at 24/Sep/2004 

using System; 
using System.Diagnostics; 
using System.Management; 
public class PK 

    public static void Main(string[] args) 
    { 
       if(args.Length != 1) 
       { 
        help(); 
       } 
       else 
       { 
        switch(args[0]) 
        { 
         case "/t"
          psst(); 
         break
         case "/p"
          psph(); 
         break
         default
          kill(args[0]); 
         break
        } 
       } 
    } 
    //Show the Usage 

    private static void help() 
    { 
     Console.WriteLine("Local System Process Lister and Killer V1.0 (2004-9-25 C#) "); 
     Console.WriteLine("Code by sfzhi msn:idazhi@hotmail.com"); 
     Console.WriteLine(); 
     Console.WriteLine("Usage:    pk    "); 
     Console.WriteLine("Options:  /t         - Show the starttime and title of all processes"); 
     Console.WriteLine("          /p         - Show the path to executable file of all processes"); 
     Console.WriteLine("          PID/Name   - Kill the specified process"); 
    } 
    //Show the starttime and title of all processes 

    private static void psst() 
    { 
        Process[] procList = Process.GetProcesses(); 
        Console.WriteLine("{0,-6}{1,-12}{2,-22}{3}","PID","Process","StartTime","Title"); 
        for (int i=0;i<procList.Length-1;i++)         
        {         
            string strProcName = procList[i].ProcessName; 
            int iProcID = procList[i].Id; 
            DateTime dProcStTime = procList[i].StartTime; 
            string strProcTitle = procList[i].MainWindowTitle; 
            Console.WriteLine("{0,-6}{1,-12}{2,-22}{3}",iProcID,strProcName,dProcStTime,strProcTitle); 
        } 
    } 
    //Show the path to executable file of all processes 

    private static void psph() 
    { 
        Process[] p = Process.GetProcesses(); 
         ManagementObjectSearcher searcher; 
        ManagementObjectCollection collection;     
        searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process"); 
        collection = searcher.Get(); 
        Console.WriteLine("{0,-5}{1,-16}{2}","PID","ProcName","ProcessPath"); 
        foreach (ManagementObject service in collection) 
        { 
         Console.WriteLine("{0,-5}{1,-16}{2}",service["ProcessID"],service["Name"],service["ExecutablePath"]); 
        } 
     } 
     //Terminate the specified process 

     private static void kill(string idname) 
       { 
           Process[] all = Process.GetProcesses(); 
           foreach(Process p in all) 
           { 
             if(p.Id.ToString() == idname || p.ProcessName == idname) 
             { 
                  p.Kill(); 
                  p.Close(); 
                  Console.WriteLine("Process {0} was terminated successfully",idname); 
              } 
           } 
       } 
posted on Wednesday, March 23, 2005 4:30:53 PM (China Standard Time, UTC+08:00)  #    Comments [0]