人生是一场不能存盘的RPG,我只能尽量多搞几个Screenshot

August 31, 2006

把页面内容作为Email发出

Filed under: ASP.NET

思路:在button的client click中把页面的内容存到一个hidden filed中,在server端的click中读取并发送
asp:Button ID=”Button_SendMail” runat=”server” Text=”SendEmail” OnClientClick=”CellPostBack();” OnClick=”Button_SendMail_Click”

function CellPostBack()
{
var result = document.getElementById(”result”);
var hiddenInfo = document.getElementById(”hiddenInfo”);
//alert(result.innerText);
//hiddenInfo.value = result.innerHTML;
}
protected void Button_SendMail_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.hiddenInfo.Value))
this.SendMail(this.hiddenInfo.Value);
}
private void SendMail( string body)
{
SmtpClient smtpClient = new SmtpClient();
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress(”aloneplayer@gmail.com“, “aLONEPLayer”);

smtpClient.Host = “XXXXX”;
//smtpClient.Port = 25;
message.From = fromAddress;
message.To.Add(”aloneplayer@gmail.com“);
message.Subject = “Hi, I’am Riven”;
message.IsBodyHtml = true;
message.Body = body;
smtpClient.Send(message);
}
还需要关闭Asp.net对页面内容的校验
<pages validateRequest=”false”/>

ASP.NET Design Templates

Filed under: ASP.NET

http://msdn.microsoft.com/asp.net/reference/design/templates/default.aspx

Database Modeling Excel

Filed under: 技术资源

同事写的生成数据库脚本的Excel,非常实用.
主要功能:
1.填写Excel表格,生成数据库脚本.
2.将数据库结构导入Excel.

http://www.codeplex.com/Wiki/View.aspx?ProjectName=dbmodelexcel

August 30, 2006

ASP.NET Themes and Skins

Filed under: ASP.NET

ASP.NET Themes and Skins Overview(MSDN)

Theme and StyleSheetTheme
http://blogs.effectivexaml.net/DaveWheeler/2005/10/theme-and-stylesheettheme.html

What is a StyleSheetTheme?
http://weblogs.asp.net/vimodi/articles/WhatIs_StyleSheetTheme.aspx

A Look at Themes
http://www.gridviewguy.com/ArticleDetails.aspx?articleID=151

1.Theme
Theme由位于一个特殊的路径下的skin,css,image等资源构成,App_Themes下的每一个
foleder包含一个Theme.

2.Theme的作用域:
page theme
Create a new folder named App_Themes in your Web site.
global theme
iisdefaultroot\aspnet_client\system_web\version\Themes

If an application theme has the same name as a global application theme, the page theme takes precedence.

3.Theme的使用:
通过web.config使用
<system.web>
<pages theme=”<ThemeName>”/>
<system.web>

<system.web>
<pages StyleSheetTheme=”Themename” />
</system.web>
或通过代码实现:
void Page_PreInit()
{
Page.Theme = profile.XXX;
Page.Theme = “Green”;
}

4. Theme and StyleSheetTheme的区别:
Simply put, the Theme is applied AFTER the properties are applied to the server-side control,
which means that the settings in the Theme override those of the control. A StyleSheetTheme
is applied BEFORE the properties from the server-side control, and are therefore overridden
by the properties on the control.

For example if StyleSheetTheme contain following default Label skin.
<asp:Label runat=”server” Text=”StyleSheetLabel” Font-Size=”Small” BackColor=”Red” ></asp:Label>

and Page Which has StyleSheetTheme and Theme defiened contain a Label contol as
<asp:Label runat=”server” Text=”PageLabel” Font-Size=”X-Large” ></asp:Label>

and Theme contain following default label skin.
<asp:Label runat=”server” Text=”ThemedLabel” ></asp:Label>

Then the resultant Label shown will look like.
<asp:Label runat=”server” Text=”ThemedLabel” Font-Size=”X-Large” BackColor=”Red” ></asp:Label>

2.Skin
.skin文件包含了一些control属性的定义,如:
skin分为default skin和named skin
default skin被用于每一类control,
<asp:button runat=”server” BackColor=”lightblue” ForeColor=”black” />

control通过SkinId属性来使用named skin,同类control的不同实例可以使用不同的named skin
<asp:imagebutton runat=”server” Imageurl=”Images/button-login.gif” skinid=”login” />
<asp:imagebutton runat=”server” id=”LoginButton” CommandName=”Login” AlternateText=”login” skinid=”login” CssClass=”button”/>
Skin和CSS的比较:
Skin可以用来设置Control的属性,如Style,CSS无此功能.
二者可以协同工作,如,设置Textbox的外观有两种等效的做法:
1.使用Skin来设置control property
In Default.skin:
<asp:TextBox runat=”server” BackColor=”#F7DE8A” BorderColor=”#933126″ BorderStyle=”Solid” BorderWidth=”1px” />

2.使用Skin + CSS
In Styles.css: .textBox {border:1px solid #933126; background-color:#F7DE8A;}
In Default.skin: <asp:TextBox runat=”server” CssClass=”textBox” />

JavaScript Toolbox

Filed under: 技术资源

http://www.mattkruse.com/javascript/

August 24, 2006

Using SQL server to store asp.net session

Filed under: ASP.NET

1.运行%windir%\Microsoft.NET\Framework\version\InstallPersistSqlState.sql
It will create a database named “ASPState”

We should config the permission for asp.net process in this database.

2. Modify the web.config
<system.web>
<sessionState mode=”SQLServer” sqlConnectionString=”data source=servername;user id=uid;password=pwd” cookieless=”false”
timeout=”30″ stateNetworkTimeout=”20″/>
</system.web>

stateNetworkTimeout configuration setting is used to define the time, in seconds, that the ASP.NET Web
application will wait for the state server to respond to network requests.
By default, this time is 10 seconds.

3. If we using two IIS server or more, we need setup the same machine key in the web.config on those IIS
Sample:
<system.web>
<machineKey validation=”SHA1″ validationKey=”
F3690E7A3143C185AB1089616A8B4D81FD55DD7A69EEAA3B32A6AE813ECEECD28DEA66A
23BEE42193729BD48595EBAFE2C2E765BE77E006330BC3B1392D7C73F” />
</system.web>

! How to create a machine key
http://support.microsoft.com/?id=312906

4.所有要放入session的class必须Serializable,且尽量小.

开发asp.net应用的两条经验

Filed under: ASP.NET

1.不要把session保存在进程的内存中.
有n种可能会导致进程中的session丢失:对web.config和global.asx进行病毒扫描,修改bin目录的内容,
asp.net的预编译.
更重要的是如果想使用多台web server,就决不能把session放到进程中

因此,所有要放入session的class必须可serialize,且尽量小.

2.一开始就使用https,以免后来才发现程序因为安全因素不能执行.

August 19, 2006

PetShop的Order和Message Queuing

Filed under: 代码学习

MSMQ与XML Web Services和.Net Remoting一样,是一种分布式开发技术。但是在使用XML Web Services或
.Net Remoting组件时,Client端需要和Server端实时交换信息,Server需要保持联机。
MSMQ以异步的方式和Server端交互,不用担心等待Server端的长时间处理过程。
在Server离线的情况下工作,将Message临时保存在Client端的消息队列中,以后联机时再发送到Server端处理。

在.Net环境下编写简单的Message Queue程序

安装Message Queuing Services
Control Panel->Add/Remove Programs->Add/Remove Windows Components安装MSMQ。

PetShop中的MesageQueuing

1. Factory class, create order Messaging implementation specified from the configuration file.

PetShop.MessagingFactory.QueueAccess
{
private static readonly string path = ConfigurationManager.AppSettings[”OrderMessaging”];

private QueueAccess() { }

public static PetShop.IMessaging.IOrder CreateOrder()
{
string className = path + “.Order”;
return (PetShop.IMessaging.IOrder)Assembly.Load(path).CreateInstance(className);
}
}

2. PetShop.IMessaging.IOrder

public interface IOrder
{
OrderInfo Receive();

OrderInfo Receive(int timeout);

void Send(OrderInfo orderMessage);
}

3. 通过transactional queue收发message的类的base class.
public class PetShopQueue : IDisposable
{

}

4. 具体类,通过MSMQ收发订单
PetShop.MSMQMessaging.Order: PetShopQueue, PetShop.IMessaging.IOrder
{

}

参考:
监视消息队列
http://www.netscum.dk/technet/prodtechnol/windowsserver2003/zh-CHS/library/RMS/RMSoperationsTC/a7109399-3a84-4681-874b-f6ea1646b0a0.mspx?mfr=true
.Net快速入门
http://chs.gotdotnet.com/quickstart/howto/doc/sendobject.aspx

PetShop中的OracleMembershipProvide

Filed under: 代码学习

Asp.net的membership缺省是放在sql server或 sql server exp中的,
如果使用Oracle就需要实现自己的memebership Provider.

Provider模式乃Asp.net2.0架构中精华之一,同时memebership也是ASP.Net2.0的要点.

1.web.config中
<membership defaultProvider=”SQLMembershipProvider”>
<providers>
<add name=”SQLMembershipProvider”
type=”System.Web.Security.SqlMembershipProvider”
connectionStringName=”SQLMembershipConnString”
applicationName=”.NET Pet Shop 4.0″
enablePasswordRetrieval=”false”
enablePasswordReset=”true”
requiresQuestionAndAnswer=”false”
requiresUniqueEmail=”false”
passwordFormat=”Hashed”/>
</providers>
</membership>

<!– Membership Provider for Oracle –>
<!–
<membership defaultProvider=”OracleMembershipProvider”>
<providers>
<clear/>
<add name=”OracleMembershipProvider”
type=”PetShop.Membership.OracleMembershipProvider”
connectionStringName=”OraMembershipConnString”
enablePasswordRetrieval=”false”
enablePasswordReset=”false”
requiresUniqueEmail=”false”
requiresQuestionAndAnswer=”false”
minRequiredPasswordLength=”7″
minRequiredNonalphanumericCharacters=”1″
applicationName=”.NET Pet Shop 4.0″
hashAlgorithmType=”SHA1″
passwordFormat=”Hashed”/>
</providers>
</membership>
–>
这里有一些配置需要注意, passwordFormat为”Hashed”时无法取回password,只能reset,此时若
enablePasswordRetrieval设为true,会出错.

if(passwordFormat == MembershipPasswordFormat.Hashed && enablePasswordRetrieval)
throw new ProviderException(”Provider cannot retrieve hashed password”);

2. Oracle的Membership表
CREATE TABLE MSPETSHOP4SERVICES.MEMBERSHIP (
UserId number NOT NULL,
Password varchar2(128 byte) NOT NULL,
PasswordFormat number NOT NULL,
MobilePin varchar2(16 byte),
Email varchar2(128 byte),
PasswordQuestion varchar2(256 byte),
PasswordAnswer varchar2(128 byte),
IsApproved char(1 byte) NOT NULL,
CreatedDate date NOT NULL,
LastLoginDate date NOT NULL,
LastPasswordChangedDate date NOT NULL,
“Comment” varchar2(4000 byte),
PasswordSalt varchar2(128 byte),
CONSTRAINT PK_MEMBERSHIP PRIMARY KEY(UserId),
CONSTRAINT FK_MEMBERSHIP_USERS FOREIGN KEY(UserId)
REFERENCES MSPETSHOP4SERVICES.USERS(UserId)
ON DELETE CASCADE);

3.OracleMembershipProvider 代码实现:

很多都没有实现.

可参照
Writing A Custom Membership Provider for your ASP.NET 2.0 Web Site

Building Custom Providers for ASP.NET 2.0 Membership

PetShop的Data Cache

Filed under: 代码学习

1.Interface
为了工厂模式的需要,PetShopCacheDependency会返回一个包含多个CacheDependency object的AggregateCacheDependency
public interface IPetShopCacheDependency
{
AggregateCacheDependency GetDependency();
}

2.工厂
CacheDependencyFactory模块中的
DependencyAccess会根据web.config的设定生成具体的PetShopCacheDependency

public static class DependencyAccess
{
public static IPetShopCacheDependency CreateProductDependency()
{
return LoadInstance(”Product”);
}

private static IPetShopCacheDependency LoadInstance(string className)
{
string path = ConfigurationManager.AppSettings[”CacheDependencyAssembly”];
string fullyQualifiedClass = path + “.” + className;

//所有的PetShopCacheDependency存在于一个assembly中
return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
}
}

web.config
<add key=”CacheDependencyAssembly” value=”PetShop.TableCacheDependency”/>

3.具体实现
提供了SQLserver Cache Dependency的通用实现,从web.config中读取table name并生成相应的
AggregateCacheDependency对象.
public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency
{
protected char[] configurationSeparator = new char[] { ‘,’ };

protected AggregateCacheDependency dependency = new AggregateCacheDependency();

protected TableDependency(string configKey)
{
string dbName = ConfigurationManager.AppSettings[”CacheDatabaseName”];
string tableConfig = ConfigurationManager.AppSettings[configKey];
string[] tables = tableConfig.Split(configurationSeparator);

foreach (string tableName in tables)
{
//注意dbName要和<caching>一节定义的database对应
dependency.Add(new SqlCacheDependency(dbName, tableName));
}
}

public AggregateCacheDependency GetDependency()
{
return dependency;
}
}

public class Product : TableDependency
{
public Product() : base(”ProductTableDependency”)
{
}
}

web.config
<!– CacheDatabaseName should match the name under caching section, when using TableCacheDependency –>
<add key=”CacheDatabaseName” value=”MSPetShop4″/>
<!– *TableDependency lists table dependency for each instance separated by comma –>
<add key=”CategoryTableDependency” value=”Category”/>
<add key=”ProductTableDependency” value=”Product,Category”/>
<add key=”ItemTableDependency” value=”Product,Category,Item”/>

<caching>
<sqlCacheDependency enabled=”true” pollTime=”10000″>
<databases>
<add name=”MSPetShop4″ connectionStringName=”SQLConnString1″ pollTime=”10000″/>
</databases>
</sqlCacheDependency>
</caching>

4.应用:
App_Code中定义了DataProxy类来获取数据,数据可能来自databse,亦可来自cache.
以ProductDataProxy为例,该类封装了BLL层的Product对象,通过Product读取数据,并放入cache

public static class ProductDataProxy
{
}

5. 数据库中的AspNet_SqlCacheTablesForChangeNotification是如何生成的?
使用工具
aspnet_regsql -S <SqlServerName> -U sa -d <DatabaseName> -ed -et -t <TableName>

见<Pet Shop 4 Install Folder>\DatabaseScripts\InstallDatabases.cmd:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql -S localhost -E -d MSPetShop4 -ed
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql -S localhost -E -d MSPetShop4 -t Item -et
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql -S localhost -E -d MSPetShop4 -t Product -et
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql -S localhost -E -d MSPetShop4 -t Category -et

PetShop动态加载Pattern

Filed under: 代码学习

加载Order strategy,见Order class
1. Interface
public interface IOrderStrategy
{
void Insert(PetShop.Model.OrderInfo order);
}

2. Concrete class
public class OrderAsynchronous : IOrderStrategy
{
private static readonly PetShop.IMessaging.IOrder asynchOrder = PetShop.MessagingFactory.QueueAccess.CreateOrder();

public void Insert(PetShop.Model.OrderInfo order) {

asynchOrder.Send(order);
}
}

3.Factory
private static PetShop.IBLLStrategy.IOrderStrategy LoadInsertStrategy()
{

// Look up which strategy to use from config file
string path = ConfigurationManager.AppSettings[”OrderStrategyAssembly”];
string className = ConfigurationManager.AppSettings[”OrderStrategyClass”];

// Using the evidence given in the config file load the appropriate assembly and class
return (PetShop.IBLLStrategy.IOrderStrategy)Assembly.Load(path).CreateInstance(className);
}

4.web.Config
<add key=”OrderStrategyClass” value=”PetShop.BLL.OrderSynchronous”/>

PetShop Connection string加解密

Filed under: 代码学习

EncryptWebConfig.bat
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pef “connectionStrings” “C:\Program Files\Microsoft\.NET Pet Shop 4.0\Web”

DecryptWebConfig.bat
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pdf “connectionStrings” “C:\Program Files\Microsoft\.NET Pet Shop 4.0\Web”

另:可通过代码加解密的connection string
public void EncryptConfig(bool bEncrypt)
{
string path = “/tricks”;

Configuration config = WebConfigurationManager.OpWebConfiguration(path);
ConfigurationSection appSettings = config.GetSection(”connectionString”);

if(bEncrypt)
{
appSettings.SetionInformation.ProtectSection(”DataProtectionConfigurationProvider”);
}
else
{
appSettings.SetionInformation.UnprotectSection();
}
config.Save();
}

程序中使用connection string的部分勿需关心web.config是否加密,
public static readonly string ConnectionStringMembership = ConfigurationManager.ConnectionStrings[”myConnString”].ConnectionString;

PetShop中的OrderStrategy和System.Transactions

Filed under: 代码学习

Asynchronous Order Placement Setup Instructions

1. Add a new private queue for Pet Shop called “PSOrders”

2. Modify web.config:

a.Change the OrderStrategyClass key to OrderAsynchronous
<add key=”OrderStrategyClass” value=”PetShop.BLL.OrderAsynchronous”/>

b.Change the MachineName in the following line to your MSMQ computer name.
<add key=”OrderQueuePath” value=”FormatName:DIRECT=OS:MachineName\Private$\PSOrders”/>

3. Modify app.config in the OrderProcessor project:

Change the MachineName in the OrderQueuePath key:
<add key=”OrderQueuePath” value=”FormatName:DIRECT=OS:MachineName\Private$\PSOrders”/>

同步定单处理 和 System.Transactions
同步定单处理中的 Order.Insert() 方法使用 System.Transactions 插入一个定单并更新库存。
通过添加对 System.Transaction 命名空间的引用,并将定单插入方法和库存减少方法包装在
TransactionScope 内,

–多线程
OrderProcessor会使用多线程从Message queue中读取order,
注意,并没有任何防止竞争的机制,莫非message queue可以做到这一点?

–Transaction
OrderProcessor使用了TransactionScope,注意设置TransactionScope的
Consistent或调用TransactionScope的Complete()

System.Transactions介绍
http://blog.joycode.com/kaneboy/archive/2005/02/15/44356.aspx

Introducing System.Transactions in .NET Framework 2.0
http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20050203NETMC/manifest.xml

PetShop中的异常处理和log

Filed under: 代码学习

1.在web.config中定义要用的event log的source name.
<appSettings>
<add key=”Event Log Source” value=”.NET Pet Shop 4.0″/>
</appSettings>

2.
在Globla.asax中

private static string LOG_SOURCE = ConfigurationManager.AppSettings[”Event Log Source”];

protected void Application_Error(object sender, EventArgs e)
{
Exception x = Server.GetLastError().GetBaseException();
EventLog.WriteEntry(LOG_SOURCE, x.ToString(), EventLogEntryType.Error);
}
任何错误都会作为exception,记录在event log中.

但是此时EventLog.WriteEntry尚不可用,用则出错:
A first chance exception of type ‘System.Security.SecurityException’ occurred in mscorlib.dll
Additional information: Requested registry access is not allowed.

3.安装Event Source
可使用EventLogInstaller来安装Event Source

EventLogInstaller.Source = “.NET Pet Shop 4.0″
EventLogInstaller.Log = “Application”

或使用:
if (!System.Diagnostics.EventLog.SourceExists(”MyApp1″))
{
System.Diagnostics.EventLog.CreateEventSource(”MyApp1″, “Application”);
}

删除
EventLog.DeleteEventSource(”MyApp1″)

August 17, 2006

PetShop数据访问架构

Filed under: 代码学习

–by Aloneplayer 2006.08.17

1. IDAL
定义了各个数据实体的数据访问层的interface
如Product,对应一个
public interface IProduct
{
IList<ProductInfo> GetProductsByCategory(string category);

IList<ProductInfo> GetProductsBySearch(string[] keywords);

ProductInfo GetProduct(string productId);
}

2. Model
定义了各个数据实体类,如:
[Serializable]
public class ProductInfo
{

private string id;
private string name;
private string description;
private string image;
private string categoryId;
}

3. BLL
定义了使用数据一些函数,这些函数封装了对数据访问层函数的使用.
public class Product
{
private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();

IList<ProductInfo> GetProductsByCategory(string category)
{
return dal.GetProductsByCategory(category);
}

IList<ProductInfo> GetProductsBySearch(string[] keywords);

ProductInfo GetProduct(string productId);
}

4. SQLServerDAL模块中定义了各个数据实体对应的数据访问层对象
每个对象都实现了IDAL层的对应Interface,如
public class Product : IProduct
{

}
每个数据访问层对象都依赖于一个封装了数据库操作的工具类,比如SQLHelper和OracleHelper,来完成对数
据库的操作.

5. DALFactory此模块中只有一个class,负责根据web.config来加载各个数据访问层对象

public sealed class DataAccess
{
private static readonly string path = ConfigurationManager.AppSettings[”WebDAL”];

public static PetShop.IDAL.IProduct CreateProduct()
{
string className = path + “.Product”;
return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className);
}

}

在web.config中WebDAL对应了当前使用了数据访问层对象所在的模块,
<add key=”WebDAL” value=”PetShop.SQLServerDAL”/>
显然,要使用其他数据库,只需要修改这个配置.

>>整个体系由数据实体(model),数据逻辑层(BLL),数据访问层构成(DAL),BLL依赖于DAL,由于数据访问层的不确定性
(可能是sql,也可能是orcal),故而将DAL拆分为IDAL和DAL,使BLL依赖于IDAL,DAL实现IDAL.
同时使用DALFactory根据配置动态生成所需DAL.

August 16, 2006

在web.config中限制对文件类型的访问

Filed under: ASP.NET

<system.web>
<httpHandlers>
<add path=”*.xml” verb=”*” type=”System.Web.HttpForbiddenHandler”>
</httpHandlers>
</system.web>

August 15, 2006

Access WebService with IE

Filed under: Web Service

INFO: HTTP GET and HTTP POST Are Disabled by Default
http://support.microsoft.com/default.aspx?scid=kb;en-us;819267

We need add following stuff into the web config
<configuration>
<system.web>
<webServices>
<protocols>
<add name=”HttpGet”/>
<add name=”HttpPost”/>
</protocols>
</webServices>
</system.web>
</configuration>

August 14, 2006

ASP.net trace and debug

Filed under: ASP.NET

这两个功能的开关都有两个级别: Application级(在web.config中设置),页面级(在<@Page>中设置)
以Page中的设定为准.

此外.net 2.0 的machine.cofig中还有一个机器级的设定:
<system.web>
<deployment retail=”false” />
</system.web>
一旦retail=”true”所有的Trace, debug设定统统无效.
参考MSDN How to: Precompile ASP.NET Web Sites for Deployment

正式服务器一定不要用debug, trace
http://blogs.msdn.com/tess/archive/2006/04/13/575364.aspx
http://weblogs.asp.net/scottgu/archive/2006/04/11/442448.aspx

>>有关 Trace:
1. 如果web.config中的Trace设定为false,就不能使用Trace.axd来
查看Trace信息.

2. TarceMode=”SortByCategory”设置Trace信息的显示顺序.

3. 条件输出
if(Trace.IsEnabled)
Trace.Write

4. 完全用代码控制:
void Page_Load (object sender, EventArgs e)
{
Trace.TraceFinished +=new TraceContextEventHandler (OnTraceFinished);
}

void OnTraceFinished (object sender, TraceContextEventArgs e)
{
foreach (TraceContextRecord record in e.TraceRecords)
{
Response.Write (String.Format (”{0}: {1}<br>”,record.Category, record.Message));
}
}
在vs2005中,可以使用下边的配置在output window中显示trace信息.
<configuration>
<system.web>
<trace enabled=”true” writeToDiagnosticsTrace=”true” />
</system.web>
</configuration>

参考 Power Programming Tips for ASP.NET 2.0 一文

>>有关Debug
1. 和<customError mode=”">联合使用,根据error code跳转到不同页
2. 在Page.Error中进行错误处理
Page_Error
{
Server.GetLastError().ToString(); //显示call stack
}

3. 常见错误
IIS 状态代码(http://support.microsoft.com/?id=318380)

500 内部服务器错误
403 No access
404 Not found

参考
ASP.NET 2.0 监视你的应用
http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/episode.aspx?newsID=1242387

August 12, 2006

HttpModule应用Trap browser refresh

Filed under: ASP.NET

参考
MSDN HttpApplication class, AcquireRequestState Event 的时机

Interface IHttpModule
{
void Init( HttpApplication context );
void Dispose();
}

使用
<system.web>

<httpModules>
<add name=”RefreshModule” type=”RivenWeb.RefreshModule” />
</httpModules>
</system.web>

要解决的问题:
当你refresh一个页面时,browser会将上次的提交再重复一遍,如果上次的操作是删除一条
记录,refresh会导致再删除一次,如果上次的操作是添加一条记录,则refresh会插入冗余
的记录.

写一个自己的HttpModule,在Init中注册HttpApplication的AcquireRequestState,
在时间处理函数中根据HttpApplication.Context拿到HttpContext并处理之.
public class RefreshModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.AcquireRequestState += new EventHandler(this.OnAcquireRequestState);
}
public void Dispose()
{

}
private void OnAcquireRequestState(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context;

RefreshAction.Check(ctx);
}
}

RefreshAction是一个工具类,用与Check HttpContext中的refresh信息,判断本次页面请求
的性质,并记录.
public static void Check(HttpContext ctx)

查看ctx.Session[”__LASTREFRESHTICKET”]是否为null,如果为null,
ctx.Session[”__LASTREFRESHTICKET”] = 0;

从Session读取Last refresh ticket
ctx.Session[”__LASTREFRESHTICKET”]
从hidden field读取Current refresh ticket
ctx.Request[”__CURRENTREFRESHTICKET”]
注意Last refresh ticket 位于Session中,而 Current refresh ticket位于Resuest中.
整个程序的关键就在于ctx.Request[”__CURRENTREFRESHTICKET”],如果是F5, ctx.Request[”__CURRENTREFRESHTICKET”]
和上一次请求一样,如果是正常的request,ctx.Request[”__CURRENTREFRESHTICKET”]为Page的隐藏字段”__CURRENTREFRESHTICKET”的值
而Page的隐藏字段”__CURRENTREFRESHTICKET”的值会在每次request中被TrackRefreshState()函数加1.
并在Pag_PreRender中被记录到hidden field中.

“When the user submits a new request (causes the displayed page to post back), the
hidden field (if any) is automatically attached to the request for the server. “

比较Last refresh ticket和Current refresh ticket,
如果current > last ()或
current = last 并且 current = last = 0(说明是第一次请求)
说明是正常的请求,set ctx.Items[PageRefreshEntry] = false;
并同步Last refresh ticket和Current refresh ticket,
ctx.Session[”__LASTREFRESHTICKET”] = current ticket;
否则在context的itemt记录此次refresh的类型
set ctx.Items[PageRefreshEntry] = true;

写一个Page类,为所有的request生成一个递增的ticket号,
1.提供Propery:IsPageRefresh,读取HttpContext.Current.Items[PageRefreshEntry],
从而得知但前page是refresh还是正常的请求.在进行正常的处理前,判断是否需要进行
数据操作.
protected void Button_Add_Click(object sender, EventArgs e)
{
if (!IsPageRefresh)
AddRecord(this.TextBox_FirstName.Text, this.TextBox_LastName.Text);
else
this.Message.InnerText = “Page refreshed”;
TrackRefreshState();
}
2.提供一个方法TrackRefreshState来修改Page.Session[RefreshTicketCounter],
如果是通过button click等错作引起的refresh, 就调用这个函数,使Page.Session[RefreshTicketCounter]+1
,以便新的页面请求中可以包含RefreshTicketCounter信息.

3.在Page.PreRender事件中将Page.Session[RefreshTicketCounter]记录到Page的隐藏字段中.
注意,这个隐藏字段中字段的名字为”__CURRENTREFRESHTICKET”,从而HttpModule可以从
ctx.Request[CurrentRefreshTicketEntry]读到这个值.

问题:
HttpContext.Session与Page.Session的辨析
隐藏字段和HttpContext.Request的关系.

August 11, 2006

VS2005 Debug 信息的输出

Filed under: Visual Studio

实验:
Console.Write(”>>Console:”);
System.Diagnostics.Debug.Write(”>>Debug:”);
System.Diagnostics.Trace.Write(”>>Trace:”);

————————————————————————-

在webpage和web service中,只有Debug.Write产生输出

另外:
Options->debugging->General
Redirect all output window text to the Immediate window (new one in VS 2005 )
Redirect all console output to the Quick Console window (一度出现,现在不见 )

August 10, 2006

特殊的Exception : ThreadAbortException

Filed under: .NET
using System;
using System.Threading;
using System.Security.Permissions;
	
namespace ThreadAbortTest
{
	
        public class ThreadWork
        {
                public static void DoWork()
                {
                        try
                        {
                                DoWorkInternal();
                        }
                        catch(ThreadAbortException e)
                        {
                                Console.WriteLine(\"Exception In Dowork(): {0}\", e.Message);
                                //Thread.ResetAbort();
                        }
                        finally
                        {
                                Console.WriteLine(\"Dowork() is dying\");
                        }
                }
	
                public static void DoWorkInternal()
                {
                        try
                        {
                                for(int i=0; i<10000; i++)
                                {
                                        Console.WriteLine(\"DoWorkInternal - working.\");
                                        Thread.Sleep(100);
                                }
                        }
                        catch(ThreadAbortException e)
                        {
                                Console.WriteLine(\"Exception In DoWorkInternal(): {0}\", e.Message);
                                //Thread.ResetAbort();
                        }
                        finally
                        {
                                Console.WriteLine(\"DoWorkInternal() ending\");
                        }
                }
        }
	
        class ThreadAbortTest
        {
                public static void Main()
                {
                        Thread myThread = new Thread(new ThreadStart(ThreadWork.DoWork));
                        myThread.Start();
                        Thread.Sleep(1000);
                        myThread.Abort();
                        myThread.Join();
                        Console.WriteLine(\"Main ending.\");
                }
        }
}
	

显示
DoWorkInternal - working.

DoWorkInternal - working.
Exception In DoWorkInternal(): Thread was being aborted.
DoWorkInternal() ending
Exception In Dowork(): Thread was being aborted.
Dowork() is ending
Main ending.

1.ThreadAbortException 在DoWorkInternal中被catch了,DoWork中依然可以catch到.
显然,MS希望Thread.Abort调用时,调用栈中每个函数都知道.
2.去掉所有的try-catch,程序照常执行. VS的Debug-Exception设定对话框中,打开所有的
exception,可看到ThreadAbortException 是一个特殊的exception.
3. myThread.Abort(); myThread.Join(); //等待myThread的finally块的执行

SqlConnection 和 SqlTrasaction应该先dispose哪一个?

Filed under: SQL&DB Accessing

我的代码

string connstr= @\"Data Source=.\sql2k5;Initial Catalog=SQLStudy; Integrated Security=SSPI\";
SqlConnection conn = null;
SqlTransaction trans = null;
try
{
        conn = new SqlConnection(connstr);
        conn.Open();
        trans = conn.BeginTransaction();
        string sql = \"Insert into Student values(100, 'ak47')\";
        // Must assign both transaction object and connection
        // to Command object for a pending local transaction
        //new SqlCommand(sql, trans.Connection);会报错!
        SqlCommand command = new SqlCommand(sql, trans.Connection, trans);
        command.ExecuteNonQuery();
        trans.Commit();
}
catch (Exception exp)
{
        Console.WriteLine(exp.Message);
        if(trans != null)
        {
                trans.Rollback();
        }
}
finally
{
        if(conn != null)
        {
                conn.Close();
        }
        if(trans != null)
        {
                trans.Dispose();
        }
}

MSDN

using (SqlConnection conn = new SqlConnection(dbConString))
{
   conn.Open();
   using (SqlTransaction trans = conn.BeginTransaction())
   {
      try
      {
         ...
              trans.Commit();
      }
      catch
      {
         trans.Rollback();
      }
   }
}
	

August 9, 2006

E都市API

Filed under: ASP.NET

一、在文字后提供链接,指向地图上所在的位置
如:
钟楼<span classid=”edushianchor” city=”西安” sitename=”钟楼” address=”" style=”display:none”></span>
西工大<span classid=”edushianchor” city=”西安” sitename=”西工大” address=”" style=”display:none”></span>
杭州阿拉丁信息科技有限公司<span classid=”edushianchor” city=”杭州” sitename=”杭州阿拉丁信息科技有限公司” address=”杭州市庆春路228号6层(延安路口)” style=”display:none”></span>

[city] 城市参数,可以是城市的名称、城市的全拼、城市的区号
[sitename] 地点名称
[address] 具体地址

二、URL地址引用
<a href= http://www.edushi.com/api/url.asp?isMark=1&z=1&v=7&x=0&y=0&w=500&h=400&city=xian&sitename”>我的位置</a>
我的位置

z: 离地面的高度

三、嵌入地图
<script language=”javascript” src= ” http://www.edushi.com/api/api.js?isMark=1&z=2&v=3&x=0&y=0&w=500&h=400&city=xian&sitename=我的位置” type=”text/javascript”> </script>
直接用IE打开html文件不能显示地图,把html文件放在vd下才能显示

四、嵌入图片
<img src=http://www.edushi.com/api/getmap?city=xian&w=200&h=200&v=3&z=1&x=0&y=0 width=500 height=400 border=0>
目前似乎不能用.

五、高级扩展

还不会…

ThreadAbortException in asp.net applcation calling web method.

Filed under: ASP.NET

Improving .NET Application Performance and Scalability Chapter 10
Improving Web Services Performance, Timeout 一节
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt10.asp)
中提到asp.net application调用web service是个很常见的case, 如果web page先于对web service的调用超
时,会导致resource leak和ThreadAbortException.因为asp.net application的I/O线程和sockets被用于调用
service,一旦出现ThreadAbortException,会导致socket无法关闭,并无法重用.

目前我们的程序的机制是在一个web page中反复调用一个web method,把多条记录逐一由web method写入另一个数据库.(很显然web page的执行时间大于web method的执行时间)

影响这个过程的timeout有:
web application 所在机器上的web proxy timeout,执行timeout, 死连接timeout
Web service 所在机器的执行timeout.

1. web proxy timeout对应proxy的Timeout属性,default 为100s

2. 执行timeout 对应web.config中的

<system.web>
<httpRuntime executionTimeout=”90″ />
</system.web >
指示在请求被ASP.NET 自动关闭前允许执行的最大秒数。Default为90s

3. 死连接timeout对应web.config中的

<system.web>
<processModel responseDeadlockInterval=”00:03:00″ />
</system.web>
Default为3m, 180s
有关各个timeout的设定,见Improving .NET Application Performance and Scalability Ch17:
Configure Timeouts Aggressively一节.

简言之:
Web service proxy timeout< executionTimeout < responseDeadlockInterval

August 7, 2006

Web Application Debug Mode

Filed under: ASP.NET

ScottGu’s Blog(MS ASP.NET PM),
http://weblogs.asp.net/scottgu/archive/2006/04/11/442448.aspx
Doing so causes a number of non-optimal things to happen including:
1) The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)
2) Code can execute slower (since some additional debug paths are enabled)
3) Much more memory is used within the application at runtime
4) Scripts and images downloaded from the WebResources.axd handler are not cached

http://blogs.msdn.com/tess/archive/2006/04/13/575364.aspx
There are three main differences between debug=true and debug=false:

ASP.NET Timeouts
Batch compilation
Code optimization

Note: Timeout values are specified in milliseconds. If you have debug=”true”
in the Web.config file, the executionTimeout value will be ignored.

Question:

>>How about using Debug=true in the web.config and using release version dll?

Upload File in ASP.NET

Filed under: ASP.NET

http://www.microsoft.com/china/msdn/library/webservices/asp.net/dnasppUploadASP2.mspx?mfr=true(CH)
http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnaspp/html/UploadASP2.asp(En)

http://www.codeproject.com/aspnet/fileupload.asp

http://windowssdk.msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.aspx

When using the File Field control in ASP.NET 1.x you had to take a few extra steps to get
everything in line and working. For example, you were required to add
enctype=”multipart/form-data” to the page’s <form> element on your own.

The new FileUpload server control provided in ASP.NET 2.0 makes the process of uploading
files to the hosting server as simple as possible.

//–Web Config
默认情况下,使用 FileUpload 控件上载到服务器的文件最大为 4MB 左右.

<system.web>
<httpRuntime maxRequestLength=”SIZE IN BYTES” executionTimeout=”????” />
</system.web>

负责上载文件大小的设置是 maxRequestLength 属性
executionTimeout 是 ASP.NET 关闭前允许发生的上载秒数

可参考web.config.comments (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG)中的defalut value
参考What’s New in ASP.NET Configuration

//–相关错误:
When uploading large files, a user might also receive the following error message:

aspnet_wp.exe (PID: 1520) was recycled because memory consumption exceeded 460 MB (60 percent of available RAM).

If your users encounter this error message, increase the value of the “memoryLimit” attribute in the “processModel”
element of the Web.config file for the application.
The memoryLimit attribute specifies the maximum amount of memory that a worker process can use.
If the worker process exceeds the memoryLimit amount, a new process is created to replace it, and all current
requests are reassigned to the new process.

To control whether the file to upload is temporarily stored in memory or on the server while the request is being
processed, set the requestLengthDiskThreshold attribute of the httpRuntime element. This attribute allows you
to manage the size of the input stream buffer. The default is 256 bytes. The value that you specify should not
exceed the value that you specify for the maxRequestLength attribute.

//–Client
FileUpload 控件被转换为一个 HTML <input type=”file”>

//–Server
if (FileUpload1.HasFile)
{
try
{
FileUpload1.SaveAs(”C:\\Uploads\\” + FileUpload1.FileName);
}
}

//–Folder permission
在folder上为asp.net的执行帐号:ASPNET 或 WebService赋写权限

//–Check File Type
Client : Validator
Server:
string fileExt = System.IO.Path.GetExtension(FileUpload1.FileName);
if (fileExt == “.mp3″)
{
}

//–Check File size
Client (just image):
Assign a image to a image’s src. get size by Image.FileSize.
If assign a image to a image’s src, get -1.
Server:

//–Uploading multiple files
string filepath = “C:\\Uploads”;
HttpFileCollection uploadedFiles = Request.Files;

for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
}






















Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham