[转载]我的python工具-代码生成器

mikel阅读(1015)

[转载]我的python工具-代码生成器 – 编码人生 – 博客园.

做企业MIS系统,最烦人的就是建立实体文件,如果使用ORM多数还要建立映射文件,字母稍有不慎拼写错误组件就加载异常,搞的心浮气躁, 于是自然而然想起写一个代码生成工具,虽然业界CodeSmith等成熟工具早已如雷贯耳,但自己动手量体裁衣,用着也舒服,心里也踏实,早些年也曾使用 C#和Groovy分别写过类似的代码,用于不同的项目,今天又想用python实现一个,目的只是想给刚入门或尚未入门的小朋友(新手)一些建议,代码 也是练出来的,多写代码,多总结,多练习,尤其学习一门新的语言时,根据需要做一些实用的工具,按照自己的思路在设计和实现过程中,会遇到很多问题,当你 解决这些问题后,你也很快掌握了该门语言,何乐而不为呢?
闲话不多讲,这就来说说用python实现一个简单的代码生成工具的思路
步骤1.连接数据库
步骤2.查询数据库系统表,获取数据库表及字段元数据信息,如字段名,类型,长度,是否主键,是否可空等信息
步骤3.加载模板信息,根据命名规则,输出实体类、业务类、映射文件等字符串信息
步骤4.输出结果,保存到文件中

1.使用pymsSQL连接数据库:

代码

1 import pymsSQL
2
3 host=.
4 user=sa
5 password=sa
6 database=Test
7
8 conn = pymssql.connect(host=host, user=user, password=password, database=database)
9 cur = conn.cursor()
10 sql = select * from test
11 cur.execute(sql)
12 cur.fetchall()
13 conn.close()

步骤2.查询数据库系统表,获取数据库表及字段元数据信息,如字段名,类型,长度,是否主键,是否可空等信息

代码

1 sql = “””SELECT sysobjects.name AS Tb_name, syscolumns.name AS Col_name,
2 systypes.name AS Col_type, syscolumns.length AS Col_len,
3 ISNULL(sys.extended_properties.[value], syscolumns.name) AS Col_memo,
4 CASE WHEN Syscolumns.Name IN
5 (SELECT A.Name
6 FROM Syscolumns A INNER JOIN
7 Sysobjects B ON A.Id = B.Id AND B.Xtype = U AND
8 B.Name <> Dtproperties
9 WHERE EXISTS
10 (SELECT 1
11 FROM Sysobjects
12 WHERE Xtype = Pk AND Name IN
13 (SELECT Name
14 FROM Sysindexes
15 WHERE Indid IN
16 (SELECT Indid
17 FROM Sysindexkeys
18 WHERE Id = A.Id AND Colid = A.Colid))) AND
19 B.Name = Sysobjects.Name) THEN 1 ELSE 0 END AS Is_key,
20 Syscolumns.isnullable as IsNullable
21 FROM sys.extended_properties RIGHT OUTER JOIN
22 sysobjects INNER JOIN
23 syscolumns ON sysobjects.id = syscolumns.id INNER JOIN
24 systypes ON syscolumns.xtype = systypes.xtype ON
25 sys.extended_properties.major_id = syscolumns.id AND
26 sys.extended_properties.minor_id = syscolumns.colid
27 WHERE (sysobjects.xtype = U OR
28 sysobjects.xtype = V) AND (systypes.name <> Sysname) AND
29 (sysobjects.name LIKE %)
30 ORDER BY sysobjects.name, syscolumns.colid“””

执行1中的cur.execute(sql); result = cur.fetchall();获取执行上边的sql获取数据库表定义的元数据信息,有心的同学,请自行copy上述sql,在SQL Server 查询窗体里边执行即可看到结果,无需多说.

步骤3.加载模板信息,根据命名规则,输出实体类、业务类、映射文件等字符串信息
通过导入python模块string中的Template定义模板信息如:

代码

from string import Template
EntityTemplate = Template(“””
/***************************************************
#  ${ClassName}.cs
#  Comment:
#
#  Current Version: V1.0
#  Author:
#
#  History List:
#  V1.0    Created by CodeBuilder@${Datetime}
#*****************************************************************************
*/
using System;
using System.Text;
using Higo.Business

namespace ${NameSpace}.Entities
{
[Serializable]
public class ${ClassName}:BaseEntity
{
public ${ClassName}()
{
${Init}
}

${Property}
}
}
“””)

根据从数据库中获取到的表结构信息,生成模板中的变量${NameSpace}, ${ClassName}等上下文信息,调用Template.safe_substitute(context),进行变量的替换,并输出替换后的字符 串,此处数据库字段名称到应用程序代码中的类名称需要事先约定好命名规则,如:数据库表明为T_SYS_CODE_DATA,对应实体类名称为 SysCodeData,另外数据表T_SYS_CODE_DATA中的某一列,如F_CODE_NAME,类型为nvarchar(200),对应应用 程序中属性的定义为:public string CodeName {get;set;}, 除命名规则外,还需要一张数据库类型对应应用程序类型映射表,可以定义一个Python全局字典变量,如:

代码

1 dbmap = {
2 int:int,
3 text:string,
4 bigint:Int64,
5 binary:byte[],
6 char:string,
7 datetime:DateTime,
8 decimal:decimal,
9 float:double,
10 image:byte[],
11 money:decimal,
12 nchar:string,
13 ntext:string,
14 numeric:float,
15 nvarchar:string,
16 real:Single,
17 smalldatetime:DateTime,
18 smallint:Int16,
19 smallmoney:decimal,
20 timestamp:DateTime,
21 tinyint:byte,
22 uniqueidentifier:Guid,
23 varbinary:byte[],
24 varchar:string,
25 variant:object,
26 bit:bool}

通过dbmap[“nvarchar”]获取到的对应类型为string

步骤4.输出结果,保存到文件中

代码

1 def saveFile(filePath, buf):
2 if not os.path.exists(filePath):
3 temp = os.path.dirname(filePath)
4 if not os.path.exists(temp):
5 os.makedirs(temp)
6 else:
7 os.remove(filePath)
8 f = open(filePath,w)
9 f.write(buf)
10 f.close()

ok,大功告成,思路很简单,但在用python代码实现的过程中,熟悉了一下python的数据库操作以及字符串模板替换、列表表达式过滤等常规用法。

源码在这里:/Files/wdong/CodeBuilder.rar,同时也希望得到您的回复和指教,谢谢

[转载]跨域SSO的实现之一:架构设计

mikel阅读(1327)

[转载]跨域SSO的实现之一:架构设计 – 好记性不如烂键盘 – 博客园.

翻译自CodeProject网站ASP.NET9月份最佳文章:Single Sign On (SSO) for cross-domain ASP.NET applications

翻译不妥之处还望大家多多指导、相互交流。

文章分为两部分:架构设计和程序实现,此为第一篇即:架构设计或者叫设计蓝图(Part-I – The design blue print)。:)

简介

周一的早晨,当你正在纳闷周末咋就一眨眼过去了并对接下来漫长的一周感到无比蛋疼之时,你收到了一份Email。

操蛋的是它既不是微软的offer也不是Google的offer,而是客户发来的一个新需求。

他说你们现在帮我们公司做了很多的ASP.NET网站和忽悠我们上线的各种系统,现在我想要我的客户只要在我们拥有的任何一个网站上登录一次,那么在我所有的网站上该用户就都已经登录了,同样,随便他从哪个网站上注销掉,那么他也就从我们所有的网站上注销了……

你受不了客户这么罗嗦了,心想不就是要一个SSO功能吗?使用ASP.NET的form authentication不就可以实现了?因为这样可以在同域的不用网站下共享cookie,只需要在machineKey设置一样的配置节就可以 了。放狗一搜,果然有xxxx条结果。放狗找东西可是我们程序员的特长。

开工前,你又扫了一眼邮件,等等,你看到了邮件中的一行话,微微一蛋疼:我们部署了那些网站,但不是都在同一个域名下。

你的客户狠狠地给你来了个下马威,好像他早就放狗搜过,因为cookie不能跨域共享,也就不能用来实现跨域验证了。

这到底是神马一回事情!(和老外一样扯玩淡,下面正经些)

ASP.NET中的验证原理

这个问题可能是老生常谈了,但在解决难题之前,还是先回归基础来看一看事物的本质到底是如何的。因此,我们重温一下ASP.NET表单验证的原理也并不坏。
下面是ASP.NET表单验证的流程图

验证流程

1:你访问一个需要用户验证的ASP.NET页面

2:在此请求中ASP.NET运行时开始查找cookie(由于表单验证的cookie),如果没有查找到,那么将跳转到登录页面(登录页地址配置在了web.config文件中)

3:在登录页面中,你提供了相关的验证凭证并点击了登录按钮,系统和已存储的数据对比验证成功后,将 Thread.CurrentPrincipal.Identity.Name的属性值设置成了你提供的用户名,并在Response中写入了 cookie(同时还写入了用户信息和一些如cookie名,失效日期等),并重定向到登录前的页面。

4:当你再点击其他的页面(或者点击导航到其他的页面),浏览器发送验证的cookie(也可能包含在该网站下写入的一些其他cookie),这一次已经包含了在上一次response中上次验证获取到的cookie。

5:和以前一样,ASP.NET运行时在请求中查找验证的cookie,这一次找到了,接下来做一些检查(如失效日期、路径等等),如果还没有失 效,那么读取出它的值,恢复出用户的信息,将Thread.CurrentPrincipal.Identity.Name的属性值设置成恢复出的用户 名,检查该用户是否有权限去访问当前请求的页面,如果有,那么页面执行的结果返回到用户的浏览器。

过程很简单,对吗?

ASP.NET中多站点同域下的验证原理

如前所述,ASP.NET表单验证完全依赖于cookie。那么只要使得不同的站点共享同样的验证cookie,那么就可以实现在一个站点登录实现所有站点的登录。

HTTP协议指出,如果两个站点是同域(或者是子域)的,那么可以共享cookie。本地的处理是浏览器根据网站的URL存储cookie在本地 (磁盘或者内存中)。当你请求接下来的任意页面时,浏览器读取和当前请求的URL匹配的域或子域的cookies,并将此cookies包含在当前的请求 中。

现在我们假设有下面两个网站:

www.mydomain.com/site1

www.mydomain.com/site2

这两个站点共享同样的主机地址(同样的域mydomain.com和子域www),且两个站点都被配置成了对用户验证和授权都使用表单验证。假设你已经登录过了站点www.mydomain.com/site1,如前所述,你的浏览器现在对于站点www.mydomain.com/site1已经有了表单验证的cookie。

现在你随意访问以www.mydomain.com/site1开头的URL,表单验证的cookie都将被包含在请求被发送。为什么?是因为此cookie本来就属于该站点吗?对的,但不是完全正确。事实上,是因为请求的URL:www.mydomain.com/site1http://www.mydomain.com/拥有同样的域名和子域名。

那么在你登录了www.mydomain.com/site1后,如果你点击www.mydomain.com/site2下的URL,表单验证的cookie也将被包含在请求中发送,这同样是因为www.mydomain.com/site2与站点http://www.mydomain.com/拥有同样的域名和子域名,尽管它是不一样的应用站点(site2)。显然,在拥有一样主机地址不一样的应用站点名之间是可以共享表单验证cookie的,这样就实现了一处登录处处都已经登录的功能(也就是单点登录)。

然而,ASP.NET没有允许你仅仅通过将同主机地址下的站点部署上表单验证后就自动完成了单点登录。为什么这样呢?因为每一个不同的 ASP.NET web应用程序使用它自己的密钥去加密和加密cookie(还有诸如ViewState之类的)从而确保了安全。除非你给每一个站点指定了同样的加密密 钥,那么cookies将被发送,但是另一个应用站点不能够读取验证cookies的值。

指定同样的验证密钥可以解决这个问题。为每一个ASP.NET应用站点使用同样的<machinekey>配置节即可,如下:

<machineKey
validationKey=”21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D”
decryptionKey
=”ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F”
validation
=”SHA1″
decryption
=”AES”/>

如果同样的machinekey(包括validationKey和decryptionKey)被用在同域下的所有应用站点时,就可以实现了跨站点读取cookie。

如果是同样的域不同的子域呢?

假定你有下面两个站点:
site1.mydomain.com
site2.mydomain.com
这两个站点共享同样的域(同样的二级域名mydomain.com),但拥有不一样的三级域名(不一样的子域site1和site2)。
默 认情况下浏览器仅仅发送主机地址一样(相同的域和子域)的站点的cookie。因此站点site1.mydomain.com不能获取到站点 site2.mydomain.com下的cookie(因为他们没有相同的主机地址,它们的子域不同),尽管你为这两个站点配置了相同的 machineKey,一个站点还是不能获取另一个站点下的cookie。
除了你为所有的站点配置了一样的machineKey,你还需要为验证cookie定义相同的域以使得浏览器在同样的域名下能够发送任何请求。

你需要像下面这样配置表单验证cookie:

<forms name=”name” loginUrl=”URL” defaultUrl=”URL” domain=”mydomain.com”/>

那么,在不用的域下如何去共享验证cookie呢?

显然这是不可能的,因为HTTP协议基于安全的原因阻止了你在不同的域之间共享cookie。
同样,假设有下面这两个域名:
http://www.domain1.com/
http://www.domain2.com/
如果你使用表单验证登录进了http://www.domain1.com/,当你点击http://www.domain2.com/下的URL时,浏览器将不能发送domain1.com的cookie到domain2.com。在ASP.NET中没有内置的方法去完成在两个不同的站点间实现单点登录。
要在两个站点间通过访问同样的cookie来实现单点登录,还真没有什么高级的技巧或即有的架构模型去解决它。

跨域单点登录设计雏形

假设有下面三个站点:
http://www.domain1.com/

http://www.domain2.com/
http://www.domain3.com/
为了实现在这些站之间实现SSO,当用户在任意一个站登录时,我们需要为所有的站点设置验证cookie。
如果用户1登录进http://www.domain1.com/,那么在给站点1response前会在response中加入验证的cookie,但当我们需要同时能够登录进http://www.domain2.com/http://www.domain3.com/时,我们需要同时在同样的客户端浏览器上为站点2和站点3设置验证cookie。因此,在response返回到浏览器前,站点1不得不定向到站点2和站点3去设置验证cookie。

下面的流程图详细描述了思路:

操作流程:

请求http://www.domain1.com/中一个需要验证的页面

状态:浏览器没有验证cookie

浏览器发送一个请求到http://www.domain1.com/,但请求中没有验证cookie(因为还没有属于http://www.domain1.com/的cookie)。

状态:浏览器没有验证cookie

因为请求中没有验证cookie,所以请求http://www.domain1.com/

的登录页面

状态:浏览器没有验证cookie

用户提供登录凭证点击登录按钮,浏览器发送一个POST请求到http://www.domain1.com/
http://www.domain1.com/验证用户提供的登录凭证,验证通过后,标记用户的状态为已登录,添加验证的cookie和其他的用户信息一起添加在response中

状态:浏览器没有验证cookie

response并没有返回给浏览器,而是将请求重定向到http://www.domain2.com/的一个页面,并将ReturnUrl设置成重定向前http://www.domain1.com/的URL值。在验证cookie被包含在了response中了后,cookie被发送给浏览器。

状态:浏览器没有验证cookie

浏览器接收到了包含验证cookie的response和重定向到http://www.domain2.com/的命令。浏览器存储了http://www.domain2.com/的验证cookie并向http://www.domain2.com/发送请求。

状态:浏览器包含了http://www.domain2.com/的验证cookie

http://www.domain2.com/立即再重定向到存储在ReturnUrl中的URL地址,在此请求中读取cookie值并为http://www.domain1.com/设置验证cookie。最终,在重定向的命令中也包含了这些验证cookie。

状态:浏览器包含了http://www.domain2.com/的验证cookie

浏览器接收到包含了验证cookie的重定向命令跳转到http://www.domain1.com/。现在浏览器存储了站点1的验证cookie并开始请求站点1,当然在请求中包含了验证cookie。

状态:浏览器包含了http://www.domain1.com/和http://www.domain2.com/的验证cookie

站点1检查了请求中包含了验证cookie,就不需要再去跳转到验证页面去验证,而是返回用户请求的页面

状态:浏览器包含了http://www.domain1.com/和http://www.domain2.com/的验证cookie

如果此时用户请求站点2, 因为浏览器已经存储了站点2的验证cookie,cookie将被包含在请求中,站点2从cookie中获取到用户信息,并为此用户返回请求的页面。
当浏览器验证了站点2和站点3后,那么用户就已经登录了所有的站点,这样就完成了一次单点登录。

如何单点注销?

作为单点登录的一部分,我们还需要去关注下单点注销,就是说当用户在一个站点注销后,那么就认为他从所有的站点都注销了。
清除所有站点的cookie和上面登录一样,也是请求-重定向-返回的过程。只是和设置验证cookie不一样的是,这次从response中移除验证cookie。

此单点登录模型的缺点

这个模型在两个站点上还是能运行的很好的。从一个站点登录或注销,此SSO模型下的站点都将遵从请求-重定向-返回的流程。当用户登录任一页面时,因为已经存储了所有站点的验证cookie,那么就不需要再执行上面的那个循环的流程了。
但 是当站点超过两个时,问题就变得复杂了,当登录站点1时,程序将重定向到站点2和站点3进行验证cookie的设置,最后站点3在跳转到站点1,服务器返 回用户请求的页面。这使得每个站点的登录和注销的过程变得复杂并花费较高的代价。如何超过3个站点呢?如果这样去设计20+站点的单点登录呢?这个模型将 完全不能胜任了。
并且此模型需要每个站点都具备用户验证逻辑,因为需要来请求此站点并设置其验证cookie。
因此此模型丢失了一般意义上的单点登录的概念,我们需要一个更好一点的模型去实现单点登录的功能。

更好的跨域单点登录架构

前面提到的架构中,设置移除cookie都需要跳转到N-1个站点去完成。每个站点还需要知道N-1个站点复杂的登录注销逻辑,
如果我们为所有的站点只去维护一份验证cookie呢?使用一个独立的站点去完成验证用户并设置验证cookie的工作呢?这个想法好像不错。
要使用单点登录,那么就需要用户的数据是统一的,这样的话就可以通过一个站点提供web或者WCF服务来完成验证和授权的功能。这样就省去了冗余的用户验证逻辑,现在最重要的是这个独立的站点如何在SSO架构中起作用。
在这个架构模型中,浏览器不存储任何其他站点的验证cookie,只存那个独立站点的验证cookie,我们就给它起名叫http://www.sso.com/
在此架构中,对每一个站点的请求都将被直接跳转到http://www.sso.com/,由于检查验证cookie是否存在。如果cookie存在,如果存在,返回请求的页面,如果不存在,那么就跳转到对应的登录页面。
大致流程图如下:

便于理解,我们假定有下面两个网站:
http://www.domain1.com/
http://www.domain2.com/
还有一个用于管理验证cookie的站点:http://www.sso.com/
验证流程如下:

用户请求http://www.domain1.com/中一个需要验证的页面
重定向到http://www.sso.com/,ReturnUrl参数设置成请求站点1时的URL。
http://www.sso.com/检查是否有验证cookie存在,如果在请求中没有任何用户令牌存在,那么请求中带着用户需要登录的指令就跳转到站点1。在query string中仍然保留着之前ReturnUrl参数的值。
站点1从参数中得知是从http://www.sso.com/跳转而来,且得知没有用户验证cookie,最后跳转到站点1的登录页面进行登录,而不跳转到http://www.sso.com/
用户提供验证信息点击登录按钮,请求没有回置到站点http://www.sso.com/,这时,站点1通过http://www.sso.com/提供的web/WCF接口进行用户的验证,如果验证成功,那么为用户颁发一个令牌(可以是一个GUID)。
站点1标志用户已经登录成功(在session中存储用户对象),一个包含了令牌的URL跳转到http://www.sso.com/设置验证cookie,ReturnUrl参数还是设置成前面请求的URL。
http://www.sso.com/站点检查过来的URL,发现有用户令牌,但还没有用户验证cookie,说明已经通过了站点1的认证,现在需要设置站点http://www.sso.com/下的验证cookie。照例设置好了cookie后,将cookie添加在response中,还添加上用户令牌按照ReturnUrl参数中的URL一并返回。
浏览器得知要跳转到站点1,并且有了站点http://www.sso.com/的验证cookie,在本地存储下sso站点的验证cookie并对站点1发起请求。
站点1检查了用户令牌,因为是通过站点SSO的web/WCF服务验证并通过的,所以站点1返回用户请求的页面。

现在用户请求站点2
浏览器跳转到sso站点,依然设置好ReturnUrl的值。
浏览器因为要跳转到sso站点,发现本地有了sso站点的验证cookie,所以将cookie添加在请求中一并发出。
sso站点检查cookie,发现cookie还没有过期,那么在query string中添加上用户令牌按照ReturnUrl返回。
站点2发现有用户令牌,证明已经走过验证流程,那么就返回用户请求的页面。

总结

刚开始,浏览器没有任何http://www.sso.com/站点下的验证cookie。请求站点1和站点2任何需要验证的页面(需要内部的跳转到sso站点检查验证cookie是否存在)。用户登录后,sso站点的验证cookie存储在本地(重要的是用户令牌仅仅用户用户登录会话时)。
现在请求站点1或者站点2都跳转到sso站点,浏览器发送sso站点的验证cookie并检查用户令牌,验证后再跳转到原始请求的URL,原始站点检查用户令牌正确后返回用户请求的页面。

传输代价

场景1:访问公共页面
从浏览器到站点+站点到浏览器
1请求+1返回
场景2:访问一个需要验证的页
从浏览器到站点+重定向到sso站点(检查cookie)+重定向到原站点(没有cookie)+原站点返回登录页面到浏览器
1请求+2跳转+1返回
场景3:登录
浏览器POST到站点+调用验证服务进行用户验证+浏览器跳转到SSO站点(带有令牌)+重定向到原站点(带有验证cookie)+通用服务验证令牌+返回用户请求的需要验证的页面
1请求+2验证服务调用+2跳转+1返回
场景4:登录后请求一个需要验证的页面
请求站点+向SSO站点跳转验证cookie(带有验证cookie)+跳转到原站点(检查验证cookie)+调用服务验证令牌+返回请求页面
1请求+2跳转+1服务请求+1返回
场景5:注销
请求站点进行注销+请求SSO站点进行注销+请求原站点移除验证cookie+返回
1请求+2跳转+1返回

孰是孰非

比较这两种架构,第一中架构更适合两个站点,最多三个站点,虽然需要部署复杂冗余的验证逻辑,但是随后的页面请求中就是普通的页面请求了(1请求+1返回)。
第一种架构不易于扩展,且会冗余出很多的用户验证逻辑。
而第二种架构,不管有多少个需要进行单点登录的网站,也不需要其他网站参与此过程,验证的cookie只有sso站点管理,这样的架构逻辑清晰、易扩且部署方便。
然而有一些性能的问题,不同于第一种架构,这种架构当用户请求一个需要验证的页面时需要请求三次(请求sso站点和原站点,两次请求是内部的跳转),且多的两次请求花费的时间很少(空跳转请求,用于设置和检查cookie),在如今这样的网络环境下是可以接受的。

第二种架构的程序实现

等有空了来翻译完第二部分:程序实现
等不及的朋友可以先看原文:http://www.codeproject.com/KB/aspnet/CrossDomainSSOExample.aspx

程序实现源码下载

[转载]android 条码识别软件开发全解析(续1详解)

mikel阅读(857)

[转载]android 条码识别软件开发全解析(续1详解) – tankaixiong – 博客园.

前天我发了一篇关于android开发条码识别软件应用程序的博客,没想到竟很受关注。

我也挺受鼓舞的,好吧,我接上次的博客继续往下写。

前篇有人讲我写的没有实质内容,我接受建议,这里我就带大家体验一下最简单最直接的完美体验。

编写你的第一个Android条码识别程序。zxing的简单使用!

第一步:下载zxing组件:我上篇也简单介绍了一下这个组件,这里也不啰嗦了。

下载两个东东

源码和文档说明:

地址下如

http://code.google.com/p/zxing/downloads/detail?name=ZXing-1.6.zip&can=2&q=

BarcodeScanner3.5.apk这个是编译好的一个可安装的apk程序!这个后面将用到。

地址如下

http://code.google.com/p/zxing/downloads/detail?name=BarcodeScanner3.51b1.apk&can=2&q=

第二步:
模拟器已完全打开后
安装BarcodeScanner3.5.apk

cmd中cd 到sdk目录

利用adb命令安装BarcodeScanner3.5.apk

adb install BarcodeScanner3.5.apk 所在目录,请确定安装成功了。

第三步:ok 终于到编码了!

代码

import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MyTest extends Activity { /** Called when the activity is first created. */ private TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mytest); tv=(TextView) findViewById(R.id.mytxt); findViewById(R.id.mybtn).setOnClickListener(listener); } public Button.OnClickListener listener=new Button.OnClickListener(){ public void onClick(View v){ Intent intent = new Intent("com.google.zxing.client.android.SCAN");//调用扫描的actity,这里其实只是转到刚才安装的BarcodeScanner3程序的中一个actity intent.putExtra("SCAN_MODE", "QR_CODE_MODE");//输入参数,(扫描类型,..二维码) startActivityForResult(intent, 0);//启动intent } }; //扫描成功后回调函数,传回code public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) { if (resultCode == RESULT_OK) { String contents = intent.getStringExtra("SCAN_RESULT"); String format = intent.getStringExtra("SCAN_RESULT_FORMAT"); // Handle successful scan tv.setText(" 条形码为:"+contents+" 条码类型为: "+format);//利用页面的textveiw显示扫描后的结果 } else if (resultCode == RESULT_CANCELED) { // Handle cancel tv.setText(" 扫描失败!"); } } } }

对应的xml如下

01 <?xml version="1.0" encoding="utf-8"?>
03 android:orientation="vertical" android:layout_width="fill_parent"
04 android:layout_height="fill_parent">
05 <TextView android:layout_width="fill_parent"
06 android:layout_height="wrap_content" android:text="@string/hello"
07 android:id="@+id/mytxt" />
08
09 <Button android:text="点我开始扫描" android:id="@+id/mybtn"
10 android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
11 </LinearLayout>

第三步:OK我们赶快看看效果吧, 运行。
你会看到如下:


模拟器当然没有摄像头设备是扫描不到结果的。
总结:
这里只是做了一个简单的调用,调用简单但有一个很大的缺陷,这里我们要安装两个程序!

在安装BarcodeScanner3.5.apk为前题,这明显不能接受!所以接下来我将在下篇博客继续深入。敬请关注!

[转载]Web前端设计模式--制作漂亮的弹出层

mikel阅读(1044)

[转载]Web前端设计模式–制作漂亮的弹出层… – 翁智华 – 博客园.

设计场景:

Ben最近在负责一个购书网站,在网站的首页上,有一个叫做“最新上架”的板块,板块的内容比较简单,只有书籍名称,作者姓名和上架时间(如图),当初设计的时候并i没有过于丰富的构思…

现在问题来了,这个版块不大,更新频率却很高,每天都有十数条最新的信息上去,浏览网站的会员对于最新图书的了解和需求越来越大,因此需要对这个板块进行 改良,以满足会员的需求,会员的主要要求有以下几个方面:显示该最新上架的图书的封面缩略图,该图书的名称和作者名称,以及该书部分内容的介绍和作者的简 介…

这下把Ben给愁坏掉了,首页上根本就没有多余的空间,怎么来呈现封面缩略图甚至是内容简介,如果去掉别的板块空间来实现这一板块的扩张,无异于在一家公司以牺牲一个部门来壮大另外一个部门,这是万万不可取的…

于是Ben想到了以弹出层的方式来显示每条信息的详细内容…

设计目标:

在不改变页面结构的情况下,以弹出层(用Dom重构的方式来实现元素的追加append和移除remove)的方式提高页面信息量…

解决方案:

首先,我们设计一个Div,样式如下:

代码

.TipDiv { width:500px; height:120px; padding:8px; border-top:solid 5px #a6c9e2; border-bottom:solid 5px #a6c9e2; border-left:solid 1px #a6c9e2; border-right:solid 1px #a6c9e2; background:#ffffff; z-index:10;/*z-index很重要,它决定了Div框在页面上的叠加顺序*/ position:absolute;/*绝对定位,它决定了该元素可以根据top 和 left 叠在其他元素上*/ } .TipDiv img { width:110px; height:110px; margin-right:36px; margin-left:10px; float:left; } .TipDiv span { /*×*/ width:340px; height:110px; float:left; word-break:break-all; border-top:dashed 1px #3a7ac8; margin-top:8px; }

下面是脚本,当鼠标经过的时候才响应弹出框事件:

代码

$(document).ready(function(){ //标题鼠标经过 $("ul li a").mousemove(function(e){ $(".TipDiv").remove();//若页面上有该元素,则移除该元素...0 var x=e.clientX + 10;//获取鼠标的x轴坐标 var y=e.clientY + 10;//获取鼠标的y轴坐标 var num=$(this).attr("id"); var imgs; var word; var name; switch(num) { case "1":{ imgs="images/mimi.bmp"; name="秘密 朗达·拜恩 (Rhonda Byrne)..." ; word="这是一个神圣的秘密花园,住着爱丽丝..." ; break; } case "2":{ imgs="images/mama.bmp"; name="一位母亲的记忆 爱心团..." ; word="这是一个关于母亲的故事,感染了每个中国人,她是一位暴走族母亲,也是一位为儿子捐献肝的母亲,她更是一位伟大的,典型的中国母亲..." ; break; } case "3":{ imgs="images/nikesong.bmp"; name="尼克爷爷讲故事 (巴特沃斯, 漪然)..." ; word="★当今世界最出色的儿童绘本作家、插画家!<br>★获得1992年度英国图书奖(British Book Awards)<br>★全球每15分钟就有一本由他创作的绘本被买走<br>★他的绘本让阅读变得赏心悦目!" ; break; } case "4":{ imgs="images/lqz.bmp"; name="李清照:人生不过一场绚烂花(蔚起)..." ; word="《李清照:人生不过一场绚烂花事》精选易安词作50首,从《武陵春(风住尘香花已尽)》始,至《好事近(风定落花深)》结束。通篇以闲话家常、婉约诚挚的笔法评析、阐释,娓娓道来,不生涩,没有说教。" ; break; } } popDiv(imgs,name,word,x,y); }) //标题鼠标离开 $("ul li a").mouseout(function(){ $(".TipDiv").remove(); }) }) //随鼠标移动的信息框 function popDiv(face,name,info,xx,yy) { var str=""; str+="<div class='TipDiv'>"; str+="<img alt='face' src='"+face+"'/>"; str+="<strong><em>"+name+"</em></strong><br />"; str+="<span>"+info+"</span>"; str+="<div>"; $('body').append(str);//在页面上追加该元素,样式如上已经写好 $(".TipDiv").css({"top":yy+"px","left":xx+"px"});//设置该元素出现的位置(这里是出现在鼠标的右边和下边的偏离10px位置) }

结果如下(当鼠标指向第三条数据时,弹出该框, 并随鼠标移动):

做到这边,会员有了一个新的要求,就是不要弹出框随着鼠标的移动而移动,那样鼠标一旦离开焦点,就会移除该弹出框,操作起来不是很方便。他们要求弹出框固定,假设就在相应的数据行的右侧吧,而且打开和关闭由会员自己控制,于是Ben就进行改良了…

同样的,先设计一个id为tips的Div元素,样式如下:

代码

#tips { background-color: white; border-left: 1px solid #a6c9e2; border-right: 1px solid #a6c9e2; border-top:5px solid #a6c9e2; border-bottom:5px solid #a6c9e2; width:268px; height:60px; z-index:9; position:absolute; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding:8px 18px; } /* 弹出层的指向图标,left:-10 使它出现在整个Div的左侧 */ #tips #tipsArrow { position:absolute; top:26px; left: -10px } #tips #light { width:36px; height:36px; margin:6px 16px 16px 16px; float:left; } #tips span { margin-top:18px; } #tips #close { width:20px; height:16px; border:none; z-index:1; left:280px; top:6px; position:absolute; cursor:pointer; }

脚本如下:

代码

$(document).ready(function(){ //时间鼠标经过 $("ul li span").mouseover(function(){ $("#tips").remove(); var elem= $(this).parent(); var mTop=elem.offset().top;//获取该元素的top坐标 var mLeft=elem.offset().left;//获取该元素的left坐标 var addLeft=elem.width();//获取该元素的宽度 var finalTop=mTop-30;//获取最终元素出现的Top位置,此时-30个元素是提高这个Div的高度,让箭头指向对应行 var finalleft=mLeft+addLeft+20; // 获取最终元素出现Left的,对应行的左边加上行宽加上20个空元素 var num=$("li").index(elem)+1; popDiv1(finalTop,finalleft,"提示框提醒你,这是第"+num+"行数据!"); }) }) //固定的信息框 function popDiv1(tops,lefts,messages) { var str=""; str="<div id='tips'><img id='tipsArrow' src='images/arrow.png' alt=''/><img id='close' src='images/close.jpg' alt='' onclick='closeUp()'/><img src='images/light.gif' alt='' id='light'/><p>"+messages+"</p></div>"; $('body').append(str); $("#tips").css({"top":tops+"px","left":lefts+"px"}); } function closeUp() { $("#tips").remove(); }

最终显示效果如下:

鼠标移动到相应的数据行上面,显示相应的提示框,右边的打叉小图标用以关闭整个弹出层…

设计小结:

这 个设计过程的关键是position:absolute(绝对定位,作用是让层在页面上叠加),z-index(用以显示层的叠加次序),top、 left(显示弹出页面坐标),(offset().left,offset().top)在页面上找到某个元素的坐标,位置找到了,就可以随意在它的周 边定位弹出层了,其他的样式可以根据自己的美工需求随意调节…

源码下载(http://files.cnblogs.com/wzh2010/popDiv.rar

[转载](一)Socket服务器整体架构概述

mikel阅读(1110)

[转载]【志良教你学Socket】(一)Socket服务器整体架构概述 – 志良的技术博客 – 博客园.

Socket服务器主要用于提供高效、稳定的数据处理、消息转发等服务,它直接决定了前台应用程序的性能。我们先从整体上认识一下Socket服务器,Socket服务器从架构上一般分为:网络层、业务逻辑层、会话层、数据访问层,如图:

(图1)

(一) 网络层

网络层主要用于侦听socket连接、创建socket、接受消息、发送消息、关闭连接。作为socket通信服务器,网络层的性能相当重要,所以 我们在设计网络层时,要着重在以下几方面获得突破:最大连接数、最大并发数、秒处理消息数。如何突破呢?下面我为大家介绍几种网络层常用到的一些技术和技 巧(具体实现,我将在博文中逐一具体阐述):

1)Buffer管理

每一个SocketAsyncEventArgs对象(以下简称SAEA)在内存中都有其对应的缓存空间,如果不对这些缓存空间进行同一管理,当SAEA 对象逐渐增多时,这些SAEA对象的缓存空间会越来越大,它们在系统内存中不是连续的,造成很多内存碎片,而且这些缓存不能重复利用,当创建、销毁 SAEA对象时,造成CPU很多额外消耗,影响服务器性能。面对这问题如何解决呢?用Buffer池管理!

2)双工通信

Socket服务器提高通信效率是一个永恒的话题,提高通信效率有很多种方法,双工通信就是其中之一。一个SAEA对象在同一时刻只能用来接收数据或发送 数据,有人想,如果一个SAEA对象在同一时刻既能发送数据又能接受数据,那肯定会提高socket通信效率。恩,很有想法!可是你能让你的头在同一时刻 既往左转又往右转吗?答案是不行的,那如何实现双工通信呢?既然一个SAEA对象在同一时刻只能做一件事,那我自定义DuplexSAEA对象,在该对象 中封装两个SAEA,一个用于接受,一个用于发送,问题不就解决了吗。

3)poolOfAcceptEventArgs

poolOfAcceptEventArgs是个什么东西?它不是个东西,是一个容器,一个容纳AcceptSAEA对象的容器。给你两个socket服 务器,你能很快判别两个服务器性能的优异吗?很简单,你瞬间向一台服务器打入5、6万的连接,看看会不会都连上,如果都连上,说明这台socket服务器 的并发处理连接的能力还是不错的。那如何提高socket服务器的并发连接能力呢?答案:poolOfAcceptEventArgs!

4)消息队列调度器

消息队列调度器主要分为两种:接受消息队列、发送消息队列。为什么要用消息队列呢?主要是提高socket服务器的吞吐量。首先我们定义一个队列 Queue,然后编写N个调度器,不断从队列中调度消息,接受队列调度器用于将消息抛至业务逻辑层处理,发送队列调度器用于调用网络层发送消息接口,向指 定端口发送数据。

5)心跳扫描

有一个困惑:客户端连接socket服务器,连接没有断开,但客户端挂了,这样这条连接在socket服务器中就成了钉子户,落地生根不走了!一个钉子户 还可以忍受,千千万万个呢?那就崩溃了!怎样解决这个问题呢?定时扫描每条连接,如果该条连接在超时时间内没有IO响应,则关闭它。

6)粘包

服务器在接受消息包时,如果两个数据包同时被你服务器收了怎么办?你会把他当成一个数据包吗?如果一个数据包断了,分成两次被你服务器收了,你会把他们拼接起来吗?这些就是粘包了,怎么解决?正则表达式扫描!

7)多线程编程

Socket服务器的编程就是多线程编程,面对多线程,线程间怎样同步、怎样避免死锁?多线程访问公共资源如何处理,在下面的博文中,我将会为大家具体阐述。

(二) 业务逻辑层

网络层将解包后的消息包抛至业务逻辑层,业务逻辑层收到消息包后,解析消息类型,然后转入相应的处理流程处理。

网络层应提供发送消息的接口供业务逻辑层调用,因为网络层不会主动发送消息,发送消息的操作是由业务逻辑层来控制的,所以业务逻辑层应根据具体的业务应用,封装不同功能的发送消息的方法。

(三) 会话层

会话层主要用于记录在线用户信息,该层隶属于业务逻辑层。既然隶属于业务逻辑层,那为什么还要独立出来呢?这主要为以后分布式开发拓展用,试 想,一台服务器最大能支持多少人同时在线?中国有多少人?如果1亿人同时在线,你一台服务器能支持得了吗?答案肯定是否定的,所以要分布式开发。分布式开 发涉及到用户信息同步的问题,所以会话层就要独立出来了。

(四) 数据访问层

数据库执行效率是整个socket服务器的瓶颈?为什么呢?举个例子:假设我们的socket服务器的秒处理消息的条数为3000,每处理一条 消息都会保存历史记录,那么,如果数据访问层不想拖网络层的后腿,那么他的执行SQL语句的效率也必须达到每秒3000!如果socket服务器和数据库 服务器部署在同一网段上,这个速度是没有问题的,但如果数据库服务器部署在外网呢?你的SQL语句的执行效率能达到那么高吗?很困难!

再思考一个问题:如果网络层执行线程和数据库执行线程是同一个线程,那么网络层的处理必须等待数据库执行完毕后,才能进行!如果数据库执行效率比较慢,那对整个socket服务器将是一个毁灭性的打击。

那么怎样将数据访问层与网络层分离,让他们互不影响?如何提高数据库执行效率,让网络层的处理速度和数据访问层的处理速度达到一个平衡?答案:连接池+sql调度器+主从数据库。

Socket服务器的整体架构就为大家介绍到这里,下面我将会为大家具体阐述各个技术的实现。

[转载]More Effective C# Partial Class是怎样炼成的?

mikel阅读(1040)

[转载]【More Effective C#】Partial Class是怎样炼成的? – 空逸云 – 博客园.

什么是部分类(Partial Class)?

C#中.我们可以利用部分类,将一个类分散到多个类文件中,这样我们就可以多个开发者同时开发某个类库,或者是扩展其他开发者发布的类库.甚至是代码生成器生成的代码,例如LINQ2SQL,ADO.NET EF等,以获取更高效的开发.

Re:Class和Class File的区别.这里的类是我们平时所说的普通类-Class,如抽象类,基类,子类等等.而类文件-Class File则是我们平时编写类时所用到的文件,如C#的.cs,VB的.vb.

虽然部分类很好的解决了多个开发者同时开发而互不影响的问题,但其约束十分严格.开发者之间不能/很难彼此沟通,并且无法/很难修改对方的代码.这意味着需要为对方提供很多挂钩.这些挂钩应该以部分方法的方式实现.而另一方的开发者可以选择实现或不实现.

扩展现有类

实 体框架的出现,大大的减轻了我们的工作量,使我们把更多的重心放在逻辑实现上,而减少对于数据访问的关注.例如我们可以使用 LINQ2SQL,LINQ2SQL是一个轻型的实体框架.它生成了我们对数据层的访问.但.有些时候,我们需要扩展些自己的内容,如方法/属性等等.除 了直接在生成的类文件中添加修改意外,我们还可以利用部分类扩展我们所需的功能,前者当每次我们跟新实体时.你所扩展的内容都会消失.而部分类依然能很好 的为你服务.

提供部分方法

为部分类提供最有效的钩子就是部分方法.它和接口的方法声明很相似.

关键字partial+void+方法名+方法参数.

partial void ReportValueChanging(RequestChange args);

由于部分方法可能成为类的一部分(实现),也可能不成为类的一部分(不实现),所以C#本身对于部分方法给出了一些限制.

1.返回类型必须为void.

2.部分方法不能为抽象/虚方法.

3.部分方法不能用来实现接口.

4.参数列表不能包含任何out参数,因为编译器无法初始化这些out参数.

我们利用部分方法来让用户件事或修改类的行为:修改方法,事件处理程序及构造函数.

修改方法

修改方法是指那些将要修改类中对外可见的状态的方法.我们可以将其理解为任何状态的变化,由于另一个类文件的部分类实现依然是类的一部分.所以我们可以完全控制到该类的所有内部状态.

一般而言,修改方法应该为类提供两个部分方法.第一个在修改前调用,用来让另一方(另一开发者)能够进行合法性验证等等.第二个方法应该在修改状态后调用,用来让另一方相应这个状态的变化.

public partial class GeneratedStuff
    {
        private struct ReportChange
        {
            public readonly int OldValue;
            public readonly int NewValue;

            public ReportChange(int oldValue, int newValue)
            {
                this.OldValue = oldValue;
                this.NewValue = newValue;
            }
        }

        private class RequestChange
        {
            public ReportChange Values
            {
                get;
                set;
            }
            public bool Cancel
            {
                get;
                set;
            }
        }

        partial void ReportValueChanging(RequestChange args);
        partial void ReportValueChanged(ReportChange values);

        private int storage = 0;

        public void UpdateValue(int newValue)
        {
            RequestChange updateArgs = new RequestChange
            {
                Values = new ReportChange(storage, newValue)
            };
            ReportValueChanging(updateArgs);
            if (!updateArgs.Cancel)
            {
                storage = newValue;
                ReportValueChanged(new ReportChange(storage, newValue));
            }
        }
    }

如果另一个部分类没有提供两个部分方法的实现,那么C#编译器将移除该调用.生成方法如下

public void UpdateValue(int newValue)
        {
            RequestChange updateArgs = new RequestChange 
            {
                Values = new ReportChange(this.storage, newValue)
            };
            if (!updateArgs.Cancel)
            {
                this.storage = newValue;
            }
        }

并且,两个部分方法也一并移除了.

我们可以实现挂钩如下

public partial class GeneratedStuff
        {
            partial void ReportValueChanging(GeneratedStuff.RequestChange args)
            {
                if (args.Values.NewValue < 0)
                {
                    //dosomething...
                }
                else
                {
                    //dosomething...
                }
            }

            partial void ReportValueChanged(GeneratedStuff.ReportChange values)
            {
                //dosomething...
            }
        }

这里,我们通过一个取消标记来让开发者可以取消某个修改动作,你也可以通过抛出异常得到同样的效果.但.推荐使用布尔型的取消标记,因为这样更加轻量一些

事件处理程序

实际上,事件的处理程序和上面的方法修改并无多大的区别.你所需要做的.仅仅只是添加一个委托事件而已.实现了类似控件的事件机制.

构造函数扩展

无论是生成的代码,还是我们手工编写的代码.我们都无法预计调用类时外部将会调用哪个构造函数.所以.我们只能在内部做一些手脚.例如

public partial class GeneratedStuff
        {
            partial void Initialize();
            public GeneratedStuff()
                : this(0)
            { }

            public GeneratedStuff(int someValue)
            {
                this.storage = someValue;
                Initialize();
            }
        }

注意!Initialize在最后调用,这样就有了一次检查当前对象状态的机会,可以进行必要的修改,或是对于不符合要求时抛出异常等等.实际 上.这种构造函数重载也有效的提升你的代码质量(对于不同的构造函数,结果IL都会生成不同的函数块.而这种重构法最后其实真正生成的函数块只有一个)

尾声

经过以上的阐述,相信我们已经更了解部分类是怎样炼成的了.只有更好的了解其背后的一系列”小动作”,才有助于我们更好的提升,写出更有质量的代码

[转载]ASP.NET MVC:窗体身份验证及角色权限管理示例

mikel阅读(898)

[转载]ASP.NET MVC:窗体身份验证及角色权限管理示例 – 鹤冲天 – 博客园.

ASP.NET MVC 建立 ASP.NET 基础之上,很多 ASP.NET 的特性(如窗体身份验证、成员资格)在 MVC 中可以直接使用。本文旨在提供可参考的代码,不会涉及这方面太多理论的知识。

本文仅使用 ASP.NET 的窗体身份验证,不会使用它的 成员资格(Membership) 和 角色管理 (RoleManager),原因有二:一是不灵活,二是和 MVC 关系不太。

一、示例项目

image

User.cs 是模型文件,其中包含了 User 类:

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Password { get; set; }
    public string[] Roles { get; set;  }
}

UserRepository 为数据存取类,为了演示方便,并没有连接数据库,而是使用一个数组来作为数据源:

public class UserRepository
{
    private static User[] usersForTest = new[]{
        new User{ ID = 1, Name = "bob", Password = "bob", Roles = new []{"employee"}},
        new User{ ID = 2, Name = "tom", Password = "tom", Roles = new []{"manager"}},
        new User{ ID = 3, Name = "admin", Password = "admin", Roles = new[]{"admin"}},
    };

    public bool ValidateUser(string userName, string password)
    {
        return usersForTest
            .Any(u => u.Name == userName && u.Password == password);
    }

    public string[] GetRoles(string userName)
    {
        return usersForTest
            .Where(u => u.Name == userName)
            .Select(u => u.Roles)
            .FirstOrDefault();
    }

    public User GetByNameAndPassword(string name, string password)
    {
        return usersForTest
            .FirstOrDefault(u => u.Name == name && u.Password == password);
    }
}

二、用户登录及身份验证

方式一

修改 AccountController:原有 AccountController 为了实现控制反转,对窗体身份验证进行了抽象。为了演示方便,我去除了这部分(以及注册及修改密码部分):

public class AccountController : Controller
{
    private UserRepository repository = new UserRepository();
    
    public ActionResult LogOn()
    {
        return View();
    }

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (repository.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (!String.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
                else return RedirectToAction("Index", "Home");
            }
            else
                ModelState.AddModelError("", "用户名或密码不正确!");
        }
        return View(model);
    }

    public ActionResult LogOff()
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }
}

修改 Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    public MvcApplication()
    {
        AuthorizeRequest += new EventHandler(MvcApplication_AuthorizeRequest);
    }

    void MvcApplication_AuthorizeRequest(object sender, EventArgs e)
    {
        IIdentity id = Context.User.Identity;
        if (id.IsAuthenticated)
        {
            var roles = new UserRepository().GetRoles(id.Name);
            Context.User = new GenericPrincipal(id, roles);
        }
    }
    //...
}

给 MvcApplication 增加构造函数,在其中增加 AuthorizeRequest 事件的处理函数。

代码下载:Mvc-FormsAuthentication-RolesAuthorization-1.rar (243KB)

方式二

此方式将用户的角色保存至用户 Cookie,使用到了 FormsAuthenticationTicket。

修改 AccountController:

public class AccountController : Controller
{
    private UserRepository repository = new UserRepository();
    
    public ActionResult LogOn()
    {
        return View();
    }

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            User user = repository.GetByNameAndPassword(model.UserName, model.Password);
            if (user != null)
            {
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                    1,
                    user.Name,
                    DateTime.Now,
                    DateTime.Now.Add(FormsAuthentication.Timeout),
                    model.RememberMe,
                    user.Roles.Aggregate((i,j)=>i+","+j)
                    );                    
                HttpCookie cookie = new HttpCookie(
                    FormsAuthentication.FormsCookieName,
                    FormsAuthentication.Encrypt(ticket));
                Response.Cookies.Add(cookie);

                if (!String.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
                else return RedirectToAction("Index", "Home");
            }
            else
                ModelState.AddModelError("", "用户名或密码不正确!");
        }
        return View(model);
    }

    public ActionResult LogOff()
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }
}

修改 Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    public MvcApplication()
    {
        AuthorizeRequest += new EventHandler(MvcApplication_AuthorizeRequest);
    }

    void MvcApplication_AuthorizeRequest(object sender, EventArgs e)
    {
        var id = Context.User.Identity as FormsIdentity;
        if (id != null && id.IsAuthenticated)
        {
            var roles = id.Ticket.UserData.Split(',');
            Context.User = new GenericPrincipal(id, roles);
        }
    }
    //...
}

代码下载:Mvc-FormsAuthentication-RolesAuthorization-2.rar (244KB)

三、角色权限

使用任一种方式后,我们就可以在 Controller 中使用 AuthorizeAttribute 实现基于角色的权限管理了:

[Authorize(Roles = "employee,manager")]
public ActionResult Index1()
{
    return View();
}
[Authorize(Roles = "manager")]
public ActionResult Index2()
{
    return View();
}
[Authorize(Users="admin", Roles = "admin")]
public ActionResult Index3()
{
    return View();
}

四、简要说明

MVC 使用 HttpContext.User 属性进行来进行实现身份验证及角色管理,同样 AuthorizeAttribute 也根据 HttpContext.User 进行角色权限验证。

因些不要在用户登录后,将相关用户信息保存在 Session 中(网上经常看到这种做法),将用户保存在 Session 中是一种非常不好的做法。

也不要在 Action 中进行角色权限判断,应该使用 AuthorizeAttribute 或它的子类,以下的方式都是错误的

public ActionResult Action1()
{
    if (Session["User"] == null) { /**/}
    /**/
}
public ActionResult Action2()
{
    if (User.Identity == null) { /**/}
    if (User.Identity.IsAuthenticated == false) { /**/}
    if (User.IsInRole("admin") == false) { /**/}
    /**/
}

若本文中有错误或不妥之处,敬请指正,谢谢!

[转载]C# DataGridView合计行完整解决方法

mikel阅读(2039)

[转载]C# DataGridView合计行完整解决方法、用户体验深刻、超实用 – 专注实用,代码真实可用 – 博客园.

在网络上看过很多关于DataGridView合计的设计及源码,搜到了很多相同的文章(都是相互复制),一点创新都没有。

普遍存在的问题是用户体现不行,或存在很多BUG等。。

很多的人写的解决办法如下几条:

  1. DataGridView的最后一行作为合计行,每增加或删除一行后重新计算合计行。
  2. 用两个大小相同的DataGridView,一个是数据表格,一个是合计表格。
  3. 第三个是用Table类SUM增加一条合计行数据,再显示到DataGridView中。
  4. 干脆用第三方控件。。。。。。。。

以上出现的问题:

合计行不能显示在DataGridView界面的最下方,用户只能滚条到表格最后才能看到合计。

如果用两个DataGridView,那我只能说他是“天才”,我想性能怎么样,大家可想而知。

如果用Table类SUM一条,同样会产生只能要最后一行看到,如果别人不使用Table显示到DataGridView中怎么办。

上述的都不能很好的解决DataGridView合计行,以下是我个人设计原理与说明:

首先我们解决的是不管用什么方式填充DataGridView数据都能够合计数据。

必须显示在DataGridView界面的最下方,这样用户体验深刻一点。

从上我们可以看到,我们要做到合计行的话,我们必须在表现层(UI)做,不要在逻辑层与数据层做,(如果出错的话只是显示错误)

最终效果如下:

合计我使用的是Lable对象。DataGridView需要处理的事件有单元格的数据改变事件CellValueChanged,滚动条事件,列宽事件,这件事件发生后重绘Lable及计算所需要列数据。

定义对象:Lable对象名为FootSumLabel,DataGridView对象名为DetailDataGrid

代码

//定义类的私有变量,两个是滚动条 HScrollBar hs; VScrollBar vs; //合计数值 decimal fSumQty = 0, fSumCBAmount = 0; //加载数据时先注册DetailDataGrid的滚动条事件,在类的构造时注册
 //DetailDataGrid类中包括有HScrollBar,VScrollBar如下 //hs_ValueChanged,vs_ValueChanged两个事件都重绘FootSumLabel,即FootSumLabel.Invalidate();这一句语句 hs = ((HScrollBar)this.DetailDataGrid.Controls[0]); vs = ((VScrollBar)this.DetailDataGrid.Controls[1]); hs.ValueChanged += new EventHandler(hs_ValueChanged); vs.ValueChanged += new EventHandler(vs_ValueChanged); //DetailDataGrid的CellValueChanged事件调用sumdata(); //FootSumLabel的重绘Paint事件 private void FootSumLabel_Paint(object sender, PaintEventArgs e) { int count = DetailDataGrid.Columns.Count; DataGridViewColumnCollection Columns = this.DetailDataGrid.Columns; Graphics grf = e.Graphics; int x = this.DetailDataGrid.RowHeadersWidth - 2; StringFormat strfmt = new StringFormat(); strfmt.Alignment = StringAlignment.Far; for (int i = 0; i < count; i++) { x += Columns[i].Width; if (i == 4) { int xx = x + Columns[i + 1].Width; grf.DrawString(string.Format("{0:F2}", fSumQty), this.FootSumLabel.Font, Brushes.Black, xx - hs.Value, 3, strfmt); } if (i == 7) { int xx = x + Columns[i + 1].Width; grf.DrawString(string.Format("{0:F2}", fSumCBAmount), this.FootSumLabel.Font, Brushes.Black, xx - hs.Value, 3, strfmt); } } } //合计数值函数 private void sumdata() { fSumQty = 0; fSumCBAmount = 0; DataGridViewRowCollection rows = this.DetailDataGrid.Rows; foreach (DataGridViewRow row in rows) { fSumQty += Convert.ToDecimal(row.Cells["fQty"].Value); fSumCBAmount += Convert.ToDecimal(row.Cells["fAmount"].Value); } //重画 this.FootSumLabel.Invalidate(); }

以上代码可以自行加工成一个类,DataGridView调整列宽的事件只要调用重绘FootSumLabel就可以了。如果有不正之处请指出。

如果要转帖请注明出处:http://www.cnblogs.com/NetWZ/articles/1862097.html 作者:.NetWZ

转载asp.net mvc 部署时出现错误 没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问权限

mikel阅读(883)

转载asp.net mvc 部署时出现错误 没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问权限 – 葡萄家园 – 博客园.

在IIS中 发布程序一个ASP.NET程序,通过IE访问报如下错误:

当前标识(NT AUTHORITY\NETWORK SERVICE)没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
说明: 执行当前 Web 请求期间,出现未处理异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误出处详细信息。

异 常详细信息: System.Web.HttpException: 当前标识(NT AUTHORITY\NETWORK SERVICE)没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files

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

在“开始”-“运行”里输入如入命令,回车,搞定

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -i -enable

[转载]android 条码识别软件开发全解析

mikel阅读(1093)

[转载]android 条码识别软件开发全解析 – tankaixiong – 博客园.

Android 条码识别软件开发全解析
Android 的有一大特色就是可以识别条形码得到URL可以直接访问地址并下载,这

个功能无疑为用户提供了很大的方便。

于是在android 上开发条码识别软件肯定是很有必要的!我在网上GOOGLE了一下

发现这类的资料特别少,而且又有很多人在问如何开发。

这里我就分享一下自己的经验。

这里我们会用到一个开源组件zxing ,大体上所有流行的条码都支持(一维码,二维码),并且识别是最好的在所有开源里面。我将详细讲解ZXing的使用
官网地址:http://code.google.com/p/zxing/
这个开源组件支持的条码有如下:
UPC-A and UPC-E
EAN-8 and EAN-13
Code 39
Code 93
Code 128
QR Code
ITF
Codabar
RSS-14 (all variants)
Data Matrix
PDF 417 (‘alpha’ quality)

下面我会详细讲解zxing的使用,将在我下几篇博客中详细讲解。今天又很晚了,

时间总是过的很快啊,尤其是晚上!呵呵,这里先贴出一些效果图吧!
下几篇我的博客文章再详细讲解,大致有如下几个方面:
zxing的编译打包
zxing的简单调用
zxing生成自定义二维码
识别图片中的条码
效果如图:

自定义二维条码

识别图片中的条码: