[转载]ASP.NET MVC 3 Project Upgrade Tool

mikel阅读(939)

[转载]MVC 3 Project Upgrade Tool – Marcin On ASP.NET – Site Home – MSDN Blogs.

We have just released the final version of ASP.NET MVC 3. Read the official MVC 3 release information or download MVC 3.

To help you upgrade your MVC 2 projects to MVC 3 we have released an upgrade tool. You can download it here: http://aspnet.codeplex.com/releases/view/59008. (This is an update of the tool that Eilon Lipton previously previewed on his blog and now we are giving it a more permanent home on our CodePlex site).

1/14 Update: We have updated the file on codeplex to fix an issue with converting solutions that had Web Sites or other solution items. If you are having problems please make sure you download the tool again from the codeplex site.

The upgrade tool only supports Visual Studio 2010 projects targeting .NET 4. Upgrading both MVC 2 and MVC 3 Beta (or RC) projects is supported.

The tool does not support Visual Studio 2008 solutions, MVC 1 projects, or projects targeting .NET 3.5. Those projects will first have to be upgraded using Visual Studio 2010 and/or retargeted for .NET 4:

  • If you have a Visual Studio 2008 solution you can simply open it with Visual Studio 2010 to initiate the solution upgrade process.
  • If your projects are targetting .NET 3.5 read how to target .NET 4.
  • If you have a MVC 1.0 project you can use the old version of this tool to convert it to MVC 2.

MVC upgrade tool screenshot

The usage of the tool is quite simple:

  1. If you use a source control system make sure your files are checked out and writable
  2. Run the executable
  3. Select your Visual Studio 2010 solution file that contains your project
  4. Review the changes for each item in the Item details pane
  5. Click on the Convert button to initiate the conversion process
  6. Review the results in the Conversion log pane

During the conversion process the tool will:

  1. Create a backup of the entire solution.
  2. Update all class library projects (including Test projects) that reference System.Web.Mvc.dll to reference version 3.0.
  3. Update all Web Application projects that reference System.Web.Mvc to reference version 3.0 and add references to System.Web.Helpers.dll and System.Web.WebPages.dll.
  4. Change all MVC 2 Web Application projects to be MVC 3 projects (this affects which version of the ‘Add View’ dialog you get etc)
  5. Update all MVC Web Application root Web.config files:
    1. Update references to System.Web.Mvc version 3.0.
    2. Add an assembly binding redirect entry for System.Web.Mvc.
    3. Add assembly and namespace references to System.Web.Helpers and System.Web.WebPages.
    4. Add the “ClientValidationEnabled” and “UnobtrusiveJavaScriptEnabled” settings to the <appSettings> element with value “false” if they were not already present (these settings can be used to control the unobtrusive client validation and unobtrusive Ajax features).
  6. Update all MVC Web Application views Web.config files (~\Views\Web.config as well as the views Web.config files for all Areas):
    1. Update references to System.Web.Mvc version 3.0
    2. Add a <configSections> entry required for Razor configuration in MVC
    3. Add the <system.web.webPages.razor> entry required for Razor support in MVC
    4. Add the “webPages:enabled” setting to the <appSettings> element with value “false” (required to prevent .cshtml or .vbhtml files in the Views folder from being directly accessible from a web browser)
  7. Add the following JavaScript libraries to the MVC Web Applications (only if they did not already exist):
    • JQuery 1.4.4 (JQuery-1.4.4.js, JQuery-1.4.4-vsdoc.js, jQuery-1.4.4.min.js)
    • jQuery UI 1.8.7 (jquery-ui.js, jquery-ui.min.js)
    • jQuery Validation 1.7 (jquery-validate.js, jquery-validate-vsdoc.js, jquery-validate.min.js)
    • Microsoft Ajax (MicrosoftAjax.js, Microsoft.Ajax.Debug.js)
  8. Overwrite MVC-specific JavaScript files in MVC Web Applications:
    • MicrosoftMvcAjax.js, MicrosoftMvcAjax.Debug.js, MicrosoftMvcValidation.js, MicrosoftMvcValidation.debug.js, jquery.unobtrusive-ajax.js, jquery.unobtrusive-ajax.min.js, jquery.validate.unobtrusive.js, jquery.validate.unobtrusive.min.js
  9. Add jQuery UI theme files (stylesheet and images)

This is an unsupported utility and there is a possibility that it might not work correctly for your solution. Specifically, the tool has the following limitations:

  • Read-only project files are not supported (make sure you check out your solution if you use source control)
  • Very long file paths might cause problems
  • Solutions with project files outside of the solution folder might cause problems
  • The tool will not upgrade your application code to account for any potential runtime breaking changes
  • Non-standard project files (e.g. missing MVC project type GUID) will not be handled correctly
  • Once again, VS 2008 solutions, MVC 1 or .NET 3.5 projects are not supported
  • The tool will also not modify any Web Sites in your solution

However, if you run into problems let me know and I will see if we can get them addressed.

[转载]ASP.NET MVC3 及其学习资源

mikel阅读(1034)

[转载]ASP.NET MVC3 及其学习资源 – haogj – 博客园.

今天,Scott 宣告了 ASP.NET MVC3,IIS Express, SQL CE4, Web Farm Framework, Orchard, WebMatrix 的发布。

Announcing release of ASP.NET MVC 3, IIS Express, SQL CE 4, Web Farm Framework, Orchard, WebMatrix

下载

如何开始 ASP.NET MVC3 的学习呢?Scott 在文章中介绍了一些学习资源,这里一起介绍一下。

当然,首先是 ASP.NET MVC3 的下载地址了。点击下载

然后,ASP.NET MVC3 源码下载,这是学习的最好资源。点击下载 ASP.NET MVC3 源码

