[Flex]Flex扩展HTTPService简化调用接口定义

mikel阅读(757)

    Flex提供MXML来描述一个HTTPService,看上可以简化开发人员的工作,但实际上这种描述HTTPService的方式很容易产生重复代码导致代码不好维护和扩展。数据交互接口唯一定义对系统的维护非常有利,但基于AS定义HTTPService也是一件烦琐的事情;那如何做才能够达到方便地定义接口呢。

接口定义

以下是定义一个登陆的HTTPService

    public class ILogin extends HttpBase

    {

       public function ILogin(method:String="get", result:Function=null)

       {

           super("userlogin",  method, result);

       }

       public var UserName:String;

       public var UserPWD:String;

       public var ImgSN:String;

       public var ImgKey:String;

      

    }

看上非常简单,只需要继承HttpBase然后效需要提交的参数定义成Public成员即可以。对于构造函数参数下介绍HttpBase的时候讲述;对于这个接口又是怎样调用的呢。

var send:ILogin =new ILogin(           "get",function(data:XML,error:Boolean){

                     if(!error)

                     {

                        

                     }

                  });

                  send.UserName= txtName.text;

                  send.UserPWD=txtPWD.text;

                  send.ImgKey= ic.ImageKey();

                  send.ImgSN=ic.ImageSN();

                  send.Open();

如果并不想考虑太多处理,只关心登陆处理可以这样定义

var send:ILogin =new ILogin()

send.UserName= txtName.text;

send.UserPWD=txtPWD.text;

send.ImgKey= ic.ImageKey();

send.ImgSN=ic.ImageSN();

send.Open();

服务端代码

对于服务端代码就可以根据自己需来处理,jsp,asp,ASP.NET,php都是一样只要接收http请求即可。为了便于理解把服务端代码顺便贴出来:

    [NClay.Web.Service.ActionMapper]

    public class UserLogin : ActionBase

    {

        protected override void OnGet()

        {

            ImageValidate.Check();

            User user= _UserService.Login(UserName, UserPWD);

            if(user ==null)

                throw new Exception("用户名或密码不正确!");

            if (user != null && !user.Enabled)

                throw new Exception("用户已经被系统禁用,请与管理员联系!");

            mLoginer = user;

            mIsLogin = mLoginer != null;

            FormsAuthentication.SetAuthCookie(Loginer.UserName, true);

            LoginID = Loginer.UserID;

            LoginName = Loginer.UserName;

            base.OnGet();

        }

        public string UserName

        {

            get;

            set;

        }

        public string UserPWD

        {

            get;

            set;

        }

        [NClay.Web.Service.OutputXml]

        public int LoginID

        {

            get;

            set;

        }

        [NClay.Web.Service.OutputXml]

        public string LoginName

        {

            get;

            set;

        }

        public NClay.Web.Actions.ImageValidate ImageValidate

        {

            get;

            set;

        }

    }

HttpBase的定义

       HttpBase是针对本人现有需求所制定的,所以并不一定适合你的需要;但作为一个参考

public  class HttpBase

    {

       private var mService:HTTPService=null

       private var mResult:Function=null;

       private var mFristSearch:Boolean=false;

       public var _TimeSlice:Date;

       public function GetService():HTTPService

       {

           return mService;

       }

       public function HttpBase(api:String,method:String="get",result:Function=null)

       {

           mService = new HTTPService();

          

           mService.useProxy=false;

           mService.url=GetServiceUrl()+api;

           mService.resultFormat="e4x";

           mService.method=method;

           mService.addEventListener(FaultEvent.FAULT,HFSoftCoreFun.onFault);

           mService.addEventListener(ResultEvent.RESULT,OnResult);

          

           mResult=result;

       }

       protected virtual function GetServiceUrl():String

       {

           return "service.aspx?do=";

       }

       private function OnResult(event:ResultEvent)

       {

           var data:XML=XML(event.result);

          

           var iserror:Boolean=HFSoftFx.HFSoftCoreFun.IsError(data);

           if(mResult!=null)

              mResult(data,iserror);

                 

       }

       public function get FirstSearch():Boolean

       {

           return mFristSearch;

       }

      

       public function Open(firstSearch:Boolean=false)

       {

           _TimeSlice =new Date();

           mFristSearch=firstSearch;

           mService.send(this);

       }

   

 

    }

代码也非常简单,就是在httpservice的基础上包装一下。其实了解AS的朋友应该可以看得出对于动态语言来说直接把HttpBase定义成动态类,然后直接设置成员提交这样就省下每个交互都定义一个类型出来这么麻烦。但作为一个服务接口调用成员越明确越好,因为程序是要经常修改和维护的;不过是不是要这样做就是团队约束规范问题了。

[MTV]藤-北京记忆主题曲

mikel阅读(858)

北京记忆》主题曲《藤》MV

京电视台纪录片《北京记忆》主题曲
《藤》
词曲:小柯
演唱:小柯 老狼 沙宝亮 满文军 满江 黄征 汪峰 常宽
监制:徐鲤

哎哦哎哎…… 小柯
A1 当我们转过脸看太阳缓缓升 老狼
鸽子依然落在屋脊
沙宝亮
却不是从前的那只 满文军

A2 当我们抬起头已过而立年纪 满江 满文军
看枝桠漫天的那颗
满江
曾经是嫩嫩的绿 黄征小柯

B1 那么多的枝枝蔓蔓 汪峰 沙宝亮
遮挡住的是那些往昔
汪峰
接着另一个往昔
老狼
那么长得缠绕
满江小柯
缠绕住的是那些回忆
满江
接着另一个回忆 满文军

C1 继续卖力的生长吧 常宽 黄征 沙宝亮
离参天还很远呢
   常宽黄征沙宝亮
继续飞快的发芽吧
老狼
要遮天蔽日还要许久呢   汪峰小柯

C2 继续卖力的生长吧    沙宝亮满江 满文军
这刚刚才开始呢 沙宝亮 满江 满文军
继续飞快的发芽吧
小柯
用枝桠缠绕往昔的回忆慢慢书 满江 沙宝亮

A3 当我们转过脸看太阳缓缓升 黄征 沙宝亮
鸽子依然落在屋脊 小柯
却不是从前的那只 满文军

A4 当我们抬起头已过而立年纪 沙宝亮满文军
看枝桠漫天的那颗 沙宝亮
曾经是嫩嫩的绿 满江 小柯

B2 那么多的枝枝蔓蔓 常宽 满文军
遮挡住的是那些往昔 常宽
接着另一个往昔
满文军

那么长得缠绕 汪峰小柯
缠绕住的是那些回忆
汪峰
接着另一个回忆 老狼

C3 继续卖力的生长吧 同C1
离参天还很远呢
继续飞快的发芽吧
要遮天蔽日还要许久呢

C4 继续卖力的生长吧 同C2
这刚刚才开始呢
继续飞快的发芽吧
用枝桠缠绕往昔的回忆慢慢书

C5 继续卖力的生长吧 合
离参天还很远呢
继续飞快的发芽吧
要遮天蔽日还要许久呢

C6 继续卖力的生长吧
这刚刚才开始呢
继续飞快的发芽吧
用枝桠缠绕往昔的回忆慢慢书

[Flex]AIR应用:FedEx Desktop

mikel阅读(937)

FedEx是全球知名的快递公司,他们使用Adobe AIR技术提供了一个用于跟踪,查看其快递包裹的桌面应用程序,你可以从这里下载:

http://www.fedex.com/desktop/
此应用程序免费,仅需免费注册成为FedEx用户即可。
那 么如果以后你的公司有国外的快递业务使用FedEx(不管你从全球哪个国家哪个购物网站使用了FedEx的快递业务,比如Amazon),你都可以使用唯 一的FedEx tracking number,来通过此工具随时查看包裹的递送状态,比如到了哪个国家,哪个机场,是否准时和延迟,状态原因描述等。

[C#]利用ajax技术显示上传进度

mikel阅读(992)

我们介绍了如何从HTTP请求流中将数据部分进行截取,同时将数据相关信息进行保存。
      本篇概述:
      用过ajax的朋友应该有听过XmlHttpRequest对象,ajax其实就是通过XmlHttpRequest对象来向服务器发出异步请求,并从服务器获得数据,然后用JavaScript来操作DOM而更新页面。
      本篇就是要通过XmlHttpRequest对象来实现实时的进度显示。
      效果图:

      正文部分:
      看过有些前辈的做法是通过设置HTTP请求的Refresh头 字段来定时刷新页面从而显示进度,但是这样就会带动整个页面一起刷新,就算我们把进度条做成单独的页面,效果仍旧不是太好。我之前试过用ajax的 Timer组件,但是不知道是何原因,Timer控件在IIS下预览时总是无法正常发挥作用。苦恼了好一阵子,怀疑是MS的BUG。最后发现了一个很好的 替代办法就是利用XmlHttpRequest对象来自己实现定时刷新,这样每次只需向服务器请求很少的数据,减少了对服务器的压力,在后期的测试中,发 现这个办法确实很好用,而且在IIS下也一切正常(上图就是IIS下运行的效果)。
      当然如果光有进度条没有数据,那这个进度条也只能是个摆设,所以我把接下来的内容分成两块:进度信息的保存、进度的显示
      
      1、进度信息的保存
      首先我们要明白进度条在这里反应的是什么的进度?毫无疑问是文件上传的进度喽~~在上一篇中, 我们对上传的文件数据进行了提取,也就是说这个提取的进度就是我们要显示给客户端的进度。那就简单了,我们只要把已经提取的文件大小与总的文件大小比对一 下,就可以知道完成的百分比了。可是问题来了,我们如何知道上传了多少了呢?答案肯定是要用一个变量来保存已经上传的数据量。那这个变量要放在哪里才能让 我们既可以在进度页面中访问,又可以在HTTP上传模块中访问呢?
      大家肯定知道一般情况下,用户在多个页面之间访问,会用到Session对象或URL传值来进行页面之前的通信。但是前一篇所介绍的HTTP模块并不属于一个页面,因此我们无法简单的应用Session让进度页面与上传模块实现通信。这里主要还是借鉴高山来客的 思路:首先构建一个用于存放文件信息的类,该类主要用来保存文件信息,如:文件名,路径,当前上传的数据量,上传时间等。然后设置一个针对某次上传的唯一 ID做为页面中通信的暗号,拥有这个暗号的页面才能获取对应于某次上传的文件信息。现在已经有了两个变量了,接着就要使这两个变量可以被多个页面所使用, 方法就是在上传页面中,将这个ID变量注册为该页面的一个隐藏域,这样包含这个页面的HTTP请求流中就会包含那个上传ID。另一个类变量就保存在页面缓 存Cache中,并用上传ID做为其编号。
      现在假设已经有了这么一个用于存放文件信息的类UploadFileInfo。
      首先我们要在上传页面的PageLoad中new一个ID,然后注册一个隐藏域用来保存此ID,同时实例化UploadFileInfo类,并将相应的信息写入该类,最后把该类放入Catch:
      

if (!IsPostBack)
{
    UploadFileInfo ufi 
= new UploadFileInfo();
    ufi.strFileGuid 
= Guid.NewGuid().ToString;//用GUID来表示唯一的ID;
    ufi.strTempDir 
= Server.MapPath("TempUpload/" + ufi.strFileGuid + "//");
    ClientScript.RegisterHiddenField(
"UploadID", ufi.strFileGuid);//隐藏域,名字为UploadID,值为ufi.strFileGuid
    HttpContext.Current.Cache.Add(ufi.strFileGuid, ufi, null, DateTime.Now.AddDays(10), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);//加入到Catch中
}

      经过以上步骤,我们就可以在HTTP模块中访问了。
      因为在这次的HTTP请求流中包含了一个隐藏域,所以我们可以对获取的HTTP请求流进行分析,从而获取相应的上传ID,也就是我们之前说的暗号。然后通 过Cache的编号找到Cache中的文件信息对象,从而我们可以在后来的数据读取过程中对该对象的上传数据量进行修改。由于是放在Cache中,加之是 一个引用对象,所以对该对象修改后,其它代码访问到的都是最新的值。

string sguid = GetUploadId(bPreloadedEnitityBody, eContentEncode);//GetUploadId是自己写的一个方法用来从请求流中获取上传ID
UploadFileInfo ufiFileInfo = (UploadFileInfo)HttpContext.Current.Cache[sguid];//取出文件信息对象

      其它页面如果要使用这个对象就得先获取ID,之后就可以自由操作了。
      2、进度的显示
      从图中我们可以看到,当显示进度的时候,背后的页面成灰色,并且无法响应任何事件,有点类似模态窗口。这个效果大家可以在网上查查,还是挺容易实现的。我这里有一段js显示此效果的代码(搜集于网上):

ModalDialogfunction ModalDialog(name,divid,width,height,leftop,topop,color)
   
{
       
this.name=name;//名称
       this.div=divid;//要放入窗体中的元素名称
       this.width=width;//窗体宽
       this.height=height;//窗体高
       this.leftop=leftop;//左侧位置
       this.topop=topop;//上部位置
       this.color=color;//整体颜色
       this.show=function()//显示窗体
       {
           document.all(obj.name
+"_divshow").style.width=obj.width;
           document.all(obj.name
+"_divshow").style.height=obj.height;
           document.all(obj.name
+"_divshow").style.left=obj.leftop;
           document.all(obj.name
+"_divshow").style.top=obj.topop;
           document.all(obj.name
+"_mask").style.width=document.body.clientWidth;
           document.all(obj.name
+"_mask").style.height=document.body.clientHeight;
           document.all(obj.name
+"_divshow").style.visibility="visible";
           document.all(obj.name
+"_mask").style.visibility="visible";
       }

       
       
this.close=function()//关闭窗体
       {  
           document.all(obj.name
+"_divshow").style.width=0;
           document.all(obj.name
+"_divshow").style.height=0;
           document.all(obj.name
+"_divshow").style.left=0;
           document.all(obj.name
+"_divshow").style.top=0;
           document.all(obj.name
+"_mask").style.width=0;
           document.all(obj.name
+"_mask").style.height=0;
           document.all(obj.name
+"_divshow").style.visibility="hidden";
           document.all(obj.name
+"_mask").style.visibility="hidden";         
       }

       
       
this.toString=function()
       
{
           
var tmp="<div id='"+this.name+"_divshow' style='position:absolute; left:0; top:0;z-index:10; visibility:hidden;width:0;height:0'>";
           tmp
+="<table cellpadding=0 cellspacing=0 border=0 width=100% height=100% >";
           tmp
+="<tr>";
           tmp
+="<td id='"+this.name+"_content' valign=top ></td>";
           tmp
+="</tr>"
           tmp
+="</table>";
           tmp
+="</div>";
           tmp
+="<div  id='"+this.name+"_mask' style='position:absolute; top:0; left:0; width:0; height:0; background:#666; filter:ALPHA(opacity=50); z-index:9; visibility:hidden'></div>";
       
           document.write(tmp);
           document.all(
this.name+"_content").insertBefore(document.all(this.div));
       }

        
var obj=this;
   }

      接着讲我们的重点:如何实现定时局部刷新。
      关于XmlHttpRequest对象,我这里就不详细讲述了,提供大家一个关于此的手册下载。为了大家更容易理解,我举个小例子:
  

小例子页面A.aspx
function returnresponse(url)
{
     
var xmlHttp = new ActiveXObject('MSXML2.xmlHttp'); 
     
if(xmlHttp!=null)
     
{
          xmlHttp.open(
"GET",url,true);//向URL指定的页面发送GET请求
          xmlHttp.onreadystatechange=function()
          
{//当xmlHttp的readyState改变的时候就会引发这个事件
               if(xmlHttp.readyState==4&& xmlHttp.status == 200)
               
//4 = "成功发送",200 = "所请求的页面返回正常"
                    temp=xmlHttp.responseText;//接收所请求页面发回的数据
                    alert(temp);
               }

          }

          xmlHttp.send(
null);  
      }

      
else
      
{
          alert(
"浏览器不支持XmlHttp.");
      }

}


//URL所指向的页面B的代码.cs,当然也可以是同一个页面的cs
if(Request.QueryString["event"]=="test")
{
     Response.Write(
"测试");
}


/*
然后我们在A页中执行returnresponse(B.aspx?event="test");
很快就会发现在A页中弹出一个窗口,内容是"测试"。
*/

   

      通过以上小例子,大家应该已经对该对象有所了解了吧。为实现定时刷新,我把进度条单独放在一个页面中(如A.aspx),通过js的setTimeout 来定时执行类似returnresponse这样的方法,然后在A.aspx.cs代码中获取文件信息对象,接着通过Response来反馈进度信息。这 样在A.aspx页面中就可以获取到信息,并进行显示了。但是执行ActiveXObject将要花费不少代价,而且我们是定时执行该方法,显然会造成性 能下降。在参考了构建一个pool来管理无刷新页面的xmlhttp对象后,决定采用这一方法,事实证明该方法确实有效。

利用pool后的代码function xmlHttpPoolFactory()
    
{
        
this.XmlHttpPool = new Array();
        
this.MaxPoolLength = 10;
        
this.Add=function()
        
{
            
if ( this.XmlHttpPool.length < this.MaxPoolLength ) 
            
{
                xmlHttp
=null;
                
if (window.XMLHttpRequest)
                
{// code for all new browsers
                    xmlHttp=new XMLHttpRequest();
                }

                
else if (window.ActiveXObject)
                
{// code for IE5 and IE6
                    try 
                    

                        xmlHttp 
= new ActiveXObject('MSXML2.xmlHttp'); 
                    }
 
                    
catch(e) 
                    

                        
try 
                        

                            xmlHttp 
= new ActiveXObject('Microsoft.xmlHttp'); 
                        }
 
                        
catch(e2) 
                        
{
                        }
 
                    }
 

                }

                
if ( xmlHttp!=null ) 
                

                    
this.XmlHttpPool.push(xmlHttp); 
                }
 
                
return xmlHttp; 
            }

        }
;
        
this.GetXmlHttp = function()
        
{
            
var xmlHttp = null
            
var pool = this.XmlHttpPool; 
            
for ( var i=0 ; i < pool.length ; ++i ) 
            

                
if ( pool[i].readyState == 4 || pool[i].readyState == 0 ) 
                

                    xmlHttp 
= pool[i]; 
                    
break
                }
 
            }
 
            
if ( xmlHttp == null ) 
            

                
return this.Add(); 
            }
 
            
return xmlHttp; 

        }
;
        
this.returnresponse= function(url,div)
        
{
            
var xmlHttp = this.GetXmlHttp();
            
var param = div.split(',');
            
if(xmlHttp!=null)
            
{
                xmlHttp.open(
"GET",url,true);
                xmlHttp.onreadystatechange
=function()
                
{
                    
if(xmlHttp.readyState==4&& xmlHttp.status == 200)
                    
//4 = "loaded",200 = "OK"

                        temp
=xmlHttp.responseText;
                        
var temparray = temp.split(",");
                        document.getElementById(param[
0]).innerText=temparray[0];
                        document.getElementById(param[
1]).innerText=temparray[1]+"KB/S";
                        document.getElementById(param[
2]).innerHTML="<table width='"+temparray[2]*3+"'><tr><td></td></tr></table>";
                        document.getElementById(param[
3]).innerText=temparray[2]+"%";
                    }

                }

                xmlHttp.send(
null);  
            }

            
else
            
{
                alert(
"Your browser does not support xmlHttp.");
            }

        }
;
        
this.AportAll = function()
        
{
            
for ( var i=0 ; i < this.XmlHttpPool.length ; ++i )  
            
{  
                
this.XmlHttpPool[i].abort();  
            }
  
        }
;   
     }

    
var a = new xmlHttpPoolFactory();//建立一个全局的工厂实例
    var strevent = "";
    
function refresh(url,interval,div)
    
{//该方法我用来定时刷新,因为除了SetTimeout还有一些其它活要干
        var str1 = "";   
        
for(i=2;i<arguments.length;i++)
        
{//因为可能需要刷新的div不只一个,所以利用js的arguments来解决动态参数的问题
            if(i!=arguments.length1)
            
{
                str1 
= str1 +arguments[i]+",";
            }

            
else
            
{
                str1 
= str1 +arguments[i];
            }

        }

        a.returnresponse(url,str1);  
//调用该方法实现异部通信

        
var str="";
        
for(i=0;i<arguments.length;i++)
        
{
            
if(i!=arguments.length1)
                str 
= str + "'"+arguments[i]+"',";
            
else
                str 
= str+"'"+arguments[i]+"'";
        }

        setTimeout(
"refresh("+str+")", interval );//定时执行该方法
        

    }

       到这就差不多整个专题都结束了,接下来几天,我会把代码稍微调整下,然后传上来。
       由于这段时间要上班,实在抽不出时间来整理,如果大家需要可以先拿去看看。不过代码写的有点乱,而且有些功能也没有完善,时间实在太少,大家见谅。
       粗糙的工程

[CMS]N2CMS开源CMS框架使用指南

mikel阅读(1222)

Installation

This section covers installation of the examples. The requirements for the examples are Visual Studio 2005 and SQL Express 2005.

Step 1: Download from CodePlex

Released files

The best place to start is in the download section on codeplex. Along the source code there are a number of examples that should speed you right along using N2. This guide will focus on the Templates Examples. This the code of a skeleton project along with compiled versions of the templates and edit interface code. Here's a quick overview of the other released files.

Step 2. Unzip

Unzipped files

 

Now that you've downloaded the Templates Examples unzip and venture into the downloaded goodies. The package includes an Sql Server 2005 Express database (mdb file) with a few pages.

If you don't want to use SQL express you can install the required tables in another database by configuring the connection string in web.config and following the installation guide located in the /edit/install directory.

Step 3: Open in Visual Studio 2008

Visual studio

As you can see there isn't much in this project. However. There's more, but it's all compiled and not included in the project. If you're new to N2 I can reccoment not digging into the source code just yet. Just play along fow now.

Step 4: Compile and Run (Ctrl+F5)

Hit the universal compile and run command in visual studio Ctrl+F5 to see how this site looks like right now. Visual Studio has a little web server that will serve us just fine right now.

Run

 

Beautiful…

Step 5: Log in and play around

Why not log in and play around a bit. The username and password should be admin/changeme. 

Log in

Edit

Step 6: Look at some code

Back in visual studio you can see two files included in the project. This is the definition of a content item we can use when we edit. For an item to be available for editing you need create a class and decorate it with the [Definition] attribute.

content definition

To be able to view it you also need to point out a template from within the definition. This is a template, it has a designer file:

a template

The template uses a master page and a theme which is set at runtime. To change edit the start page.

This is the code-behind file:

a template

Step 7: Verify the example code

Switch back to the browser and create a new item (right click on the startpage and choo new). Notice that there's a choice "My First Page"? That's defined by the code in the example project you just looked at.

a template

When we click on it we start start editing the page. The fields that are there by default are inherited from AbstractContentPage (if you didn't notice before go back to Visual Studion and "MyPagePage.cs" and take a look) .

Some results

[CMS]NetCMS开源CMS项目

mikel阅读(1149)

安装环境

SQL Server 版基本安装环境
操作系统: Windows Server 2003(推荐)、Windows 2000、Windows XP
数据库 :SQL Server 2000(推荐)、Sql Server 2005
Web服务器: IIS 5.0及以上版本(推荐IIS6.0)
其它:.NET Framework 2.0

下载NetCMS 1.7.0.1125

更新列表
NetCMS 1.7.0 build1125 正式版(最后更新 2008年11月25日) 
NetCMS 1.7.0 build1125 源码版(最后更新 2008年11月25日) 
NetCMS 1.7.0 build1125 正式版(中国站长站分流)(最后更新 2008年11 月25日) 
NetCMS 1.7.0 build1125 源码版(中国站长站分流)(最后更新 2008年11 月25日) 

下载NetSNS1.5.1 1209

NetSNS V1.5.1 build1209正式版(最后更新 2008年12月09日) 
NetSNS V1.5.1 build1209源码版(最后更新 2008年12月09日) 
NetSNS V1.5.1 build1209正式版(中国站长站分流)(最后更新 2008年12月09日) 
NetSNS V1.5.1 build1209源码版(中国站长站分流)(最后更新 2008年12月09日) 
NETSNS功能使用说明(最后更新 2008年7月15日)
由于大头贴文件过大,单独提供下载,请解压后放到inc/cam文件夹下(最后更新 2008年12月08日) 
请在SQL数据库查询分析器中执行database/sql/1.sql(表结构),database/sql/2.sql(初始值),SQL脚本也可以在这里单独下载(最后更新 2008年12月09日) 
管理员帐号:admin,密码:admin888

下载用户手册

点击下载 (最后更新 2008年4月21日)

下载数据库设计文档

点击下载(最后更新 2008年4月11日)

下载标签说明

点击下载 (最后更新 2008年05月09日)

下载模板风格

查看(最后更新 2008年05月09日)

[C#]利用Windows系统服务自动更新网站

mikel阅读(1123)

利用Windows系统服务自动更新网站

 

       Tag: windows服务   自动更新 自动发布 网站自动更新

应用背景:作为一个站长,为了管理好网站,也为了讨好搜索引擎,每天都需要在不同的时段更新网站的内容,有的站长需要维护几个网站,每天的工作量可想而知,如果逢年过节,站长没有在电脑旁边或者无法上网,这个维护工作也就无法进行。

       使用原理:本文介绍了一种方法来自动更新网站内容,采用一个Windows系统服务,设置好它的URL访问地址,每天在特定时间内访问需要更新内容的网站 的特殊页面(假定这个页面为A);在网站端,设置一个审核机制,只有通过审核的内容才能显示在网站前端,新加的信息默认是不审核,页面A的作用就是从未审 核信息中挑出几条进行审核,这样就更新了网站内容,对于静态首页的,页面A还可以生成下首页静态页面。当然页面A还可以做更多的用途,如备份数据库、更改 到期用户状态、删除无用的临时文件等。

       详细原理:

1)        Windows服务端:

              Windows服务采用.Net Framework2.0框架,所以使用时应该先安装好.Net Framework2.0,下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=0856EACB-4362-4B0D-8EDD-AAB15C5E04F5&displaylang=zh-cn

       采用一个xml文件存储配置信息,里面存储需要访问的网址,示例结构如下:

<?xml version="1.0" encoding="utf-8" ?>

<root>

  <Urls>

    <item url="http://www.shouji138.com/" time="3:59"/>

    <item url="http://www.baidu.com/" time="11:59"/>

    <item url="http://www.baidu.com/" time="13:59"/>

    <item url="http://www.baidu.com/" time="15:59"/>

    <item url="http://www.baidu.com/" time="16:59"/>

  </Urls>

</root>

一个item代表一次访问,url是具体的网址,设置为网站自动更新的url地址,可以带查询字符串来设置更新的数量,time表示每天访问的时间,time只能精确到1分钟,而且必须保证每个item在同一分钟内只有一个url任务。

       程序采用一个定时器,每隔20秒扫描一下配置项中是否有需要访问的网址,如果有则访问一次这个网址。相关代码如下:

public Job()

        {

            System.Timers.Timer myTimer = new System.Timers.Timer(20000);

            myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);

            myTimer.Enabled = true;

            myTimer.AutoReset = true;

            XmlDocument xml = new XmlDocument();

            xml.Load(AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["xmlfile"]);

            xmllist = xml.SelectNodes("//root/Urls/item");

 

        }

 

        void myTimer_Elapsed(object source, ElapsedEventArgs e)

        {

            try

            {

                Log.SaveNote(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Heart Work!(心跳检测)");

                YourTask();

            }

            catch (Exception ee)

            {

                Log.SaveException(ee);

            }

        }

        void YourTask()

        {

            count++;

            if (count > 10000)

                count = 0;

            for (int i = 0; i < xmllist.Count; i++)

            {

                string url = xmllist[i].Attributes["url"].Value;

                string time = xmllist[i].Attributes["time"].Value;

                //Log.SaveNote(url + "-" + time);

 

                DateTime workTime = DateTime.Parse(DateTime.Now.ToShortDateString() + " " + time);

 

                //lastwork

                if (DateUtil.DateDiff(DateUtil.DateInterval.Minute, workTime, DateTime.Now) == 0)

                {

                    //到了执行时间

                    if (DateUtil.DateDiff(DateUtil.DateInterval.Minute, workTime, lastworktime) != 0)

                    {

                                          //访问网址,如 手机主题 http://www.shouji138.com/

                        visit(url);

                        lastworktime = DateTime.Now;

                    }

                }

            }

        }

 

 

        void visit(string url)

        {

            HttpWebRequest myHttpWebRequest = null;

            HttpWebResponse myHttpWebResponse = null;

            Stream receiveStream = null;

            try

            {

                myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);

                myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

                receiveStream = myHttpWebResponse.GetResponseStream();//得到回写的字节流

                Log.SaveNote("访问:" + url);

            }

            catch (Exception ex)

            {

                Log.SaveNote("访问失败:" + url);

                Log.SaveException(ex);

            }

            finally

            {

                if (receiveStream != null)

                    receiveStream.Close();

                if (myHttpWebResponse != null)

                    myHttpWebResponse.Close();

            }

        }

2)        网站端:

网站端应该采用审核机制,比如一个表News表,设置字段isaccept为审核字段,1表示已审核,0表示未审核,新增的内容默认为未审核0。我 们在平时的时候多添加一些内容到未审核库中,然后交给程序来自动更新。更新程序可以采用任何动态网页技术,asp、php、jsp都可以,该程序的作用就 是把未审核的内容更改为审核状态,为了灵活起见,可以设置一个表示更新数量的查询字符串变量给程序,如num,则更新3条的网址就变成http://www.shouji138.com/A.asp?num=3这 种形式,这个网址可以在Windows服务的配置文件中设置好。本文的重点是讲采用Windows服务来进行网站更新,所以具体网站端的代码我就没有写出 来了,各位站长可以根据自己网站的情况来编写。Windows服务是与网站端没有业务逻辑关联的,windows服务只管定期的来访问网站端的更新网址, 而网站端的更新网址只管更新的业务逻辑。

 

最后,提供下工具和源代码的下载地址:

Windows服务工具下载:http://www.shouji138.com/aspnet2/files/autopub.rar

Windows服务源码下载: http://www.shouji138.com/aspnet2/files/autopubsource.rar

[C#]如何在ASP.NET中使用验证通过的Windows Live ID用户登录网站

mikel阅读(964)

前言

现在有很多在线服务的验证,我曾经就写过一篇 如何在ASP.NET中创建OpenID, 这里我再介绍如何使用Windows Live ID在ASP.NET应用程序中验证用户的身份,说穿了这也是一种特殊验证模型,也就是说当在您的网站中使用Windows Live ID登录时,此用户首先会重定向到Windows Live登录页,然后通过验证的用户Windows Live将该用户再重定向到您的网站,并提供一个用户ID。

sshot-3

 

使用Windows Live ID

要开始使用的Windows Live ID ,首先你需要申请一个应用程序ID。转到:https://msm.live.com/app/default.aspx 注册应用程序ID,其实微软针对此应用还有一个指南—>http://msdn.microsoft.com/en-us/library/cc287659.aspx

sshot-1

sshot-2

上面这个注册表格要填的我都填了,其中要注意的是 返回的URL,这个页面主要是处理与 Windows Live ID的沟通,如我现在VS的启动页是:
http://localhost:15650/WebAuth/Sample/webauth-handler.aspx

 

下载并安装Windows Live ID Web身份验证的SDK

呵呵,老样子,微软已经为ASP.NET开发者已经提供了非常容易实现的示例模板。这里下载:http://www.microsoft.com/downloads/details.aspx?FamilyId=E565FC92-D5F6-4F5F-8713-4DD1C90DE19F&displaylang=en, 准确点可以看该文:http://livesino.net/archives/302.live。默认安装路径在:C:\Program Files\Windows Live ID\WebAuth。

 

整合到您的网站

首 先用Visual Studio2008或者2005创建一个Asp.Net网站,然后将安装的示例模板中的App_Code文件夹中的 WindowsLiveLogin.cs(C:\Program Files\Windows Live ID\WebAuth\Sample\App_Code\WindowsLiveLogin.cs)添加到我们的App_Code文件夹中。这里我直接用 微软的示例,不自己新建网站了。

然后在web.config文件中配置刚申请一个应用程序ID 000000004400D659,

sshot-4

Default.aspx页面中的HTML的代码如下:

<body>
<table width="320">
<tr>
<td>
<h1>
欢迎来到Windows Live ID&trade;网络身份验证SDK中的C#模板</h1>
<p>
下面的链接表明您是否登录。如果该链接的文本是 <b>Sign in</b>, 表明您尚未登录。如果它显示 <b>Sign out</b>,表明您已经登录。</p>
<iframe id="WebAuthControl" name="WebAuthControl"
src="http://login.live.com/controls/WebAuth.htm?appid=<%=AppId%>&style=font-size%3A+10pt%3B+font-family%3A+verdana%3B+background%3A+white%3B"
width="80px" height="20px" marginwidth="0" marginheight="0" align="middle" frameborder="0"
scrolling="no"></iframe>
<p>
<% if ( UserId == null ) { %>
你还没有登录到网站,请点击 <b>Sign in</b> 链接.
<% }
else { %>
您已经登录到网站,您的用户编号ID = "<b><%=UserId%></b>".
<% } %>
</p>
</td>
</tr>
</table>
</body>
</html>

Default.aspx文件的代码隐藏文件代码如下:

using System;
using System.Web;
using System.IO;
using WindowsLive;
/// <summary>
/// This is the default aspx.cs page for the sample Web Auth site.
/// It gets the application ID and user ID for display on the main
/// page.  
/// </summary>
public partial class DefaultPage : System.Web.UI.Page
{
const string LoginCookie = "webauthtoken";
// Initialize the WindowsLiveLogin module.
static WindowsLiveLogin wll = new WindowsLiveLogin(true);
protected static string AppId = wll.AppId;
protected string UserId;
protected void Page_Load(object sender, EventArgs e)
{
/* If the user token has been cached in a site cookie, attempt
           to process it and extract the user ID. */
HttpRequest req = HttpContext.Current.Request;
HttpCookie loginCookie = req.Cookies[LoginCookie];
if(loginCookie != null){
string token = loginCookie.Value;
if (!string.IsNullOrEmpty(token))
{
WindowsLiveLogin.User user = wll.ProcessToken(token);
if (user != null)
{
UserId = user.Id;
}
}
}
}
}

Default.aspx 将作为网站的一个登录页。 用户点击登录按钮,将被重定向到的Windows Live 登录页面。 当他微软进行身份验证后,微软会重新回到我们的处理程序页上,所以,我们现在将创建一个新的aspx页,并将其命名webauth- handler.aspx。 还记得,当我们在注册申请Windows Live 时提供的返回URL的网页吗。

webauth- handler.aspx页面将作为处理Windows Live重定向回到您的网站用户的网页。 而且微软Windows Live将提供一个验证特定值给您使用。 我们可以简单地删除所有的标记,下面是webauth-handler.aspx代码隐藏类的代码:

   1: using System;
   2: using System.Web;
   3: using System.IO;
   4: using WindowsLive;
   5:  
   6: /// <summary>
   7: /// This page handles the login, logout and clearcookie Web Auth
   8: /// actions.  When you create a Windows Live application, you must
   9: /// specify the URL of this handler page.
  10: /// </summary>
  11: public partial class HandlerPage : System.Web.UI.Page
  12: {
  13:     const string LoginPage = "default.aspx";
  14:     const string LogoutPage = LoginPage;
  15:     const string LoginCookie = "webauthtoken";
  16:     static DateTime ExpireCookie = DateTime.Now.AddYears(-10);
  17:     static DateTime PersistCookie = DateTime.Now.AddYears(10);
  18:  
  19:     // Initialize the WindowsLiveLogin module.
  20:     static WindowsLiveLogin wll = new WindowsLiveLogin(true);
  21:  
  22:     protected void Page_Load(object sender, EventArgs e)
  23:     {
  24:         HttpRequest req = HttpContext.Current.Request;
  25:         HttpResponse res = HttpContext.Current.Response;
  26:  
  27:         // Extract the 'action' parameter from the request, if any.
  28:         string action = req["action"];
  29:  
  30:         /*
  31:           If action is 'logout', clear the login cookie and redirect
  32:           to the logout page.
  33: 
  34:           If action is 'clearcookie', clear the login cookie and
  35:           return a GIF as response to signify success.
  36: 
  37:           By default, try to process a login. If login was
  38:           successful, cache the user token in a cookie and redirect
  39:           to the site's main page.  If login failed, clear the cookie
  40:           and redirect to the main page.
  41:         */
  42:  
  43:         if (action == "logout")
  44:         {
  45:             HttpCookie loginCookie = new HttpCookie(LoginCookie);
  46:             loginCookie.Expires = ExpireCookie;
  47:             res.Cookies.Add(loginCookie);
  48:             res.Redirect(LogoutPage);
  49:             res.End();
  50:         } 
  51:         else if (action == "clearcookie")
  52:         {
  53:             HttpCookie loginCookie = new HttpCookie(LoginCookie);
  54:             loginCookie.Expires = ExpireCookie;
  55:             res.Cookies.Add(loginCookie);
  56:  
  57:             string type;
  58:             byte[] content;
  59:             wll.GetClearCookieResponse(out type, out content);
  60:             res.ContentType = type;
  61:             res.OutputStream.Write(content, 0, content.Length);
  62:  
  63:             res.End();
  64:         } 
  65:         else 
  66:         {
  67:             WindowsLiveLogin.User user = wll.ProcessLogin(req.Form);
  68:  
  69:             HttpCookie loginCookie = new HttpCookie(LoginCookie);
  70:             if (user != null)
  71:             {
  72:                 loginCookie.Value = user.Token;
  73:  
  74:                 if (user.UsePersistentCookie)
  75:                 {
  76:                     loginCookie.Expires = PersistCookie;
  77:                 }
  78:             } 
  79:             else 
  80:             {
  81:                 loginCookie.Expires = ExpireCookie;
  82:             }   
  83:  
  84:             res.Cookies.Add(loginCookie);
  85:             res.Redirect(LoginPage);
  86:             res.End();
  87:         }
  88:     }
  89: }

 

第一次登录测试

当以上操作都完成后,现在应该可以使用Windows Live ID登录了,我们首页浏览登录页面Default.Aspx:

sshot-6

点Sign In链接后,将重定向到Windows Live的登录页面:

sshot-7

当Windows Live ID验证通过,Widnows Live将返回到我们的登录页面,下面这个页面现在将显示欢迎您的信息和您的用户ID :

sshot-5

完毕!

[C#]如何在ASP.NET中创建OpenID

mikel阅读(1125)

前言( 引用 Lee's 程序人生- 博客园-OpenID使用手册JAVA版

 

了解一下openID

openID在中国还不怎么普及,而且支持openID登录的站点也比较少

,不过还是先补充点openID的信息吧

啥是openID呢,所谓openID就是用一个URL作为登录帐号和密码的验证

再详细一点就是,不用注册,也不用输入密码,只要你拥有一个openID就可以登录网站

可能这样说有点难以理解,接下来我们稍微深一点的去理解

假设你现在已经从一个可以申请openID的网站上申请了一个openID,链接是”rjys.163.com”

{openID是一个URL链接,不是一个以前的字母或者字母+数字哦}

什么是OpenID?
OpenID是一种开放、离散式的用于用户数字标识的开源框架。
请让我们思考自己所拥有的在线帐号种类:博客、wiki、to-do list、 个人相册。在网络应用日益充斥的今天,这些个人在线帐号可谓不胜枚举,而对帐号的需要也同样无处不在,乃至当我们想在好友博客上进行评论时都需要注册成为 该博客系统的用户。于是作为终端用户,我们不得不在每个网站上设置帐号,并管理众多的帐号。而采用OpenID技术的话,你就无须再管理这些相互独立的帐 号,而是通过认证服务器管理自己唯一的身份标识。
OpenID常见的应用场景:某用户试图登录一个外部网站。与提交用户名和密码的方式不同,他只提交了属于自己的一个URL,例如:http://johnsmith.example.com/
这 个URL即指向了用户的OpenID认证服务器,同时又是用户的身份标识。因此外部网站使用此URL便可以找到用户的认证服务器,并询问认证服务器:“该 用户声称他拥有此URL。而这个URL说明了你负责认证工作,那么请告诉我,该用户能否访问我的站点?”。认证服务器将提示用户登入认证系统,并询问用户 是否允许和外部网站进行认证。如果用户同意的话,那么认证服务器将通知外部网站——用户已经通过认证。在上面,我们通过拟人化的表达方式来形象生动地诠释 整个认证请求/回应过程。
用户可以使用同一个URL用作在任何支持OpenID认证的外部网站中使用的标识。这正是OpenID与其它传统认 证方式的最大不同。通过使用URL,可以使外部站点非常容易地获取到负责认证工作的服务器位置。而只有认证服务器才需要输入密码来验证用户身份。其它希望 验证用户身份的站点都将询问用户所注册的认证服务器。如果你正在使用支持OpenID的门户站点(比如AOL),那么你就可以使用现成的AOL即时消息登 录帐号来登录AOL站点,而无需另外注册。因此,我们可以猜想Google和Yahoo也许已经开始着手建造他们的OpenID服务。
你一定想知道OpenID是如何实现分散化服务的?由于用户具有选择OpenID服务提供者的权利,因此你会在最初选择AOL作为OpenID提供者,而过一段时间后,可能觉得希望更换到另外一个OpenID提供者,此时你所需要做的就是修改以下的HTML标签:

<link rel="openid.server" href="http://openid.example.com/">

保存这些link元数据的最常见位置就是个人站点(比如博客)的根页面。
如何使用OpenID?
OpenID 绝妙地解决了多个帐号同步问题,但并不仅仅如此。例如,你可以利用它建立跨应用、跨域的单点登录(Single sign-on)。如果你使用同一个OpenID登入了博客和个人相册,那么你只需要在登录过程中进行一次认证。对于在此之后的每个需要登录的应用(在同 一个session周期)只需提供OpenID,而不是传统的用户名和密码。
大多数OpenID提供者也提供了支持多个配置的功能。这样你就可以使用“Bob Smith”登录博客,而使用“Robert J Smith”登录企业wiki。随着OpenID提供者的日益成熟和OpenID功能上的提升,我们不久就会使用对来自伙伴公司OpenID认证服务器主 机名的用户进行认证的服务。
哪些网站支持OpenID?
OpenID技术出现不久,便获得了在众多公共消费站点的热捧:DiggSix ApartZoomrAOL。 其中AOL为老用户提供了OpenID支持,使得六千五百万的登录用户在一日之内就全部能够使用OpenID。目前已经具有超过九千五百万的用户能够使用 OpenID登录系统,并且每天都有25至50个站点加入到支持OpenID规范的队伍中。另外,OpenID增加了对Firefox3和微软 Windows Vista的支持。
下面是实现了OpenID代码库的语言列表:
        • C#
        • C++
        • Java
        • Perl
        • Python
        • Ruby
        • PHP
        • Coldfusion
OpenID社区维护了这些代码库的清单:http://openid.net/wiki/index.php/Libraries

 

ASP.NET中实现OpenID登录

  注册一个OPENID帐号,这里使用http://www.myopenid.com
  1.从谷歌CODE上下载强大的C# OpenID库DotNetOpenId,并把它应用到你的项目中。
 

  2.在OpenID登录时添加了一些不错的可用性功能,这是可选的,下图为格式化了的OpenID框,请转到:ID Selector

  3.转到Scott Hanselman's的示例帖子。你将很好的了解如何新增的OpenID到ASP.NET的网站。
  4.创建登录表单,这里用用户控件。

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OpenIdLoginForm.ascx.cs"
Inherits="OpenIDSampleApp.Web.UserControls.OpenIdLoginForm" %>
OpenID:
<asp:TextBox ID="openid_identifier" runat="server" />
<asp:Button ID="loginButton" runat="server" Text="登录" OnClick="loginButton_Click" />
<!-- BEGIN ID SelectOR -->
<script type="text/javascript">
<!--
idselector_input_id = "<%= openid_identifier.ClientID %>";
-->
</script>
<script type="text/javascript" id="Script1" 
    src="https://www.idselector.com/selector/acd9fbc926f4707be4d6a05b400fe40de1f31449"
charset="utf-8"></script>
<!-- END ID SelectOR -->
<br />
<asp:CheckBox ID="chkRememberMe" runat="server" Text="记住我." />
<asp:CustomValidator
runat="server"
ID="openidValidator"
ErrorMessage="OpenID格式无效"
ControlToValidate="openid_identifier"
EnableViewState="false"
OnServerValidate="openidValidator_ServerValidate" />
<asp:Label ID="loginFailedLabel" runat="server" EnableViewState="False" Text="登录失败"
Visible="False" />
<asp:Label ID="loginCanceledLabel" runat="server" EnableViewState="False" Text="登录取消"
Visible="False" />
  5.登录按钮下的代码,Scott Hanselman's提供,基本上告诉的OpenID库需要用户的电子邮件和昵称。

        protected void loginButton_Click ( object sender, EventArgs e ) {
if ( !openidValidator.IsValid )
return; // 如果自定义验证失败,将不会登录。
OpenIdRelyingParty openid = new OpenIdRelyingParty ();
try {
IAuthenticationRequest request = openid.CreateRequest ( openid_identifier.Text );
// 请将您的访客给供应商进行验证。
ClaimsRequest fetch = new ClaimsRequest ();
fetch.Nickname = DemandLevel.Require;
fetch.Email = DemandLevel.Require;
request.AddExtension ( fetch );
//SaveCookies (); //在网站上保存身份票
request.RedirectToProvider ();
}
catch ( OpenIdException ex ) {
// 可能不是一个有效的OpenID。
openidValidator.Text = ex.Message;
openidValidator.IsValid = false;
}
}
  6.处理OpenID库的答复,当然你也可以让用户选择是否用OPENID创建一个帐户,或者直接看看是否用户已经存在与网站上的ASP.NET成员数据库。
如果不存在可以为OPEN用户创建一个成员帐户使用OpenID作为他们的用户名。

  protected void Page_Load ( object sender, EventArgs e ) {
openid_identifier.Focus ();
OpenIdRelyingParty openid = new OpenIdRelyingParty ();
if ( openid.Response != null ) {
switch ( openid.Response.Status ) {
case AuthenticationStatus.Authenticated:
// 下面2个变量只是为了作为后面的添加网站用户表字段的值,
// 也就是创建Membership[web.config]时才用到
string email = "";
string alias = "";
ClaimsResponse fetch = openid.Response.GetExtension ( 
                              typeof ( ClaimsResponse ) ) as ClaimsResponse;
if ( fetch != null ) {
alias = fetch.Nickname;
email = fetch.Email;
}
if ( string.IsNullOrEmpty ( alias ) )
alias = openid.Response.ClaimedIdentifier;
if ( string.IsNullOrEmpty ( email ) )
email = openid.Response.ClaimedIdentifier;
//#region Membership[web.config]
// 是否在网站上添加OPEN用户 
//if (Membership.GetUser(openid.Response.ClaimedIdentifier) == null)
//{
//    MembershipCreateStatus membershipCreateStatus;
//    MembershipUser user = Membership.CreateUser(
//        openid.Response.ClaimedIdentifier, 
//        "123456", 
//        email, 
//        "这是一个的OpenID帐户。昵称是什么?", 
//        alias, 
//        true, 
//        out membershipCreateStatus );
//    if (membershipCreateStatus != MembershipCreateStatus.Success) {
//        loginFailedLabel.Text += ": 帐户添加不成功的: " +
//                                 membershipCreateStatus.ToString();
//        loginFailedLabel.Visible = true;
//        break;
//    }
//    user.Comment = alias;
//    Membership.UpdateUser(user);
//}
// 使用FormsAuthentication告诉ASP.NET,用户现在已经登录成功, 
// 并使用OpenID标识作为用户名 
//#endregion
FormsAuthentication.RedirectFromLoginPage (
openid.Response.ClaimedIdentifier, chkRememberMe.Checked );
break;
case AuthenticationStatus.Canceled:
loginCanceledLabel.Visible = true;
break;
case AuthenticationStatus.Failed:
loginFailedLabel.Visible = true;
break;
}
}
}
  7.测试.

补充:Scott Hanselman's Blog

          http://www.codeplex.com/dasblog

          示例代码下载