php, appserv 更换php版本的方法(从php6改成php5)

mikel阅读(1459)

需修改2个地方:

1、修改php版本,将路径与module改为 php5_module  。如果只修改后面的路径,而不修改module名,则服务启动不起来,报找不到相应的模块名。

LoadModule php5_module d:/AppServ\php5\php5apache2_2.dll

上面修改正确后,在浏览器中输入地址,会发现只能出现php的脚本源码!!!显然没有解析php文件。

2、指定模块的解释器。由mod_php6.c   改为  mod_php5.c

<IfModule mod_php5.c>
AddType application/x-httpd-php .php

这样就可以正常解析了。

还一点也很重要:就是php.ini配置文件路径(PHPIniDir “D:/PHP5″),一定要配置,否则apache总是找:windows目录下的php.ini。一般我们都去php安装目录下配置,这将导致配置的无效。

总结:加载dll + 指定php.ini配置路径+php类型解析。

安装Appserv后,phpmyadmin进不去的问题

mikel阅读(1443)

问题:

安装Appserv后,phpmyadmin进不去的问题

配置PHP环境,安装Appserv后,登陆127.0.0.1能够正常进入,但是点击phpMyAdmin Database Manager Version 2.10.3显示登录界面。输入账号密码后(绝对正确)就一直加载。有谁知道这个问题怎么解决吗。重装也试过了。。。

解决方法:

系统里面的配置 C:\WINDOWS\system32\drivers\etc\hosts打开修改里面的 127.0.0.1对应到localhost

[转载]逆向某停车app(原创) - 七夜的故事 - 博客园

mikel阅读(967)

来源: [转载]逆向某停车app(原创) – 七夜的故事 – 博客园

最近一直在做python开发的事情,信息安全方面做得很少,也是”蛋蛋”的忧伤呀。今天有朋友请我帮忙,将一个app里的文字和图标替换一下,花了一下午和一晚上的时间搞了一下,主要是图标的PS很伤脑筋,弱项呀。。。满眼都是泪。。。。。。只能慢慢的做了。。。

先把工具更新一下,发现AndroidKiller_v1.3已经发布一段时间,看来真是好久没搞了。。。把apk拖进去进行反编译。

AndroidKiller提供了很好的搜索和替换功能,所以文本替换变得极其的方便。

替换文字极其方便,替换图标稍微麻烦一点,首先找到对应16进制ID,再找到布局文件,接着找到图标,最后PS修改一下,改一下布局,就OK了,技术上不复杂,就是费时间。

 

 

当然这不是我们几天说的重点,咱们讨论的是反编译,修改,打包,签名,这一系列工作之后遇到的难点。

 

这个停车app在我改完之后,能在手机上安全运行,不出现异常,以为就要大功告成的时候。我的朋友发现了问题,就是百度地图显示不出来了。。。

此番逆向的难度也就在这个地方了。怎么解决这个问题呢?

 

既然是百度地图显示不出来,可以判断出百度地图进行了校验,反编 译后的app和原app最大的不同是签名,差不多可以肯定是校验了签名。幸亏之前做过两三年的Android开发,了解过百度地图的开发,这次发挥了作 用。看来要搞好信息安全,学会开发是基本功呀。废话不多说,既然确定了秘钥问题,那咱们就去 百度地图开发者中心 去解决问题。

登录百度地图开发者中心,注册成开发者。我已经注册完成了。

大家注意到图中这句话了吗!!!

  百度地图Android SDK提供的所有服务是免费的,接口使用无次数限制。您需申请密钥(key)后, 才可使用百度地图Android SDK。

由此看来咱们的猜测是对的,是通过密钥进行判断,是否被允许使用百度地图SDK。咱们看一下,密钥是怎么生成的,怎么放到程序中校验的。

http://lbsyun.baidu.com/index.php?title=androidsdk/guide/key

 

这就是申请密钥的整个流程,密钥的生成主要和数字签名(SHA1)和包名有关。

包名咱们可以在manifest文件中找到。

由于咱们使用的是AndroidKiller的签名文件(原程序的也搞不到。。。),所以数字签名(SHA1)就使用AndroidKiller的。

 

最后咱们把包名和数字签名填写好,提交之后,就生成咱们自己的应用和密钥。

那这个密钥应该填写到什么地方呢????

从开发文档中,咱们可以看到

好,那咱们就直接找到咱们反编译程序的AndroidManifest文件,然后使用我自己的密钥把他原来的给替换掉。

当这一切都做完后,打包安装,看效果,可想而知,成功了,地图出来了。

今天的分享就到这里,如果大家觉得不错的话,记得打赏呦。

欢迎大家支持我的公众号:

ThinkPHP框架初步掌握

mikel阅读(994)

为了帮老师用ThinkSNS二次开发一个微博系统,专门花了几天学习ThinkPHP框架,现在将一些ThinkPHP入门知识作以记录。

 

首先声明:

本文不是完全教程,只是将开发中碰到的问题作以总结,如果需要学习ThinkPHP框架,请参考官网文档:

官网首页

ThinkPHP3.1快速入门教程(更新中)

目录结构

目录/文件 说明
ThinkPHP.php 框架入口文件
Common 框架公共文件目录
Conf 框架配置文件目录
Lang 框架系统语言目录
Lib 系统核心基类库目录
Tpl 系统模板目录
Extend 框架扩展目录(关于扩展目录的详细信息请参考后面的扩展章节)

 

 

 

 

 

 

 

 

 

我的文件结构

入口(ThinkPHP.php)

1、先在Web根目录(我用的phpstudy,是www文件夹)下面创建一个app项目(这个app就是我们的项目名)。

2、将下载的ThinkPHP解压(我是解压到app下,名为ThinkPHP)。

3、在app目录下面创建一个index.php文件,添加两行简单的代码:

    <?php
    define("APP_DEBUG", TRUE);  //开启调试模式,方便调试
     require '/ThinkPHP框架所在目录/ThinkPHP.php';  //我的为/ThinkPHP/ThinkPHP.php

这行代码的作用就是加载ThinkPHP框架的入口文件ThinkPHP.php,这是所有基于ThinkPHP开发应用的第一步。
然后,在浏览器中访问这个入口文件。

        http://localhost/app/index.php

因为index.php为默认首页,所以亦可省略。

 

模板(Tpl)

Tpl文件夹下为模版页面,可放置html、php等页面。

同时支持多模块,即可在Tpl下建立多个文件夹,每个文件夹对应一个模块,同时一个模块和一个控制器对应(需要名字相同)

我的:

两个模块Form、Index

Tpl下对应有两个文件夹Form、Index

则对应的控制器也是两个FormController.class.php、IndexController.class.php

 

控制器(Controller)

命名:模块名+Controller

PATHINFO模式:是系统的默认URL模式,提供了最好的SEO支持,系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境。

对应上面的URL模式,PATHINFO模式下面的URL访问地址是:

    http://localhost/app/index.php/module/action/var/value/
  //module为模块名称(控制器名称)、不带Controller
  //action为操作名称(控制器中的方法名称)、不带Model
  //var为参数名
  //value为参数值
  //var与value成对出现

我的:

    http://localhost/app/index.php/Index/index
  调用IndexController下的index()方法  
  如果该方法不存在,将直接调用Tpl/Index/index.html页面

 

模型(Model)

1、命名:模块名字+Model

在ThinkPHP的模型里面,有几个关于数据表名称的属性定义,在对应的Model中声明为属性字段(或者叫成员变量):

属性 说明
tableName 不包含表前缀的数据表名称,一般情况下默认和模型名称相同,只有当你的表名和当前的模型类的名称不同的时候才需要定义。
trueTableName 包含前缀的数据表名称,也就是数据库中的实际表名,该名称无需设置,只有当上面的规则都不适用的情况或者特殊情况下才需要设置。
dbName 定义模型当前对应的数据库名称,只有当你当前的模型类对应的数据库名称和配置文件不同的时候才需要定义。

 

 

 

只要命名规范,ThinkPHP会根据Model名字找到你要调用的数据库表,当然,前提你得建立。

规则:

1)表名为tp_categories(tp_为表前缀,在配置文件中配置)

 

    protected $tableName = 'categories';

 

2)表名为top_depts,top_不是系统配置的表前缀,需要使用表的全名

    protected $trueTableName = 'top_depts';

3)可设置数据库

    protected $dbName = 'top';

 

调用:

可调用本模块Model,也可跨项目或模块调用。

本模块:

 

D("UserModel")

 

 

跨项目:

 

D("UserModel", "app")  //D(Model名称,项目名称)

 

M方法与D方法类似,不过,我只用了D方法

 

 

函数库

可通过load(@.hello),hello为函数库文件名称

也可通过在项目配置文件中定义LOAD_EXT_FILE参数,例如:

    "LOAD_EXT_FILE"=>"user,db"

 

类库

通过import可引入使用的类包,可跨项目或模块

import("App.Model.UserModel");
App为应用名

Model表明是模型

UserModel为模型名称

 

数据库

这块东西太多,使用也最频繁,因此,官方文档介绍的很详细,请大家点击文章开头的链接查看

 

写了好久,希望对大家有点用处。

 

 

原文链接:http://www.cnblogs.com/FlyFive/archive/2013/01/06/2848246.html

[转载]Remote Desktop using C#.NET - CodeProject

mikel阅读(1227)

来源: [转载]Remote Desktop using C#.NET – CodeProject

This article is about showing how to create a .NET application to perform remote desktop operation using Microsoft Terminal Services Client ActiveX control.

Introduction

Remote Desktop Services is one of Microsoft Windows components to access a remote computer through the network. Only the user interface of the application is presented at the client. Any input is redirected over to the remote computer over the network.

At work, we use Remote Desktop a great deal. It allows us to login to a remote server to perform health checks, deploy applications, troubleshoot problems, etc. We also use remote desktop often when we do WFH (work from home).

Why do you want to write a .NET application to do this when you have the MS Terminal Services client available from OS? Well, consider if you want to work on 3 different application servers at the same time and want to toggle between these 3 servers quite often. With the MSTSC, we will be running 3 different clients for the 3 servers and it is difficult to manage the working environment. In .NET, you can develop an application with tab control to load remote desktop sessions in different tabs in one window.

Background

We will be using AxMSTSCLib an ActiveX component in our program to connect to the remote computer. It’s not that hard to build a remote desktop application in .NET. Microsoft has a “Microsoft RDP client control” ActiveX control that we will be using in our application.

This is How We Do It

We will start by creating a Windows application in the Visual Studio IDE.

Add a reference to “Microsoft Terminal Services Control Type Library” from the COM tab. This will add MSTSCLib.dll to the project.

Sample Image - maximum width is 600 pixelsTo add MSTSC to the toolbox, right click the toolbox and select “Choose Items…”. Now add “Microsoft Terminal Services control from the COM tab.

Sample Image - maximum width is 600 pixelsDrag the newly added control from toolbox to the form.

Add 3 textbox and 2 button controls to the form:

Sample Image - maximum width is 600 pixels

Connect Button – Click Event

Here is how we write the Connect button click event.

rdp.Server = txtServer.Text;
rdp.UserName = txtUserName.Text;
IMsTscNonScriptable secured = (IMsTscNonScriptable)rdp.GetOcx();
secured.ClearTextPassword = txtPassword.Text;
rdp.Connect();

Now assign the properties (Server, UserName) of RDP control with the textbox values.

Here’s how easy it is to login to remote machine. However there is one catch, there is no direct method in RDP control through which you can pass the username and password to login to the remote desktop.

Due to security reasons, you have to implement an interface (IMsTscNonScriptable) to cast it separately.

IMsTscNonScriptable secured = IMsTscNonScriptable)rdp.GetOcx();
secured.ClearTextPassword = txtPassword.Text;

Disconnect Button – Click Event

To disconnect from the remote desktop session, we just need to call the Disconnect() method.

Before disconnecting, we want to ensure that the connection is still available. We don’t want to disconnect if it is already disconnected (very clever, huh).

if (rdp.Connected.ToString() == "1")
 rdp.Disconnect();

That’s all folks!

History

  • 5th November, 2009: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Thiagarajan Alagarsamy

Web Developer
India India
Thiagu is living in Bangalore, India. He has started coding when he was 12 years old. His native is Madurai, a historic city in south India. He loves to code in C#. He frequents code project when he is not coding. Thiagu loves reading Dan Brown and Michael Crichton novels. He is very much interested in Artificial Intelligence (AI). To view his blog – http://csharpnet.blogspot.com

[转载](转)Visual C#中用WMI控制远程计算机 - oraclejava - 博客园

mikel阅读(933)

来源: [转载](转)Visual C#中用WMI控制远程计算机 – oraclejava – 博客园

原文:http://dev.yesky.com/msdn/478/2376978.shtml

 

WMI不仅可以获取想要的计算机数据,而且还可以用以远程控制。远程控制计算机不仅是黑客们的梦想,也是大多数网络管理者所渴 望得到的,尤其在现代的网络 中,每一个网络管理者所面对的局域网,都是由一个庞大的计算机群组成,如果有效的管理网络的每一台计算机就显得格外重要了。目前网络管理软件通常的做法 是,在远程计算机上运行客户端后台程序,在本地计算机上运行一个服务器端前台控制程序,通过这二个程序直接的通讯实现对计算机的远程控制。这种作法的缺点 是十分明显的,当客户端关闭了后台程序,这种远程管理就无法实现了,所以为了克服这个缺点,远程控制软件的客户端程序就做的非常隐蔽,使用户在不知觉中运 行程序。

其实做远程控制软件,WMI是一个很好的选择,尤其是在目前,Windows 2000已经成为了主流的操作系统,利用WMI编写远程控制软件可以省略了已往远程控制软件最头痛的一个环节–分发客户端程序。

版权声明:任何获得天极网授权的网站,转载时请务必保留作者信息和以下链接
天极开发C#专栏:http://dev.yesky.com/msdn/msdnc/

本节中介绍的远程控制程序,能够让使用者重启和关闭远程计算机。其所使用的就是WMI,下面是Visual C#中利用WMI控制远程计算机具体实现步骤。

1. 首先启动Visual Studio .Net,依次选择”文件”、”新建”、”项目”菜单后,在弹出”新建项目”对话框中将”项目类型”设置为”Visual C#项目”,将”模板”设置为”Windows应用程序”,在”名称”文本框中输入”利用WMI控制远程计算机”,在”位置”的文本框中输 入”E:”VS.NET项目”,然后单击”确定”按钮。这样在”E:”VS.NET项目”目录中就创建了一个新的文件夹”利用WMI控制远程计算机”,里 面存放的就是”利用WMI控制远程计算机”的项目文件。

2. 重新执行一下实现【获取远程计算机硬盘信息】项目中的第二至第四步骤。

3. 把Visual Studio .Net当前窗口切换到【Form1.cs(设计)】窗口,并从【工具箱】中的【Windows窗体组件】选项卡中往窗体中拖入下列组件,并执行相应操作:

三个TextBox组件,用以输入远程计算机名称(或IP地址)、远程计算机WMI操作用户名和口令。

一个ComboBox组件,用以选择对远程计算机执行的操作类型。

四个Label组件。

一个Button组件,名称为button1,拖入窗体后,双击此组件,则系统会在Form1.cs文件中自动产生其Click事件对应的处理代码。

4. 按照表06中的数据调整各组件属性对应的数值:

组件类型 组件名称 属性 设置结果
Form Form1 Text 利用WMI控制远程计算机
Form1 FormBorderStyle FixedSingle
Form1 MaximizeBox False
Label label1 Text 机器名称或IP地址:
label2 Text 具有WMI权限的超级用户名:
label3 Text 口令:
label4 Text 选择控制类型:
TextBox textBox1 Text “”
textBox2 Text “”
textBox3 PasswordChar *
textBox3 Text “”
Button button1 Text 执行
button1 FlatStyle Flat

表06:【利用WMI控制远程计算机】项目窗体中各组件的主要属性设定数值表

并按照图09中各组件的位置和排列顺序调整窗体中组件的位置和排列顺序:


图09:【利用WMI控制远程计算机】的设计界面


5. 把Visual Studio .Net的当前窗口切换到Form1.cs文件的编辑窗口,并用下列代码替换Form1.cs中的button1的Click事件对应的处理代码。下列代码的作用是对根据用户的选择对远程计算机进行进行相应的远程控制:

private void button1_Click ( object sender , System.EventArgs e )
{
//确定WMI操作的范围
ConnectionOptions options = new ConnectionOptions ( ) ;
//设定用于WMI连接操作的用户名
options.Username = textBox2.Text ;
//设定用户的口令
options.Password = textBox3.Text ;
try
{
ManagementScope Conn = new ManagementScope( “””””” + textBox1.Text + “””root””cimv2”, options ) ;
Conn.Connect();
//确定WMI操作的内容
ObjectQuery oq = new ObjectQuery ( “SELECT * FROM Win32_OperatingSystem” ) ;
ManagementObjectSearcher query1 = new ManagementObjectSearcher ( Conn , oq ) ;
//获取WMI操作内容
ManagementObjectCollection queryCollection1 = query1.Get ( ) ;
//根据使用者选择,执行相应的远程操作
foreach ( ManagementObject mo in queryCollection1 )
{
string [ ] ss= { “” } ;
//执行重启操作
if (comboBox1.Text ==”重新启动”)
{
mo.InvokeMethod ( “Reboot” , ss ) ;
} else
//执行远程关机
if ( comboBox1.Text ==”远程关机”)
{
mo.InvokeMethod ( “Shutdown” , ss ) ;
}else
MessageBox.Show (“选择不正确的操作!”,”错误!”);
}
}
//报错
catch ( Exception ee )
{
MessageBox.Show ( “连接” + textBox1.Text + “出错,出错信息为:” + ee.Message ) ;
}
}


6. 至此,在上述步骤都正确完成,并全部保存后,【利用WMI控制远程计算机】下面的全部工作就完成了。此时单击【F5】快捷键,就可以运行程序了。在程序的 【计算机名称或IP地址】文本框中输入要控制的远程计算机名称或IP地址,在【具有WMI权限的用户名】和【口令】文本框中输入具有WMI操作的帐户和口 令,在【选择控制类型】组合框中选择对远程计算机的控制类型后,单击【执行】按钮,则程序就能够对指定的远程计算机进行相应的控制了。图10是【利用 WMI控制远程计算机】的运行界面。


图10:【利用WMI控制远程计算机】的运行界面


总结:

通过以上示例,可见WMI的确是一个非常有用的东西,但由于它还比较新,国内甚至国外还没有完整的介绍资料,因此只是简要的浏览了一下WMI的应用,希望本文的内容能够对大家了解、掌握使用Visual C#调用WMI的方法有所帮助。 

[转载]MVC采用HtmlHelper扩展和Filter封装验证码的功能 - 云在青天水在哪 - 博客园

mikel阅读(790)

来源: [转载]MVC采用HtmlHelper扩展和Filter封装验证码的功能 – 云在青天水在哪 – 博客园

最近因为有个项目除了登录还有其他很多地方需要用到验证码的功能,所以想到了采用 HtmlHelper和ActionFilter封装一个验证码的功能,以便能够重复调用。封装好以后调用很方便,只需在View中调用Html扩展好的 方法,相应的Action加上验证功能的Filter就行了。

首先写一个能够随机生成数字的图片的类,园子里有一大把这样的文章,直接拿过来就用了,自己懒得写了。

复制代码
  1   public class CaptchaRender
  2     {
  3         public CaptchaRender()
  4         {
  5         }
  6 
  7         /// <summary>
  8         /// 验证码的最大长度
  9         /// </summary>
 10         public int MaxLength
 11         {
 12             get { return 10; }
 13         }
 14 
 15         /// <summary>
 16         /// 验证码的最小长度
 17         /// </summary>
 18         public int MinLength
 19         {
 20             get { return 1; }
 21         }
 22 
 23         /// <summary>
 24         /// 生成验证码
 25         /// </summary>
 26         /// <param name="length">指定验证码的长度</param>
 27         /// <returns></returns>
 28         public string CreateValidateCode(int length)
 29         {
 30             int[] randMembers = new int[length];
 31             int[] validateNums = new int[length];
 32             string validateNumberStr = "";
 33             //生成起始序列值
 34             int seekSeek = unchecked((int) DateTime.Now.Ticks);
 35             Random seekRand = new Random(seekSeek);
 36             int beginSeek = (int) seekRand.Next(0, Int32.MaxValue - length*10000);
 37             int[] seeks = new int[length];
 38             for (int i = 0; i < length; i++)
 39             {
 40                 beginSeek += 10000;
 41                 seeks[i] = beginSeek;
 42             }
 43             //生成随机数字
 44             for (int i = 0; i < length; i++)
 45             {
 46                 Random rand = new Random(seeks[i]);
 47                 int pownum = 1*(int) Math.Pow(10, length);
 48                 randMembers[i] = rand.Next(pownum, Int32.MaxValue);
 49             }
 50             //抽取随机数字
 51             for (int i = 0; i < length; i++)
 52             {
 53                 string numStr = randMembers[i].ToString();
 54                 int numLength = numStr.Length;
 55                 Random rand = new Random();
 56                 int numPosition = rand.Next(0, numLength - 1);
 57                 validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1));
 58             }
 59             //生成验证码
 60             for (int i = 0; i < length; i++)
 61             {
 62                 validateNumberStr += validateNums[i].ToString();
 63             }
 64             return validateNumberStr;
 65         }
 66 
 67         /// <summary>
 68         /// 创建验证码的图片
 69         /// </summary>
 70         /// <param name="containsPage">要输出到的page对象</param>
 71         /// <param name="validateNum">验证码</param>
 72         public byte[] CreateValidateGraphic(string validateCode)
 73         {
 74             Bitmap image = new Bitmap((int) Math.Ceiling(validateCode.Length*12.0), 22);
 75             Graphics g = Graphics.FromImage(image);
 76             try
 77             {
 78                 //生成随机生成器
 79                 Random random = new Random();
 80                 //清空图片背景色
 81                 g.Clear(Color.White);
 82                 //画图片的干扰线
 83                 for (int i = 0; i < 25; i++)
 84                 {
 85                     int x1 = random.Next(image.Width);
 86                     int x2 = random.Next(image.Width);
 87                     int y1 = random.Next(image.Height);
 88                     int y2 = random.Next(image.Height);
 89                     g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
 90                 }
 91                 Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));
 92                 LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
 93                     Color.Blue, Color.DarkRed, 1.2f, true);
 94                 g.DrawString(validateCode, font, brush, 3, 2);
 95                 //画图片的前景干扰点
 96                 for (int i = 0; i < 100; i++)
 97                 {
 98                     int x = random.Next(image.Width);
 99                     int y = random.Next(image.Height);
100                     image.SetPixel(x, y, Color.FromArgb(random.Next()));
101                 }
102                 //画图片的边框线
103                 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
104                 //保存图片数据
105                 MemoryStream stream = new MemoryStream();
106                 image.Save(stream, ImageFormat.Jpeg);
107                 //输出图片流
108                 return stream.ToArray();
109             }
110             finally
111             {
112                 g.Dispose();
113                 image.Dispose();
114             }
115         }
116 
117         /// <summary>
118         /// 得到验证码图片的长度
119         /// </summary>
120         /// <param name="validateNumLength">验证码的长度</param>
121         /// <returns></returns>
122         public static int GetImageWidth(int validateNumLength)
123         {
124             return (int) (validateNumLength*12.0);
125         }
126 
127         /// <summary>
128         /// 得到验证码的高度
129         /// </summary>
130         /// <returns></returns>
131         public static double GetImageHeight()
132         {
133             return 22.5;
134         }
135     }
复制代码

然后写HtmlHelper类型的扩展方法,以便在View中调用。

复制代码
 1  public static class HtmlExtensions
 2     {
 3         /// <summary>
 4         /// 生成验证码
 5         /// </summary>
 6         /// <param name="helper">当前View的HtmlHelper</param>
 7         /// <param name="urlHelper">当前View的UrlHelper</param>
 8         /// <returns>带验证码的Img</returns>
 9         public static MvcHtmlString GenerateCaptcha(this HtmlHelper helper, UrlHelper urlHelper)
10         {
11             var sb = new StringBuilder();
12             var builder = new TagBuilder("img");
13             builder.Attributes.Add("id", "captcha");
14             builder.Attributes.Add("style", "cursor:pointer");
15             builder.Attributes.Add("src", urlHelper.Action("GetCaptcha", "Common"));
16             builder.Attributes.Add("alt", "单击刷新验证码");
17             sb.AppendLine(builder.ToString(TagRenderMode.Normal));
18 
19             sb.AppendLine("<script>");
20             sb.AppendLine("$(function(){");
21             sb.AppendLine("$('#captcha').bind('click',function(){this.src='" +
22                           urlHelper.Action("GetCaptcha", "Common") + "?time='+(new Date()).getTime()})");
23             sb.AppendLine("})");
24             sb.AppendLine("</script>");
25 
26             return MvcHtmlString.Create(sb.ToString());
27         }
28 
29         /// <summary>
30         /// 生成验证码
31         /// </summary>
32         /// <typeparam name="TModel">Model</typeparam>
33         /// <typeparam name="TValue">Model的值</typeparam>
34         /// <param name="helper">当前View的HtmlHelper</param>
35         /// <param name="expression">Model属性的Lambda表达式</param>
36         /// <param name="urlHelper">当前View的UrlHelper</param>
37         /// <returns>封装好的label,textbox,带验证码的img</returns>
38         public static MvcHtmlString GenerateCaptcha<TModel, TValue>(this HtmlHelper<TModel> helper,
39             Expression<Func<TModel, TValue>> expression, UrlHelper urlHelper)
40         {
41             StringBuilder sb = new StringBuilder();
42             var label = helper.LabelFor(expression, new {}, ":");
43             var textbox = helper.TextBoxFor(expression);
44             var captcha = GenerateCaptcha(helper, urlHelper);
45             sb.AppendLine(label.ToHtmlString());
46             sb.AppendLine(textbox.ToHtmlString());
47             sb.AppendLine(captcha.ToHtmlString());
48 
49             return MvcHtmlString.Create(sb.ToString());
50         }
51     }
复制代码

其中builder.Attributes.Add(“src”, urlHelper.Action(“GetCaptcha”, “Common”))调用了用于生成带验证码的GetCaptcha方法,该方法后面会提到,本人写在
CommonController当中,GetCaptcha方法其实就是调用了上面的CaptchaRender类中的CreateValidateCode方法,生成验证码输出到View。

GenerateCaptcha<TModel, TValue>这个泛型方法可以绑定视图模型中验证码的字段,并且生成label,textbox,image标签,还有相关的脚本,在View中输出的内容如下:

复制代码
<label for="Captcha">验证码:</label>
<input id="Captcha" name="Captcha" type="text" value="" />
<img alt="单击刷新验证码" id="captcha" src="/Common/GetCaptcha" style="cursor:pointer"></img>
<script>
$(function(){
$('#captcha').bind('click',function(){this.src='/Common/GetCaptcha?time='+(new Date()).getTime()})
})
</script>
复制代码

CommonController中的GetCaptcha方法如下:

复制代码
        /// <summary>
        /// 生成验证码
        /// </summary>
        /// <returns></returns>
        public ActionResult GetCaptcha()
        {
            CaptchaRender captcha = new CaptchaRender();
            string code = captcha.CreateValidateCode(5);
            TempData["Captcha"] = code;
            byte[] bytes = captcha.CreateValidateGraphic(code);
            return File(bytes, "image/jpeg");
        }
复制代码

TempData[“Captcha”] = code是把生成的验证码放到TempData中,以便在ActionFilter中获取到验证码的值,ActionFilter方法如下:

复制代码
 1     public class CaptchaValidatorAttribute : ActionFilterAttribute
 2     {
 3         private const string CaptchaFormValue = "Captcha";
 4         public override void OnActionExecuting(ActionExecutingContext filterContext)
 5         {
 6             bool valid = false;
 7 
 8             foreach (var value in filterContext.HttpContext.Request.Form.AllKeys)
 9             {
10                 if (value.Contains(CaptchaFormValue))
11                 {
12                     valid = (string) filterContext.Controller.TempData["Captcha"] ==
13                             filterContext.HttpContext.Request.Form[value];
14                     break;
15                 }
16             }
17             filterContext.ActionParameters["captchaValid"] = valid;
18             base.OnActionExecuting(filterContext);
19         }
20     }
复制代码

CaptchaValidator过滤器其实就是在相应的Action执行前,遍历Form窗体变量集合的所有Key值,把保存在 TempData[“Captcha”]中的验证码的值和Form窗体中name=”Captcha”(Key值=”Captcha”)的Textbox 的值(用户输入的验证码)比较,然后再把比较后的bool值赋值给用CaptchaValidator特性修饰的Action的captchaValid 参数。(Action根据captchaValid参数的值去判断是否通过验证)。

View视图代码调用如下:

@Html.GenerateCaptcha(m => m.Captcha, Url)

Action调用如下:

一定要记得Action的参数名称captchaValid和过滤器中 filterContext.ActionParameters[“captchaValid”]一致。

效果图如下:

 

[转载]asp.net signalR 专题—— 第一篇 你需要好好掌握的实时通讯利器 - 一线码农 - 博客园

mikel阅读(758)

来源: [转载]asp.net signalR 专题—— 第一篇 你需要好好掌握的实时通讯利器 – 一线码农 – 博客园

一:背景

我们知道传统的http采用的是“拉模型”,也就是每次请求,每次断开这种短请求模式,这种场景下,client是老大,server就像一个小乌龟任人摆布,

很显然,只有一方主动,这事情就没那么完美了,所以为了能够让server也能主动点,html5就应运而生了,或许大家都知道html5中有两种server的主动

模型,第一种叫做websockect,也就是基于tcp模式的双工通讯,还有一种叫做SSE,也就是客户端来订阅服务器的一种事件模型,当然了,在html5出

来之前,如果要做到服务器主动,我们只能采用变相的longpool和foreverframe勉强实现,而signalR这吊毛就是一个对他们进行了高层封装,也就是说

signalR会在这四种技术中根据浏览器和服务器设置采取最优的一种模式,废话不多说,我们快速建立一个例子。

 

二:快速搭建

这里我们采用 PersistentConnection模式来构建一个持久连接让大家快速接触下:

 

1. PersistentConnection

在新建项目中,我们选择”Sig“这里我们就使用默认的名字MyConnection1。

 

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace WebApplication1
{
    public class MyConnection1 : PersistentConnection
    {
        protected override Task OnConnected(IRequest request, string connectionId)
        {
            return Connection.Send(connectionId, "Welcome!");
        }

        protected override Task OnReceived(IRequest request, string connectionId, string data)
        {
            return Connection.Broadcast(data);
        }
    }
}
复制代码

 

在上面,我们简单的看出来了,”持久连接“类有点像socket连接,有OnConnected和OnReceived事件,这里我们就不过多介绍,只要知道

Connection.Send方法中有一个叫做connectionID就好了,而这个connectionID就是客户端和服务器建立连接的唯一标识,比如上面我们看到的

return Connection.Send(connectionId, “Welcome!”);就是当客户端连接到服务器之后,服务器主动将客户端推送一个”Welcome”,以示欢迎。

 

2. Startup类

由于signalR采用的是Owin中间件的模式来把signalR和FCL进行隔离,这样的话,大家就可以相互独立,谁也不依赖于谁,也就方便signalR快速独立

发展和更新,而Startup类的Configuration方法就是将一些中间件配置送到Owin管道中,下面我们要做的就是把MyConnection1和”/myconnection”

地址的映射送到Owin管道中,这样当我访问”/myconnection“的时候,就可以触发MyConnection1这个类了,如下图:

复制代码
[assembly: OwinStartup(typeof(WebApplication1.Startup1))]

namespace WebApplication1
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR<MyConnection1>("/myconnection");
        }
    }
}
复制代码

 

3:新建客户端

这里我们采用web客户端的形式来连接server,这就必须引用一些js文件,比如这里的signalR.js和JQuery.js,如下图:

复制代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta charset="utf-8" />
</head>
<body>
    <script src="/scripts/jquery-1.10.2.js"></script>
    <script src="/scripts/jquery.signalR-2.1.2.js"></script>
    <script type="text/javascript">
        var conn = $.connection("/myconnection");

        conn.start().done(function (data) {
            console.log("当前clientID=" + data.id);
        });

        //接受服务器的推送
        conn.received(function (data) {
            console.log("server返回的数据: " + data);
        });
    </script>
</body>
</html>
复制代码

 

上面的代码很简单,第一个就是$.connection(“/myconnection”)用于找到对应的服务器端的Myconnection处理类,第二个start()方法就是开始建

立连接,后面的 received事件就是获取服务器端推送过来的消息,也就是welcome,对吧。。。然后我们在chrome中试试看。

现在,你可以对应代码看一看,start方法成功的拿到了connectionID,而received方法成功的拿到了服务器推送的”welcome”数据,对吧。

 

四:用Fiddler监视一下

下面就是我用Fiddler监视到的截图,从图中的http 101状态码就可以看出,这里将http协议转换成了websocket协议。然后我们从websocket

协议中看到了服务器端推送过来的“welcome”数据。

 

好了,本篇大概就这么说了,是不是非常简单,当然里面还有很多的细节没有说,后续我们来慢慢解读。

[转载]Android 控件架构 - laozhu1124 - 博客园

mikel阅读(925)

来源: [转载]Android 控件架构 – laozhu1124 – 博客园

  如果说Android上的app是一个有血有肉的人的话,那么人靠衣装马靠鞍,那么控件就是把app装扮的漂漂亮亮的“衣服”。那么安卓的控件到底是如何架构,又是如何渲染的了。

无论是什么控件,在Android中控件只有两种,一种就是View,另一种是ViewGroup。ViewGroup控件组,一个控件的百宝 箱,可以包含各种各样的控件组,它不仅能够包含控件还能够管理着控件。通过ViewGroup,整个控件就至上而下的形成了树形结构,即我们通常所说的控 件树;父控件负责相应子控件的绘制与测量,并向其传递交互事件。安卓系统怎么准确无误的找到每一个控件?只需要调用findViewbyid的方法就能够 按照深度优先的方法找到每一个控件了。在每个控件树最顶端,都站立了一个Viewparent对象,这个对象也是这颗控件树的核心,所有的交互管理事件都 是由这个大大负责统一分配和调度,从而起这一个整体宏观调控的效果。一个控件树架构如图所示:

做过Android开发都知道,要使一个activity显示相应的布局文件,都必须要setContentView。我们要看一下 setContentView背后到底发生了什么,Android又是如何将其渲染出来的了。要解答这些问题,我们还是要了解Android的界面架构 图。具体的架构图如图所示:

通过上图所示,我们可以得出这样的结论。

①每个activity都有一个window对象。

②而每一个window对象通常是由PhoneWindow来实现。

③每个PhoneWindow对象包含DecorView这个根视图对象,将其视图展示都是通过这个对象显示到PhoneWindow上。

④而DecorView被一分为二,一个是TitleView,一个ContentView,TitleView显示相应的标题,ContentView显示具体布局,这些应该大家很熟悉。

这样架构也可以建立一个上文提到的视图树,这颗视图树长成这个样子:

这样控件树,能够帮我们解答这样一个问题为什么requestWindowFeature()一定要在setContentView之前调用才 能起效。这是由于TitleBar下面才是ContentView,在ContentView之后设置,这时,只能有ContentView。当程序在 oncreate方法调用setcontentView后会调用onResume方法,此时系统会把整个DecorView添加到PhoneWindow 中,最终将视图显示出来。

[转载]asp.net mvc+angularjs+web api单页应用 - wolfy - 博客园

mikel阅读(780)

来源: [转载]asp.net mvc+angularjs+web api单页应用 – wolfy – 博客园

写在前面

最近的工作一直在弄一些h5的单页应用,然后嵌入到app的webview中。之前一直在 用angularjs+html+ashx的一套东西。实在是玩腻了。然后就尝试通过ASP.NET mvc的方式构建单页应用。用到的技术angularjs+webapi+mvc。在网上找到了一些相关的文章,关于anguar的位置也没有一个比较好 的一个标准。这里也是抛砖引玉,希望通过讨论,得到一个更好的结构。

项目结构

结构说明:

_Layout.cshtml:该文件作为模板文件,这里将应用的js,及css文件,都凡在该页。如图所示:

Controllers/api文件夹:存放webapi接口。

Controllers/*.cs:存放控制器。

将angularjs的mvc结构,都存放在了Scripts文件夹,这样做,也是为了操作方便(文件多的话,来回的切换窗口,确实很麻烦)。

Scripts/App:存放angularjs的文件,以及app.js

app.js的定义如下,包括module的注册,以及服务信息:

复制代码
var app = angular.module('app_store', ['ngRoute', 'StoreService', ]);

//服务
var StoreService = angular.module('StoreService', []);
//请求服务
StoreService.factory('requestService', function ($http, $q) {
    var request = {
        method: 'POST',
        url: '',
        headers: { 'Content-Type': 'application/json' },
        data: {}
    };
    var postData = {
        lists: function (type) {
            request.method = "get";
            request.url = "../api/order/lists/" + type + "";
            return requestService($http, $q, request);
        },
        submit_product: function (data) {
            request.method = "post";
            request.url = "../api/order";
            request.data = data;
            return requestService($http, $q, request);
        }
    };
    return postData;
});
function requestService($http, $q, request) {
    var deferred = $q.defer(); // 声明延后执行,表示要去监控后面的执行  
    $http(request).
    success(function (data, status, headers, config) {
        deferred.resolve(data);  // 声明执行成功,即http请求数据成功,可以返回数据了  
    }).
    error(function (data, status, headers, config) {

        deferred.reject(data);   // 声明执行失败,即服务器返回错误  
    });
    return deferred.promise;   // 返回承诺,这里并不是最终数据,而是访问最终数据的API  
};
复制代码

将modlue的定义放在了该js文件中,其中也包括请求的服务,考虑到减少一次静态文件的请求,所以将服务也放在了该文件中。

Scripts/Controllers:这是angularjs的控制器。用来定义前端 的controller。关于这个你可以根据用途,分成不同的控制器。也可以对应于web api的方式定义。我建议如果功能不是太多,还是放在一个里面,如果定义太多的js文件,一是静态文件的请求次数会很多,二是开发起来确实很头大,每次开 发在vs打开n个tab页面,你会发现会让你非常的头大。

Scripts/Filter:存放angularjs自定义的过滤器,(如果过滤器不多,建议还是合并到app.js文件中。)

Scripts/Route:angularjs路由,如果路由不多,仍建议放在app.js中。

Scripts/Views:angularjs视图,存放视图模板。这个分法,不好说,可以参考ASP.NET mvc的分发,按控制器名称建文件夹。如果视图不多,我是一股脑的都塞到views文件夹了。

一个例子

列举一个根据关键字搜索商品的列表的例子。

Scripts/Controllers/StoreController.js

复制代码
app.controller('StoreController', function ($scope, $http, $location, $routeParams, requestService) {
    console.log('StoreController');
    if (!$scope.productKey) {
        $scope.productKey = "飞机";
    };
    requestService.lists($scope.productKey).then(function (data) {
        console.log(data);
        if (data._code === 200) {
            $scope.orders = data._data;
        };
    });
});
复制代码

Scripts/Route/app-route.js

app.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
    .when('/', { templateUrl: '../Scripts/Views/OrderList.html', controller: 'StoreController' })
    .when('/error', { templateUrl: '../Scripts/Views/Error.html', controller: 'ErrorController' })
    .otherwise({ redirectTo: '/error' });
}]);

Scripts/Views/OrderList.html

复制代码
<div class="address_serace">
    <input class="form-control" ng-change="" ng-model="productKey" placeholder="搜索商品">
</div>
<div class="address_div">
    <dl class="address_dl" ng-repeat="item in orders">
        <dt class="address_checkbox">
            <img class="address_check" src="../Images/icon-xx01@2x.png" />
        </dt>
        <dt class="address_user"><img class="address_user" src="../Images/dingy.png" /></dt>
        <dd class="address_font">
            <p class="address_font_t">{{item.Name}}</p>
            <p>单价:{{item.Price}}</p>
        </dd>
    </dl>

</div>
复制代码

ASP.NET mvc 控制器StoreController.cs 中Index的action添加视图,作为呈现的页面。

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Wolfy.MvsSinglePage.Controllers
{
    public class StoreController : Controller
    {
        // GET: Store
        public ActionResult Index()
        {
            return View();
        }
    }
}
复制代码

Index.cshtml,很简单,一个添加指定ng-view的div,用来呈现Views中的html模板的。

@{
    ViewBag.Title = "Index";
}

<div ng-view></div>

web api:OrderController

复制代码
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Wolfy.MvsSinglePage.Models;

namespace Wolfy.MvsSinglePage.Controllers.api
{
    public class OrderController : ApiController
    {
        // GET: api/Order
        [HttpGet]
        [Route("api/order/lists/{key?}")]
        public async Task<HttpResponseMessage> Get(string key)
        {
            return await Task.Run(() =>
            {
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Accepted);
                List<Order> lst = new List<Order>() { 
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机", Price=2222222},
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机2", Price=2222222},
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机3", Price=2222222},
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机4", Price=2222222},
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机5", Price=2222222},
                   new Order(){ Id=Guid.NewGuid(), Dt=DateTime.Now, Name="飞机6", Price=2222222},
                };
                var results = string.IsNullOrEmpty(key) ? lst : lst.Where(x => x.Name.Contains(key));
                response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(JsonConvert.SerializeObject(new { _code = 200, _data = results }))
                };
                return response;
            });
        }
    }
}
复制代码

最后不要忘了,为_Layout.cshtml的html标签添加指令ng-app。

运行测试:

总结

这是在实际工作中,摸索出的一种分层的方式,如果你有更好的建议,可以分享一下,在网上也找了一些资料,并没有具体的分层方式。我这里抛砖引玉,希望有个更好的方案。

博客地址: http://www.cnblogs.com/wolf-sun/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。