升级

如果你需要从早期的版本升级到 ASP.NET MVC3 ,这是手动的升级步骤,manual upgrade steps in the release notes

太麻烦了?这里还有自动的升级工具,automated ASP.NET MVC 3 upgrade tool

学习示例

创建你的第一个 ASP.NET MVC3 程序,Build your First ASP.NET MVC 3 Application

还记得 PetShop 吗?,这次是一个音乐商店,一个完整的购物网站,现在已经是 2.0 版了。

与 PetShop 一样,也有购物车

这里提供了一个由 10 个部分组成的完成练习,Building the ASP.NET MVC 3 Music Store

完整的 PDF 手册可以从这里下载,点击下载手册

全部的源程序在这里,刚刚更新到 2.0 ,点击下载

[转载]NVelocity for ASP.NET MVC

mikel阅读(1090)

[转载]NVelocity for ASP.NET MVC – 阿不 – 博客园.

在我的这篇博文中,有这么一段话:“我一直在想,有没有办法可以单独限制View中的代码的访问权限,类似于trust level,只是这个trust level是用来限制模板中的代码。”。有读者johngeng问, 为什么要用trust level来锁住view,他不是很理解。我的本意是,希望在view中,开发人员只能写某一些特定功能的代码,调用某一些特定开放的API,对于大部分 安全级比较高的代码,比如读写文件等API或类库,不允许在view当中使用。这对于我们将模板开放出来,在线提供给我们的用户去修改的需求下是非常重要 的。而目前,不管WebForm还是Razor,都是非常自由的模板,在View能做的事情等同于Controller或其它地方所写的代码,这样 View就不允许开放出来由用户在线修改。

在相同的博文里面,还是那位读者johngeng提到它更喜欢$而不是@,由于我之前并不了解NVelocity,所以我误解为它是在说客户端开发包JQuery。现在看来,他说的应该就是NVelocity,也许他觉得此人不可教,他并没有直接回复我的疑问,这也只能怪自己知识面太窄了。悲伤

若不是最近在为项目添加多模板引擎的支持,或许我永远也无法得到以上两个问题的答案,而这两个答案都与NVelocity有关。虽然我平常肯定也见过NVelocity这个词,但到要选择除WebForm以外的模板引擎,我还是完完全全没有记起他,还是同事@浪子提 醒我NVelocity这个模板引擎值得一试。看了官方的语法介绍后,我不得不说它是一种非常简洁且实用的模板,同时又不失它的灵活性和安全性。我所指的 灵活性是它不像StringTemplate那样,限制的那么死,连个对象的函数都不允许调用。安全性方面又可以满足我希望模板上限制开发人员只能在模板 上调用指定的API。到目前为止,NVelocity仍然让我非常满意。

ASP.NET MVC切换视图引擎非常简单,在ASP.NET MVC1.0出来以后,MvcContrib就曾经提供了多种视图引擎的切换选择,但是在最近的版本中,我却始终没有找到相关的代码,应该是这些代码已经被移出去了,但它的介绍文档中还没有删掉相关的主题。还好在@重典童鞋的博客上找到了他从MvcContrib中提取出来的实现。 但是这个实现相对于MVC3来说,已经相对过时了,有些接口已经改变或被移除了,比如IViewLocator这个接口就已经不存在了。还有就是,它去掉 了原先支持的调用HtmlHelper扩展方法的功能,而我最重要的就是要支持扩展函数,因为我自定义了一些必须的扩展方法。下面我们就来看看 NVelocity for ASP.NET MVC几个类的详细情况:

NVelocityViewEngine

在 之前的实现中,直接实现了IViewEngine这个接口,查找View的路径是通过实现IViewLocator来定位。在MVC2当中,修改了这部分 的实现,MVC内部提供了VirtualPathProviderViewEngine这个模板方法类,在子类当中,我们中需要设置一下我们要查找的路径 格式,其它的事件就可以交给模板方法类来完成,这样一方面可以简化我们的实现,另一方面还可以和默认的路径查找方式统一。

同时,由于我使 用Nvelocity内置的相对文件路径的方式来查找模板,而使用VirtualPath的风格,因此在找到VirtualPath后,我们需要转换成实 际的物理路径,直接通过物理路径来加载模板内容,而内置的FileResourceLoader并不支持从物理路径加载模板,所以我们还要额外实现一下 FileResourceLoader,让支持从物理路径的加载方法。这两个类的代码如下:

NVelocityView

主要实现IView接口,实现Render方法来将模板和当前的上下文结合之后输出出来。这个类还实现了,IViewDataContainer好 像不是特别必要。NVelocity的Render也很简单,只是把所需要的对像塞到NVelocity执行的上下文当中,然后调用一下Merge方法就 OK了。这里要特别说明的是,在NVelocity模板上面,我们可以调用上下文对象的中的任何属性和方法,但是没有办法调用到对象上的扩展方法,这时 候,我们就需要借助NVelocity所提供的IDuck这个接口来提供扩展方法的支持,如下代码的:new HtmlExtensionDuck(context, this); 。完全代码如下:

ExtensionDuck

ExtensionDuck就是对IDuck接口的实现,它是我们需要提供扩展方法支持的Duck对象的基类。所有需要接供扩展方法的对象,通过继承该方法可以简化大部分的工作:

接下,我们就可以来实现一个HtmlExtensionDuck,指定一下,View中可以调用到HtmlHelper的哪些扩展方法,需要被开放的扩展方法可以在HTML_EXTENSION_TYPES中提供扩展方法所在的静态类名:

完整的NVelocity for ASP.NET MVC的实现就是以上几个类就可以完成。然后,我们就可以直接注册到系统中来。我们不需要重写任何Conroller,我们直接把ViewEngine注 册到MVC中来就可以被用到,也可以支持一个程序支持多种视图引擎共存的和谐场面。简单的注册代码放在Global.asax文件中:

详细的使用示例,下载附件查看详细。

最后总结一下,NVelocity确实是一种简单实用的模板引擎,特别是它的语法非常简洁,而且API的可扩展性还是挺强的。Razor的语法的基 本风格应该是有借鉴了它的语法风格。我现在虽然也很喜欢NVelocity,但如果不是特殊情况的特殊需要,在普通的ASP.NET MVC程序中,我还是会侧向于使用Razor。它更自由一点,由于是直接的C#编译支持,所以我们可以做任何的事情,这对于很多开发人员来说很重要。另一 个不可忽视的就是它的IDE支持,特别是代码提示确实是让人相当的舒服。

[转载]Android 解码Gif 图像并播放

mikel阅读(922)

[转载]Android 解码Gif 图像并播放 – Terry_龙 – 博客园.

Android 播放GIF之前就有过一篇文章是讲述如何使用GIF文件并播放。可以通过 这里 了解关于播放GIF的一种方法。

如果前面有了解过的朋友肯定知道这上面的做法比较麻烦,又要去分解图片,又要写各种麻烦的XML文件,有点郁闷,而且还带来的直接后果是一个比较多动作的GIF图片可能会将项目的体积变大,这点很多朋友都无法接受。不过这样的好处也显而易见,就是运行的速度会比你去解码的速度要快。

以下这种方法是需要解码,但是速度的话保证不了,可能开线程的时候没有处理好吧,以下面这张图片为例做解码播放:

首先,先编写一个GIF解码的帮助类,该类提供了几个操作GIF图片的方法,比如图片的初始化呀,切换图片呀,获得整个GIF的组合数量等等,由于代码量太多,这里就不列出来,后面会提供源码供大家参考,可于源码内找到该帮助类。

之后,编写一个用于可显示Gif 的组件,继承自View 并实现了Runable,代码如下:

package com.terry.gif;

import Android.content.Context;
import Android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class TypegifView extends View implements Runnable {
gifOpenHelper gHelper;
private boolean isStop = true;
int delta;
String title;

Bitmap bmp;

// construct – refer for java
public TypegifView(Context context) {
this(context, null);

}

// construct – refer for xml
public TypegifView(Context context, AttributeSet attrs) {
super(context, attrs);
//添加属性
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.gifView);
int n = ta.getIndexCount();

for (int i = 0; i < n; i++) {
int attr = ta.getIndex(i);

switch (attr) {
case R.styleable.gifView_src:
int id = ta.getResourceId(R.styleable.gifView_src, 0);
setSrc(id);
break;

case R.styleable.gifView_delay:
int idelta = ta.getInteger(R.styleable.gifView_delay, 1);
setDelta(idelta);
break;

case R.styleable.gifView_stop:
boolean sp = ta.getBoolean(R.styleable.gifView_stop, false);
if (!sp) {
setStop();
}
break;
}

}

ta.recycle();
}

/**
* 设置停止
*
* @param stop
*/
public void setStop() {
isStop = false;
}

/**
* 设置启动
*/
public void setStart() {
isStop = true;

Thread updateTimer = new Thread(this);
updateTimer.start();
}

/**
* 通过下票设置第几张图片显示
* @param id
*/
public void setSrc(int id) {

gHelper = new gifOpenHelper();
gHelper.read(TypegifView.this.getResources().openRawResource(id));
bmp = gHelper.getImage();// 得到第一张图片
}

public void setDelta(int is) {
delta = is;
}

// to meaure its Width & Height
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}

private int measureWidth(int measureSpec) {
return gHelper.getWidth();
}

private int measureHeight(int measureSpec) {
return gHelper.getHeigh();
}

protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(bmp, 0, 0, new Paint());
bmp = gHelper.nextBitmap();

}

public void run() {
// TODO Auto-generated method stub
while (isStop) {
try {
this.postInvalidate();
Thread.sleep(gHelper.nextDelay() / delta);
} catch (Exception ex) {

}
}
}

}

基础功能实现后。可通过view.start()开启GIF的播放,或者view.stop()停止GIF的播放,代码如下:

setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.Button01);
Button btn2 = (Button) findViewById(R.id.Button02);
final TypegifView view = (TypegifView) findViewById(R.id.gifView1);

btn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
view.setStop();
}
});

btn2.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
view.setStart();
}
});

显示效果:

源码参见:gifPlayer

[转载]Silverlight+WCF 实战-网络象棋最终篇之解决重复的消息提示-状态重置(九)

mikel阅读(804)

[转载]Silverlight+WCF 实战-网络象棋最终篇之解决重复的消息提示-状态重置(九) – 路过秋天 – 博客园.

上节留下的问题:

在上一节:Silverlight+WCF 网络象棋 终极篇 解决重复的消息提示(八) 中,我们解决了重复登陆时产生的多次消息的重复提示。

不过由此优化产生的另一个问题:全局只有一个实例,在来回的切换房间或进出时,需要重置状态,我们这节来解决这个问题。

在上节的,我留下了几行这样的注释代码:

//loginObj.Reset();
//roomObj.Reset();
//indexObj.Reset();

本节就顺路把这三个注册的方法给实现了:

1:loginObje.Reset()方法的实现,进入Login.xaml.cs中:

public void Reset()
{
btnLogin.IsEnabled
= true;
}

就一行,把不可用的按钮重置为可用。

2:roomObj.Reset()方法的实现,进入Room.xaml.cs中:

public void Reset()
{
game.Reset();
App.client.GetRoomListAsync();
}

代码很简洁,第一行,把游戏房间的状态重置为初始状态,然后重新获取房间的状态。

代码分解:game.Reset()方法,我们进入到Game.cs中添加Reset方法实现如下:

public void Reset()
{
if (GameRoomList == null)
{
CreateGameRoom(
20);
}
foreach (GameRoom item in GameRoomList)
{
if (item.BlackPlayer != null || item.RedPlayer != null)
{
item.BlackPlayer
= null;
item.RedPlayer
= null;
item.IsGaming
= false;
item.ReDraw();
}
}
}

把每一个房间重新重置为初始状态了。

3:indexObj.Reset()方法的实现,进入Index.xaml.cs中:

public void Reset()
{
chessControl.Reset();
onlineUserControl.Reset();
chessManualControl.Reset();
eventButtonControl.Reset();
chatControl.Reset();
}

这里代码是比较简单,不过接下来要做的事就多了,每个控件都要去实现一下,当体力活了。

下面为每一个控件实现状态重置方法:

A:棋盘及棋子的重置:chessControl.Reset();

public void Reset()
{
chess.Reset();//这个已经实现了的。
}

因此内部就调用象棋类的重置,分解为:

B:房间在线用户的重置:onlineUserControl.Reset();

public void Reset()
{
App.client.GetPlayerListAsync(App.player.RoomID);
}

重新获取一次用户即可。

C:棋谱的重置:chessManualControl.Reset();

public void Reset()
{
timer.Stop();
moveStepIndex = 0;
tempIsCanMove = false;
App.chessManualPlaying = false;
App.stepList.Clear();
lbChessManual.Items.Clear();
}

D:在线聊天的重置: chatControl.Reset();

public void Reset()
{
lbMsg.Items.Clear();
}

4:回去把那三行注释掉的代码给开启了。

OK,一切就绪,最后运行看下效果,随便点点,运行情况良好,截几张图:

a:登陆

b:进到房间中

c:接着退出系统

d:换个名称重新登陆

e:重新登陆后进房间的界面

OK,本节就介绍到这里了。

[转载]分支在版本树中的应用(使用subversion)

mikel阅读(1050)

[转载]分支在版本树中的应用(使用subversion) – 登山耐危路,踏雪耐危桥 – 博客园.

场景

项目已上线,需不断维护。要求加入全市统一的功能,并马上上线,功能已经开发并测试,目前正在修改一些小的bug。但是新需求在不断引入:修改周期长,由于新需求还未完全实现并测试,bug修正后无法马上发布新版本。

产品化的软件,可能会有多版本存在,其中部分代码需要不断同步。

这两种应用场景,都可以考虑建立分支版本,使用版本控制工具的自动合并功能,更好的实现配置管理。

基本概念

REVISION 修订版本号

HEAD 版本库中的最新版本

下面三个是本地路径:

BASE 如果发生本地修改,BASE版本就是本地未修改版本

COMMITEED BASE之前最后修改的版本

PREV 最后修改版本之前的版本,技术上也叫COMMITEED-1

拷贝修改合并方案

版本库和修订号

全局修订号,一个修订号对应一个版本树,commit之后产生全局修订号,本地工作拷贝为混合版本,update之后是本地工作拷贝为最新的全局修订号。

Commit之后进入混合修订版本。Pull push分离原则

常规工作方式:

svn import 导入项目到svn

svn checkout 得到工作拷贝

建立分支

使用svn copy命令或工具创建

建立分支后的版本变化

分支合并

注意:每次合并,提交都建立日志。选择好合并到哪个工作拷贝

主干合并到分支

范围合并或者版本树合并(最后一个)

方法1:

指定主干版本的版本范围,此范围内被合并到分支

方法2

两个不同版本树合并

选择分支指定版本号(最后一次同步版本)到最新的主干版本直接版本,此版本范围内的版本被同步

解决冲突:使用版本库版本或者使用本地版本,或者编辑修改

分支合并到主干

Reintegrate brache或者不同版本树合并

[转载]借助HttpCombiner让你的网站加速

mikel阅读(1053)

[转载]借助HttpCombiner让你的网站加速 – 三桂 – 博客园.

上一篇 < 利用Microsoft Ajax Minifier在服务器端对静态资源进行自动化压缩 > 得到不少有意义的交流和建议,最近也在不停的尝试做一些网站优化的工作,我会陆续的写一些或者翻译一些优化方面的文章跟大家交流,一方面提供给有需要的朋友一些参考,另一方面也希望得到高手们的指点。

经过上一篇文章介绍的压缩步骤,我们的资源文件(没指明则特指js,css静态资源文件)已经减肥成功,保持了苗条的身材,这样从服务器端传输到客户端也没那么费劲了,初步获得小成功,但是根据 雅虎网站页面性能优化的34条黄金守则 提 供给我们的建议,让优化工作做得更进一步,比如一个页面引入了4个css文件,5个js文件(这个数目还算过得去,也许还会更多),这样页面载入的时候就 会产生9个请求,加之js加载又是阻塞加载的方式,这样也会造成一定程度上的性能损伤。寻思了一会在网上找到这么一个文件 HttpCombiner.ashx,接下来介绍它能帮我们做的事情。

HttpCombiner.ashx是一个http处理程序,通过它能够合并多个CSS,JavaScript或者url成为一个响应让页面载入加速.同时它可以合并,压缩并缓存响应,这样就使得我们的应用程序更快的加载和具备更好的扩展性。

用 一个大的JavaScript或者CSS文件替代多个小体积的Javascript和CSS文件这是一个很好的实践,可以获得更好的可维护性,但是在网站 性能方面会产生一定的影响(这里指的是随着文件体积的增大,随之消耗服务器的内存也会增加)。尽管你应该把Javascript代码单独写成小支的文 件,CSS文件拆分成小块,但是当浏览器请求这些文件时,会产生同等数量的http请求。每个http请求都会产生一次从你的浏览器到服务器端网络往返过 程,并且导致推迟到达服务器端和返回浏览器端的时间,我们称之为延迟。因此,如果你有4个Javascript和3个css文件在页面中被加载,你浪费掉 了7次因网络往返过程产生的时间。在美国,延迟平均是70毫秒,这样你就浪费了7*70 = 490毫秒,大致延迟了半秒的时间。在美国之外的国家访问你的页面,平均延迟大约是200毫秒,这意味着你的页面有1400毫秒的时间是在等待中度过。浏 览器在你的CSS和Javascript文件完全加载完成之前是不能很好的渲染你的页面的。因此越多的延迟让你的页面载入越慢。

下图显示每个请求的延迟造成页面加载时显著的延误

你可以通过使用CDN加速来减少等待时间.阅读我前一篇文章关于使用CDN. 然而,一个更好的解决方案是使用一个HttpHandler来合并多个文件成一个文件一次性输出.因此,你只要将多个<script>或者<link>标签合并成为一个并将他们指向HttpHandler,指定哪些文件需要作为一次响应传输到浏览器段.这样就减少了请求次数以及消除因其造成的延迟This saves browser from making many requests and eliminates the latency.

通过上图你可以看见通过合并多个JavaScripts和CSS文件为一所带来各方面的提升。

在一个电影的web页面中你会看到许多JavaScripts引用

代码

<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jquery.js"></script>
<script type ="text/javascript" src="http://www.msmvps.com/Content/JScript/jDate.js"></script>
<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jQuery.Core.js"></script>
<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jQuery.Delegate.js"></script>
<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jQuery.Validation.js"> </ script >

你可以用Http Handler通过scripts的设置来实现将多个单独的 <script>标签合并成一个:

<script type="text/javascript"  src="HttpCombiner.ashx?s=jQueryScripts&t=text/javascript&v=1"></script>

HTTP Handler 通过配置文件中设置的名称读取所有文件合并成一次响应传输到客户端,通过gzip压缩响应节省了宽带使用.此外还会生成合适的缓存头来缓存响应的浏览器缓存,因此,浏览器不会再次向服务器发送请求.

在查询字符串中,’s’指明配置文件中的设置名,’t’为文件的内容类型,’v’为版本号.一旦响应被缓存,如果你更改了配置中任何文件,你将不得不增加参数’v’的值来让浏览器再次下载服务器端最新的响应:

<link type="text/css" rel="stylesheet" href="HttpCombiner.ashx?s=CommonCss&t=text/css&v=1"></link>

web.config中的设置如下:

代码<appSettings>
<add key=”JQueryScripts” value=”~/Content/JScript/JQuery.js,
~/Content/JScript/jDate.js,
~/Content/JScript/jQuery.Core.js,
~/Content/JScript/jQuery.Delegate.js,
~/Content/JScript/jQuery.Validation.js”
/>
<add key=”CommonCss” value=”~/App_Themes/Default/Theme.css,
~/Css/Common.css,
~/Controls/Grid/grid.css”
/>
</appSettings>

我已经写好一个测试网站来演示如何使用HttpCombiner.网站包含2个CSS和2个JS文件. default.aspx文件中<link>和<script>标签2个请求都是指向了HttpCombiner.ashx文件 .

下面就是Default.aspx的内容:

就如你所见,页面中 <link >和<script>标签 都同时指向了 HttpCombiner.ashx,并且所带的参数’s’就是web.config文件中定义的2组设置 :

该处理程序如何工作:

  • 首先通过传入的参数”s”获得设置名称
  • 然后根据设置名称获得web.config中定义的文件名称(通过特定的分隔符分隔开)
  • 读取每单个文件然后存储到缓冲区
  • 通过gzip压缩缓冲区中的数据
  • 发送压缩后缓冲区中的数据到浏览器端
  • 已压缩后缓冲区的数据使用ASP.NET缓存模块缓存起来以便在频繁请求同一个设置的情况下直接访问缓存而不必从文件系统或者外部URL读取文件

该处理程序带来的好处:

  • 可以节约因网络延迟造成的时间.如果一次性设置的文件越多,节省的网络延迟性时间越多,同时得到的性能提升就越可观.
  • 因为缓存了所有压缩后的响应数据,这样节省了反复执行从文件系统中读取并压缩的步骤,提升了应用程序的伸缩性.

首先处理程序会从QueryString中获取setName,contentType,version三个关键参数:

如果设置的文件已经被缓存起来,它将直接被写入到缓存当中去,否则它们会从MemoryStream中分别被加载。如果浏览器支持压缩输出的话,MemoryStream会使用GZipStream进行压缩

当合并所有文件之后并压缩,合并的二进制流被缓存起来便与频繁的访问可以直接从缓存中读取.

GetFileBytes方法主要是根据文件路径或者http url读取文件并返回二进制。因此您可以使用你站点的虚拟路径或者使用外部站点Javascript/CSS的url

WriteBytes 方法很巧妙,它会基于二进制流是否为压缩而生成一个合适的header,并设置浏览器缓存头让浏览器缓存服务器端的响应

目前发现部署到运行环境中会出现异常(远程主机关闭了连接。错误代码是 0x80072746。),将上面图片中的代码最后2行替换成

response.Flush();
if (response.IsClientConnected)
response.OutputStream.Write(bytes, 0, bytes.Length);
response.End();
另外就是注意HttpCombiner.ashx文件建议直接放在跟.js或者.css同一个目录下(排除你的项目有统一的路径处理方案),不然会出现路径引用问题

如何使用该文件:

  • 包含HttpCombiner.ashx在你的项目中
  • 在你的web.config的 <appSettings>定义需要设置的文件节点
  • 更改你网站的 <link> <script> 标签指向HttpCombiner.ashx 如下面的格式:
    HttpCombiner.ashx?s=<appSettings里设置的节点名>&t=<文件类型>&v=<版本号>

本文是在优化实际项目中的总结,解决方案源自网上并加以翻译和整理而成,有不当之处或者建议请大家一起讨论。

原文连接:http://www.codeproject.com/KB/aspnet/HttpCombine.aspx 下载示例

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

补充:

#6楼 提供的combres组件很有价值,比本文提供的解决方案更有参考性,大家可以猛击连接前往围观,博客园也有相关的介绍文章,这里给出几个连接

http://www.codeproject.com/KB/aspnet/combres2.aspx(codeproject上的原文)

http://www.cnblogs.com/shanyou/archive/2010/04/03/1703597.html(本文评论部分也有很多亮点)

http://www.cnblogs.com/liping13599168/archive/2010/04/04/1704154.html(本文对combres部分源码也进行了分析)
#7楼 分享的另外一个关于image sprite的组件,早之前重典有写博文介绍过,在ASP.NET中自动合并小图片并使用CSS Sprite显示出来

[转载]神奇的Redis

mikel阅读(1103)

[转载]神奇的Redis – lovecindywang – 博客园.

Redis按照官方的定义是一个开源的,高级的键值存储。本文就想扩展开介绍,高级和存储两点。

为什么高级,咱们列一下它的基本特性:

  1. 每秒10万+的读,8万+的写(是不是有点吹?)
  2. 操作原子性(还支持把一组命令合并为一个原子操作)
  3. 多种基元数据类型的支持(hash/list/(sorted)set/string)
  4. 支持过期(可以用作缓存)
  5. 支持主从架构(多级层次)
  6. 支持管道(一次性发送多个命令执行)

以及丰富的API:

  1. 提供丰富有关key的操作命令
    1. 移动/排序/删除/重命名/获取类型/是否存在
    2. 获得符合某个表达式的所有键
    3. 设置和删除过期时间
    4. 随机获得一个
  2. 提供丰富的list结构操作命令
    1. 获取列表长度
    2. 获取列表中一段元素
    3. 移除一个或若干项
    4. 从最后开始移除若干项
    5. 追加一个项
    6. 为列表最前加入一项
    7. 移除并获取第一项
    8. 移除并获取最后一项
    9. 按照索引号获取或设置项
    10. 移除A列表最后一项追加到B列表
    11. 在列表中某个项(根据值)前或后加入项
    12. 获取项的索引号
  3. 提供丰富的string操作命令
    1. 设置(允许有过期)和追加值
    2. 获取值的一段
    3. 递减和递增
    4. 减少和增加
    5. 设置新值并且返回老的值
    6. 一次获取和设置多个键的值
    7. 获取值的长度
  4. 提供丰富的set结构操作命令
    1. 增加
    2. 批量增加
    3. 交集(并且保存到另外一个集合)
    4. 并集(并且保存到另外一个集合)
    5. 从一个移除加入另一个
    6. 获取长度
    7. 随机获取(并移除)
    8. 是否存在
    9. 获取所有
  5. 提供丰富的hash结构操作命令
  6. 提供丰富的sorted set操作命令
  7. 支持主从(并且支持多层)
  8. 提供发布订阅功能
    1. 监听某个信道(符合某个表达式)的消息
    2. 向某个信道发布消息
  9. 提供事务功能
    1. 开始事务块
    2. 抛弃之前的所有命令
    3. 执行事务块中的所有命令
    4. 监视某个键的事务执行
  10. 其它
    1. 授权
    2. 改变数据库
    3. 在线配置
    4. 异步刷新数据到磁盘
    5. 同步刷新数据到磁盘
    6. 获取状态信息
    7. 获得调试信息
    8. 删除所有数据
    9. 关闭
  11. 支持SET if Not eXists(可以用作分布式锁)

这么多API总结起来:

  1. 如此多的基于服务端的命令可以实现各种各样的逻辑(这里重点突出服务端这个词,虽然我们知道很多情况下可以get后再set,或是getall后再setall,但是这效率无法和服务端直接操作相比)
  2. 很多命令都组合成了原子命令(这是很重要的,使得我们不需要在客户端做分布式锁)
  3. 创新的list/set/sorted set存储结构,比单纯的key/value丰富多了

接下来说说存储这个词,很多人把它和memcached来比较,其实Redis的配置和架构是如此灵活,我们想怎么用就怎么用,想怎么调优就怎么调,可以为我们的应用来定制存储架构:

  1. 设置数据刷新到磁盘的条件(几秒内几次改动)
  2. 设置数据刷新到磁盘的方式(总是/每秒/不刷新)
  3. 设置虚拟内存(最大内存/页大小/页数量)
  4. 设置限制(内存占用/并发数/端口/是否后台)

对于用作缓存还是存储,数据的安全性等我们都可以根据不同的应用来调整。那么Redis可以用作哪些应用呢?

  1. 分布式缓存
  2. 分布式锁
  3. 消息队列
  4. 全文索引
  5. 和业务逻辑绑定的存储

对于.NET客户端来说,目前ServiceStack.Redis是不错的选择,其中也有一些不错的例子:

  1. 发布订阅
  2. 分布式锁
  3. 博客的例子

更多信息,参阅:

  1. http://blog.mjrusso.com/2010/10/17/redis-from-the-ground-up.html
  2. http://simonwillison.net/static/2010/redis-tutorial/
  3. http://antirez.com/

Mongodb作为大数据量的存储,把Redis作为中数据量的业务热点的存储确实是不错的方案。

[转载]android开发我的新浪微博客户端-登录页面UI篇(4.1)

mikel阅读(918)

[转载]android开发我的新浪微博客户端-登录页面UI篇(4.1) – 遇见未知的自己 – 博客园.

首先回顾一下功能流程当用户开启软件显示载入页面时程序首先去SQLite库查询是否已经保存有用户的新浪微博的UserID号、Access Token、Access Secret的记录如果没有一条记录那么跳转到用户授权功能页面,这个已经由上面两篇文章实现了,如果有记录那么页面跳转到用户登录页面,也就是本篇以及 下篇要实现的功能,本篇讲UI的实现,本项目支持多微博账号了,也就是用户可以设置多个微博账号,登录的时候选择其中的一个登录,具体效果如上图,新建名 LoginActivity.java的Activity并且在AndroidManifest.xml中进行相应配置,这个页面就是我们要实现的用户登 录页面。

看上面的效果,首先页面分3部分实现,背景部分、底部菜单部分、用户选择以及头像显示部分,首先在res/layout的目录下新建名为login.xml的layout,然后根据页面显示要求编写如下的布局控制:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:Android=”http://schemas.android.com/apk/res/android”
android:id
=”@+id/layout”
android:orientation
=”vertical”
android:layout_width
=”fill_parent”
android:layout_height
=”fill_parent”>
<ImageView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:src
=”@drawable/logo_s”
android:layout_marginTop
=”5dip”
android:layout_marginLeft
=”5dip”>
</ImageView>
<RelativeLayout
android:layout_width=”fill_parent”
android:layout_height
=”fill_parent”>
<RelativeLayout
android:id=”@+id/iconBtn”
android:layout_width
=”90px”
android:layout_height
=”80px”
android:background
=”@drawable/icon_selector”
android:layout_above
=”@+id/selectLayout”
android:layout_centerHorizontal
=”true”
android:layout_marginBottom
=”20dip”>
<ImageView
android:id=”@+id/icon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_centerInParent
=”true”>
</ImageView>
</RelativeLayout>

<RelativeLayout
android:id=”@+id/selectLayout”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_centerInParent
=”true”>
<EditText
android:id=”@+id/iconSelect”
android:layout_width
=”200px”
android:layout_height
=”wrap_content”
android:maxLength
=”10″
android:paddingLeft
=”20px”
android:editable
=”false”
android:enabled
=”false”
android:textSize
=”13px”
android:background
=”@drawable/input_over” >
</EditText>
<ImageButton
android:id=”@+id/iconSelectBtn”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_marginRight
=”1.0dip”
android:layout_alignTop
=”@+id/iconSelect”
android:layout_alignRight
=”@+id/iconSelect”
android:layout_alignBottom
=”@+id/iconSelect”
android:background
=”@drawable/more_selector” >
</ImageButton>
<ImageButton
android:id=”@+id/login”
android:layout_width
=”40px”
android:layout_height
=”40px”
android:layout_marginLeft
=”5dip”
android:layout_alignTop
=”@+id/iconSelectBtn”
android:layout_toRightOf
=”@+id/iconSelectBtn”
android:layout_alignBottom
=”@+id/iconSelectBtn”
android:background
=”@drawable/btn_in_selector” >
</ImageButton>
</RelativeLayout>

<RelativeLayout
android:layout_width=”fill_parent”
android:layout_height
=”44dip”
android:layout_alignParentBottom
=”true”
android:background
=”#BB768e95″>
<LinearLayout
android:id=”@+id/addLayout”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:layout_alignParentLeft
=”true”
android:gravity
=”center”
android:layout_marginTop
=”3px”>
<ImageButton
android:id=”@+id/addIcon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:background
=”@drawable/add_selector”>
</ImageButton>
<TextView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#ffffff”
android:textSize
=”12px”
android:text
=”添加账号”>
</TextView>
</LinearLayout>
<LinearLayout
android:id=”@+id/exitLayout”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:layout_centerInParent
=”true”
android:gravity
=”center”
android:layout_marginTop
=”3px”>
<ImageButton
android:id=”@+id/exitIcon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:background
=”@drawable/exit_selector”>
</ImageButton>
<TextView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#ffffff”
android:textSize
=”12px”
android:text
=”退出软件”>
</TextView>
</LinearLayout>
<LinearLayout
android:id=”@+id/delLayout”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:layout_alignParentRight
=”true”
android:gravity
=”center”
android:layout_marginTop
=”3px”>
<ImageButton
android:id=”@+id/delIcon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:background
=”@drawable/del_selector”>
</ImageButton>
<TextView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#ffffff”
android:textSize
=”12px”
android:text
=”删除账号”>
</TextView>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>

正对上面的login.xml的layout进行一下说明,背景部分前面已经讲过了这里也就不重复。

底部菜单实现,原本我是采用GridView实现的非常的方便但是后来由于显示位置不好控制改成了用RelativeLayout和LinearLayout嵌套的方式,实现的比较土但是达到了显示需求,首先是一个最外面的RelativeLayout目的是用来实现底部对齐显示,并且把这个RelativeLayout的背景设置为浅蓝色半透明的效果,关键这2行:android:layout_alignParentBottom=”true”和android:background=”#BB768e95″。然后是在RelativeLayout内部添加3个LinearLayout分别是用来显示添加账号退出软件删除账号3个功能按钮菜单,并且分别设置为左对齐、居中对齐、右对齐,3个LinearLayout都设置为垂直布局android:orientation=”vertical”,然后每LinearLayout添加相应的图片和文字。

用户选择以及头像显示部分,这块分成3小块,用来显示用户头像的ImageView、用来显示用户名字并且点击可以出现选择列表的EditText、用来 点击进入当前选择用户首页的功能按钮ImageButton,这3小块的布局实现也是采用elativeLayout和LinearLayout相互嵌套 配合的方式实现的具体参考login.xml。这里重点说说这个账号选择列表弹出窗口的实现,当点击下拉箭头按钮的时候弹出并显示,这个是用Dialog 控件实现,首先准备好圆角的半透明背景图mask_bg.png然后添加到res/drawable-mdpi文件夹下,接着自定义一个Dialog样式 文件,在res/values目录下新建名为dialogStyles2.xml的resources文件,在用户授权验证页面的时候我们也自定义过类似 的Dialog的样式,具体解释可以参考前面的户授权验证页面功能,内容如下:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<style name=”dialog2″ parent=”@android:style/Theme.Dialog”>
<item name=”android:windowFrame”>@null</item>
<item name=”android:windowIsFloating”>true</item>
<item name=”android:windowIsTranslucent”>false</item>
<item name=”android:windowNoTitle”>true</item>
<item name=”android:windowBackground”>@drawable/mask_bg</item>
<item name=”android:backgroundDimEnabled”>true</item>
</style>
</resources>

接下来还需要定义选择列表的layout,新建名为dialog2.xml的layout文件,内容如下:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:padding
=”4dip”>
<ListView
android:id=”@+id/list”
android:layout_width
=”240px”
android:layout_height
=”220px”
android:divider
=”#f1f2f2″
android:dividerHeight
=”1px”
android:layout_margin
=”5px”
android:background
=”#ffffff”
android:cacheColorHint
=”#00000000″>
</ListView>
</LinearLayout>

完成了layout和样式文件的编写,接下来就是把dialogStyles2.xml样式文件和dialog2.xml的列表layout用起来,当点击id为iconSelectBtn的ImageButton时显示用户选择窗口,在LoginActivity的onCreate方法中添加如下代码:

代码

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);

LinearLayout layout=(LinearLayout)findViewById(R.id.layout);
//背景自动适应
AndroidHelper.AutoBackground(this, layout, R.drawable.bg_v, R.drawable.bg_h);

ImageButton iconSelectBtn=(ImageButton)findViewById(R.id.iconSelectBtn);
iconSelectBtn.setOnClickListener(
new OnClickListener(){
@Override
public void onClick(View v) {
View diaView
=View.inflate(LoginActivity.this, R.layout.dialog2, null);
dialog
=new Dialog(LoginActivity.this,R.style.dialog2);
dialog.setContentView(diaView);
dialog.show();

……
}

});

到这里登录的UI部分就实现的差不多了,剩下的都是一些功能部分代码用来实现从SQLite中账号列表的获取,以及点击选择等交互操作等,这些在下一篇中来继续的讲。

[转载]SWF文件格式和ABC代码混淆工具的开发 (一) - 出发点和目标

mikel阅读(1179)

[转载]SWF文件格式和ABC代码混淆工具的开发 (一) – 出发点和目标 – Tony Huang 的编程园地 – 博客园.

在2010年11月28日,我在盛大举办的WeDoSwf会议上,我做了一个演讲,主题就是关于Swf的文件格式和Abc文件的混淆。 最近一个多月的时间里面,各种零零总总的事情特别多,一直没有时间把这个东西整理好放到博客中。 首先呢,把我的演讲的视频的ppt放上来: 视频: http://v.ku6.com/show/MwjMgfhEgUFoiZ.html PPT: http://www.slideshare.net/swfsh/swfabc 然后呢,经过我们的努力,我们已经将这个东西做成了一个产品,有兴趣的朋友可以去我们的公司主页上下载试用。 Ok, 接下来切入正题:

出发点和目标

现在游戏行业已经越来越激烈,竞争对手之间的不正当竞争手段也越来越恶劣。 而现在的游戏的内核已经越来越重要,由于Flash的局限性,每个厂商都都会设计一些高性能的算法以支持复杂游戏的流畅运行。 在这同时,由于Flash和Web环境的特点,网页游戏的外挂简直泛滥到了一定的程度。 所以,我们加密Swf文件要达到如下的几个目的:

  • 防止游戏中的高性能算法被他人盗用
  • 防止游戏的客户端成为外挂编写者的参考资料
  • 防止游戏被破解后,广泛传播,却不能给开发者带来合理的收益

所以,我们不能任由他人践踏我们的知识产权。 现在在市场上,最流行的Swf反编译软件主要有两款:

  • 硕思闪客精灵说来惭愧,我是这款软件的正版用户。这款软件应该是市面上用户界面最友好,使用面积也最广的Flash破解软件了。个人认为他的主要强项在于资源文件的破解。它的反编译引擎比较傻瓜,依葫芦画瓢,所以我们插入的混淆代码能起到很好的作用。
  • ASVASV也是市面上非常流行的反编译软件。它的侧重点恰恰相反,在于AS代码的反编译上面,它反编译出来的代码可读性非常强,如果swf是采 用Debug编译的,基本上能够反编译几乎完全相同的代码。试用我们的方法进行混淆了以后,用ASV打开文件,就会发现,它根本无法正常识别AS脚本。

所以,我们加密的目标也就是要保证,这两款软件的最新版本也无法破解我们的软件,即:

  • 硕思闪客精灵 5.6
  • ASV 2010/6

效果

直接上图是最给力的,先把我们的加密效果发布出来大家围观一下吧: