Feb 01

发现一个System.Uri类的一个bug:

比如一个Web页面地址是:http://www.changethis.com/archives,

页面中有个链接是:<a href=”?by=email_count&order=descending&page=3&topic=”>Next Page</a>,

那么Internet Explorer和Firefox解释出来的正确地址是:
http://www.changethis.com/archives?by=email_count&order=descending&page=3&topic=

但使用Uri(Uri baseUri, string relativeUriString)解释出来的是:
http://www.changethis.com/?by=email_count&order=descending&page=3&topic=

推测bug的起因:实现人员和测试人员,没有使用JSP/PHP等语言的URL地址去测试这个Uri类。

Dec 24

如果使用过UpdatePanel,可能已经注意到,当一个页面有多个UpdatePanel的时候,异步页面请求同时只能有一个请求(callback),而且后发起的请求会取消先发的请求。怎么改变这个次序呢,比如一个异步请求已经在进行,怎么阻止其它请求呢?这就要用到PageRequestManager。(让多个请求并发进行,以后会介绍)

通过PageRequestMangaer还能提供更多的feature:提供取消callback的选项,自定义错误处理消息,访问底层进行异步请求的request/response对象。

总的来看,PageRequestManager是运行在浏览器端的协调者,它和服务器端的UpdatePanel一起,把局部页面更新的复杂性抽象化,提供给开发者方面的使用接口。

PageRequestManager提供了以下事件,让开发者能加入自己的Javascript脚本来改变缺省的行为:

1. initializeRequest

Raised before the request is initialized for an asynchronous postback. Event data is passed to handlers as an InitializeRequestEventArgs object. The object makes available the element that caused the postback and the underlying request object.

2. beginRequest

Raised just before the asynchronous postback is sent to the server. Event data is passed to handlers as a BeginRequestEventArgs object. The object makes available the element that caused the postback and the underlying request object.

3. pageLoading

Raised after the response to the last asynchronous postback has been received but before any updates to the page have been made. Event data is passed to handlers as a PageLoadingEventArgs object. The object makes available information about what panels will be deleted and updated as a result of the last asynchronous postback

4. pageLoaded

Raised after page regions are updated after the last asynchronous postback. Event data is passed to handlers as a PageLoadedEventArgs object. The object makes available information about what panels were created and updated. For synchronous postbacks, panels are only created, but for asynchronous postbacks panels can be both created and updated.

5. endRequest

Raised when request processing is finished. Event data is passed to handlers as an EndRequestEventArgs object. The object makes available information about errors that have occurred and whether the error was handled. It also makes available the response object.

?

我们来分析一个使用PageRequestManager的例子:

Run the example ( view source)

这个例子中,使用了PageRequestManager来定制Update状态显示,也提供了取消请求的方法,这主要是从下面的代码中展示出来:

<script type=”text/javascript”>
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
var postBackElement;
function InitializeRequest(sender, args) {
if (prm.get_isInAsyncPostBack())
{
???args.set_cancel(true);
}
postBackElement = args.get_postBackElement();
if (postBackElement.id == ‘ButtonTrigger’)
{
???$get(’UpdateProgress1′).style.display = “block”;
}
}
function EndRequest (sender, args) {
if (postBackElement.id == ‘ButtonTrigger’)
{
???$get(’UpdateProgress1′).style.display = “none”;
}
}
function AbortPostBack() {
if (prm.get_isInAsyncPostBack()) {
???prm.abortPostBack();
}
}
</script>

在例子中,通过给PageRequestManager的initializeRequest事件和endRequest事件加入自定义的javascript代码,实现了定制的行为。

对于PageRequestManager,使用get_isInAsyncPostBack方法或isInAsyncPostBack属性能得到当前异步请求状态;使用abortPostBack可以取消当前的请求;使用add_initializeRequest和add_endRequest分别将用户编写的javascript处理函数注册到initializeRequest事件和endRequest事件中。

另外,在函数InitializeRequest中,args.set_cancel(true)用来让先发的请求被执行,改变缺省的后发具优的行为。



得到PageRequestManager的所有方法和事件列表,请参见:


Sys.WebForms.PageRequestManager Class

Dec 04

Google Search API的英文全称是Google SOAP Search API,它使我们能够提交搜索请求到Google,并在程序中得到结构化的查询结果。在.NET中使用Google Search API非常方便,基本步骤是:

1. 到API上主页上,申请一个license key:
http://code.google.com/apis/soapsearch/index.html

2. 下载开发工具包(developer’s kit),如果不能下载,你需要登录先。

3. 解压缩开发工具包,里面含有Java、C#、VB.NET的示例程序。但这里我们只关心两个文件:

GoogleSearch.wsdl??
APIs_Reference.html

4. 使用.NET Framework SDK中的工具wsdl.exe生成本地proxy class:

wsdl.exe GoogleSearch.wsdl

这时生成一个C#文件:GoogleSearchService.cs

5. 在Visual Studio 2005中创建一个新的项目Project。把步骤4生成的GoogleSearchService.cs加入到项目中。

6. 下面一段代码完成一个查询:

GoogleSearchService gss =new GoogleSearchService();
GoogleSearchResult results = gss.doGoogleSearch(”your_License_Key“, “nicole kidman”, 0, 10, true, “”, false, “”, “”, “”);
foreach (ResultElement r in results.resultElements)
{
???Console.WriteLine(”Title: “+ r.title);
???Console.WriteLine(”Snippet: “+ r.snippet);
???Console.WriteLine(”URL: “+ r.URL);
???Console.WriteLine(”\n”);
}

7. OK,基本过程就是这样了。

?


需要特别注意的地方:
—————————————-
1. 对一个查询query,最多能能访问前1000个搜索结果。(MSN Search是前250个)

2. 每次搜索doGoogleSearch调用,最多只能返回10个搜索结果。(MSN Search是50个)

3. 如果搜索doGoogleSearch时,指定最多返回的结果数大于10,会引发SoapException。

4. 在很快的网络连接下,一个查询大概耗时6.6~10.3秒。批量执行时,每个查询大概耗时2.2秒。这样,取完1000个结果,大概耗时220秒。

5. 这里只列了一个最简单的例子,关于API的类、方法、参数说明,详细文档请参见APIs_Reference.html,里面解释的非常细致。

?


更多资源:

—————————————-
FAQ:http://code.google.com/apis/soapsearch/api_faq.html

Discussion/Community: http://groups.google.com/group/google.public.web-apis

More Gogole APIs: http://code.google.com/apis.html

MSN Search API: http://msdn.microsoft.com/live/msnsearch/default.aspx