我的CMS开发记 -引子
官方网址:
http://www.DNNLite.com
[Flex]Flex与.NET互操作(四):使用HttpService、URLReqeust和URL
在前两篇文章中分别介绍了Flex与.NET的WebService之间的数据交互通信知识,本文将介绍另外一种加载数据以及发起请求的方 式。ActionScript 3.0中提供的数据加载请求类主要是HTTPService,URLLoader和URLRequest,可以通过他们协同来完成数据加载和请求。下面我 么便来看看这三个类是怎么来完成数据加载工作。
在本地IIS服务器上有如下定义的XML文件:
2 <Root>
3 <Book>
4 <Id>1</Id>
5 <Name>《三国演义》</Name>
6 <Author>罗贯中</Author>
7 <Price>52.30</Price>
8 </Book>
9 <Book>
10 <Id>2</Id>
11 <Name>《西游记》</Name>
12 <Author>吴承恩</Author>
13 <Price>39.91</Price>
14 </Book>
15 <Book>
16 <Id>3</Id>
17 <Name>《红楼梦》</Name>
18 <Author>曹雪芹</Author>
19 <Price>48.20</Price>
20 </Book>
21 <Book>
22 <Id>4</Id>
23 <Name>《水浒传》</Name>
24 <Author>施耐庵</Author>
25 <Price>39.85</Price>
26 </Book>
27 </Root>
一、使用HTTPService传递和加载数据
使用HTTPService可以实现加载数据,也可以实现参数传递,下面通过两个示例程序来讲解这两个知识点。
首先来看看HTTPService加载数据的方式。在Flex中使用HTTPService来装载外部数据是非常简单的,他是基于 HTTP协议发送POST和GET请求外部数据,然后通过指定的监听方法来处理响应。我们可以通过<mx:HTTPService>标签来完 成对数据源的连接,也可以通过可编程方式来处理,两种方式没什么大的差距,实际开发中可以根据自己喜好选择。
2 {
3 var service:HTTPService = new HTTPService();
4 service.url = "http://localhost:1146/Data/Book.xml";
5 service.useProxy = false;
6 service.resultFormat="e4x";
7 service.addEventListener(ResultEvent.RESULT,onResultHandler);
8 service.send();
9 }
10
11 internal function onResultHandler(evt:ResultEvent):void
12 {
13 var xml:XML = evt.result as XML;
14 trace(xml);
15 bookGrid.dataProvider = xml.Book;
16 }
该示例的运行结果见文章最后,下面是这个示例的完整代码:
OK,我们来看看使用HTTPService传递参数到服务端是怎么实现的。使用HTTPService传递参数可以通过两种方式实现,分别如下:
1、直接在请求URL后面跟上参数列表,如:http://localhost/web/Test.aspx?a=1&b=2。
2、通过Flex SDK为我们提供专门用语参数传递的对象(URLVariables)来实现。
下面以一道简单的加法运算来演示HTTPService传递参数的使用,在Flex里将需要进行加法运算的两个数传递到.NET服务端并计算其和后返回给Flex客户端,两种方式传递没有太大的区别,详细请看如下代码演示:
2 * 通过RUL参数直接传递
3 * */
4 internal function onClick():void
5 {
6 var service:HTTPService = new HTTPService();
7 var a:String = txtA.text;
8 var b:String = txtB.text;
9 service.url = "http://localhost:1146/OperationHandler.ashx?a="+a+"&b="+b;
10 service.useProxy = false;
11 service.resultFormat="e4x";
12 service.addEventListener(ResultEvent.RESULT,onResultHandler);
13 service.send();
14 }
15
16 /**
17 * 通过URLVariables进行参数传递
18 * */
19 internal function onClick():void
20 {
21 var service:HTTPService = new HTTPService();
22 service.url = "http://localhost:1146/OperationHandler.ashx";
23 service.useProxy = false;
24 service.resultFormat="e4x";
25 service.addEventListener(ResultEvent.RESULT,onResultHandler);
26 var param:URLVariables = new URLVariables();
27 param.a = txtA.text;
28 param.b = txtB.text;
29 service.send();
30 }
下面是完整的示例代码,可以把onClick()方法相互切换来测试两种不同的参数传递方式。
上面示例的运行界面截图:
二、了解URLReqeust
使用URLRequest 类可捕获单个 HTTP 请求中的所有信息。将URLRequest 对象传递给URLStream或URLLoader 类以及其他加载操作的load()方法以启动URL数据加载。它的使用很简单,通过构造方法构造对象就OK:
同样可以使用URLRequest来请求一个本地项目/应用里的文件,如下代码示例:
如上便构造好了URLRequest对象,只要将他传递给相应的对象load()方法便可实现数据加载。从某种角度可以将URLRequest 理解为建立请求的工具。要是URLRequest类对象变成可用的对象还需得通过其他类来与之配合协作,详细见后面使用URLLoader加载数据。
URLRequest虽然功能强大,使用简单。但我们还是需要了解更多的东西,以便可以正确的应用URLRequest类和处理相应的错误。其中最引人关注的就是安全沙箱的问题,这部分我将在以后的文章中介绍,这里只需要记住两点就OK。
1、如果执行调用的 SWF 文件在只能与本地文件系统内容交互的沙箱中,而目标资源来自网络沙箱,则不允许进行数据加载。
2、如果执行调用的 SWF 文件来自网络沙箱而目标资源在本地,也不允许进行数据加载。
这里就简单介绍这些,关于URLRequest的详细资料大家可以查看官方提供的在线文档:http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/URLRequest.html
三、使用URLLoader加载数据
URLLoader 类可以以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据。下面将结合使用本地服务器上的数据(详细见文章前面的xml文件定义)的加载示例来演示URLLoader的使用方法。
那我们怎么通过URLLoader来加载它呢?很简单,使用上面介绍的URLRequest来创建请求连接,然后将URLRequest对象传递给URLLoader的load方法来实现数据加载。
2 {
3 var request:URLRequest = new URLRequest("http://localhost:1146/Data/Book.xml");
4 var loader:URLLoader = new URLLoader();
5 loader.load(request);
6 loader.addEventListener(Event.COMPLETE,onCompleteHandler);
7 }
8
9 private function onCompleteHandler(evt:Event):void
10 {
11 var xml:XML = new XML(evt.target.data);
12 bookGrid.dataProvider = xml.Book;
13 }
下面是整个mxml的代码定义:
1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3 <mx:Script>
4 <![CDATA[
5 internal function onClick():void
6 {
7 var request:URLRequest = new URLRequest("http://localhost:1146/Data/Book.xml");
8 var loader:URLLoader = new URLLoader();
9 loader.load(request);
10 loader.addEventListener(Event.COMPLETE,onCompleteHandler);
11 }
12
13 private function onCompleteHandler(evt:Event):void
14 {
15 var xml:XML = new XML(evt.target.data);
16 bookGrid.dataProvider = xml.Book;
17 }
18 ]]>
19 </mx:Script>
20 <mx:Panel x="49.5" y="94" width="419" height="267" layout="absolute" fontSize="12" borderColor="#E2E2E2" themeColor="#009DDF" title="使用URLLoader加在XML数据">
21 <mx:DataGrid x="10" y="10" width="377" id="bookGrid">
22 <mx:columns>
23 <mx:DataGridColumn headerText="编号" dataField="Id"/>
24 <mx:DataGridColumn headerText="书名" dataField="Name"/>
25 <mx:DataGridColumn headerText="作者" dataField="Author"/>
26 <mx:DataGridColumn headerText="价格" dataField="Price"/>
27 </mx:columns>
28 </mx:DataGrid>
29 <mx:ControlBar height="42">
30 <mx:Button label="加载数据" fontWeight="normal" click="onClick()"/>
31 </mx:ControlBar>
32 </mx:Panel>
33 </mx:Application>
34
本示例的运行结果如下图:
关于URLLoader的更多资料大家可以查看Adobe提供的在线文档:http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/URLLoader.html
[MVC]Asp.net MVC :Custom Action Filters
来自:http://quickstarts.ASP.NET/previews/mvc/mvc_ActionFiltering.htm
Custom Action Filters
Introduction
The possible uses for action filters are as varied as the actions to which they can be applied. Some possible uses for action filters include the following:
- Logging to track user interactions.
- "Anti-image-leeching" to prevent images from being loaded in pages that are not on your site.
- Web crawler filtering to change application behavior based on the browser user agent.
- Localization to set the locale.
- Dynamic actions to inject an action into a controller.
Implementing a Custom Action Filter
An action filter is implemented as an attribute class that inherits from ActionFilterAttribute. ActionFilterAttribute is an abstract class that has four virtual methods that you can override: OnActionExecuting, OnActionExecuted, OnResultExecuting, and OnResultExecuted. You must override at least one of these methods.
The ASP.NET MVC framework will call the OnActionExecuting method of your action filter before it calls any action method that is marked with your action filter attribute. Similarly, the framework will call the OnActionExecuted method after the action method has finished.
The OnResultExecuting method is called just before the ActionResult instance that is returned by your action is invoked. The OnResultExecuted method is called just after the result is executed. These methods are useful for performing actions such as logging, output caching, and so forth.
The following example shows a simple action filter that logs trace messages before and after an action method is called.
Public Class LoggingFilterAttribute
Inherits ActionFilterAttribute
Public Overrides Sub OnActionExecuting(ByVal filterContext _
As ActionExecutingContext)
filterContext.HttpContext.Trace.Write("Starting: " & _
filterContext.ActionMethod.Name)
MyBase.OnActionExecuting(filterContext)
End Sub
Public Overrides Sub OnActionExecuted(ByVal filterContext _
As ActionExecutedContext)
If Not filterContext.Exception Is Nothing Then
filterContext.HttpContext.Trace.Write("Exception thrown")
End If
MyBase.OnActionExecuted(filterContext)
End Sub
End Class
public class LoggingFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Starting: " +
filterContext.ActionMethod.Name);
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext
filterContext)
{
if (filterContext.Exception != null)
filterContext.HttpContext.Trace.Write("Exception thrown");
base.OnActionExecuted(filterContext);
}
}
Action Filter Context
Each of the controller event handlers for action filtering takes a context object as a parameter. The following list shows the event handlers and the context type that each takes.
- OnActionExecuting takes an ActionExecutingContext object.
- OnActionExecuted takes an ActionExecutedContext object.
- OnResultExecuting takes a ResultExecutingContext object.
- OnResultExecuted takes a ResultExecutedContext object.
All context classes inherit from the ControllerContext class and include an ActionMethod property. You can use the ActionMethod property to identify which action the filter is currently applied to.
The ActionExecutingContext and ResultExecutingContext classes contain a Cancel property that enables you to cancel the action.
The ActionExecutedContent and ResultExecutedContext classes contain an Exception property and an ExceptionHandled property. If the Exception property is null, it indicates that no error occurred when the action method ran. If the Exception property is not null and the filter knows how to handle the exception, the filter can handle the exception and then signal that it has done so by setting the ExceptionHandled property to true. Even if the ExceptionHandled property is true, the OnActionExecuted or OnResultExecuted method of any additional action filters in the stack will be called and exception information will be passed to them. This enables scenarios such as letting a logging filter log an exception even though the exception has been handled. In general, an action filter should not handle an exception unless the error is specific to that filter.
Marking an Action Method with a Filter Attribute
You can apply an action filter to as many action methods as you need. The following example shows a controller that contains action methods that are marked with an action-filter attribute. In this case, all the action methods in the controller will invoke the same action filter.
Public Class HomeController
Inherits Controller
Shared clicked As Boolean = False
<LoggingFilter()> _
Public Function Index()
ViewData("Title") = "Home Page"
ViewData("Message") = "Welcome to ASP.NET MVC!"
If clicked = True Then
ViewData("Click") = "You clicked this button."
clicked = False
End If
Return View()
End Function
<LoggingFilter()> _
Public Function About()
ViewData("Title") = "About Page"
Return View()
End Function
<LoggingFilter()> _
Public Function ClickMe()
clicked = True
Return RedirectToAction("Index")
End Function
End Class
public class HomeController : Controller
{
static Boolean clicked = false;
[LoggingFilter]
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (clicked == true)
{
ViewData["Click"] = "You clicked this button.";
clicked = false;
}
return View();
}
[LoggingFilter]
public ActionResult About()
{
ViewData["Title"] = "About Page";
return View();
}
[LoggingFilter]
public ActionResult ClickMe()
{
clicked = true;
return RedirectToAction("Index");
}
}
| Note: |
| If you want to apply an action filter to all action methods of a controller, you can mark the controller with the filter attribute. This is the same as marking every action method with the attribute. |
Executing Code Before and After an Action from Within a Controller
The ASP.NET MVC Controller class defines OnActionExecuting and OnActionExecuted methods that you can override. When you override one or both of these methods, your logic will execute before or after all action methods of that controller. This functionality is like action filters, but the methods are controller-scoped.
The following example shows controller-level OnActionExecuting and OnActionExecuted methods that apply to all action methods in the controller.
Public Class HomeController
Inherits Controller
Shared clicked As Boolean = False
Public Function Index()
ViewData("Title") = "Home Page"
ViewData("Message") = "Welcome to ASP.NET MVC!"
If clicked = True Then
ViewData("Click") = "You clicked this button."
clicked = False
End If
Return View()
End Function
Public Function About()
ViewData("Title") = "About Page"
Return View()
End Function
Public Function ClickMe()
clicked = True
Return RedirectToAction("Index")
End Function
Protected Overrides Sub OnActionExecuting(ByVal filterContext _
As ActionExecutingContext)
filterContext.HttpContext.Trace.Write("Action Executing: " & _
filterContext.ActionMethod.Name)
If clicked = True Then
filterContext.HttpContext.Trace.Write("Button clickced")
End If
MyBase.OnActionExecuting(filterContext)
End Sub
Protected Overrides Sub OnActionExecuted(ByVal filterContext _
As ActionExecutedContext)
If Not filterContext.Exception Is Nothing Then
filterContext.HttpContext.Trace.Write("Exception thrown")
End If
MyBase.OnActionExecuted(filterContext)
End Sub
End Class
public class HomeController : Controller
{
static Boolean clicked = false;
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (clicked == true)
{
ViewData["Click"] = "You clicked this button.";
clicked = false;
}
return View();
}
public ActionResult About()
{
ViewData["Title"] = "About Page";
return View();
}
public ActionResult ClickMe()
{
clicked = true;
return RedirectToAction("Index");
}
protected override void OnActionExecuting(ActionExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Action Executing: " +
filterContext.ActionMethod.Name);
if (clicked == true)
filterContext.HttpContext.Trace.Write("Button clickced");
base.OnActionExecuting(filterContext);
}
protected override void OnActionExecuted(ActionExecutedContext
filterContext)
{
if (filterContext.Exception != null)
filterContext.HttpContext.Trace.Write("Exception thrown");
base.OnActionExecuted(filterContext);
}
}
Scope of Action Filters
In addition to marking individual action methods with an action filter, you can mark a controller class as a whole with an action filter. In that case, the filter applies to all action methods of that controller.
Additionally, if your controller derives from another controller, the base controller might have its own action-filter attributes. Likewise, if your controller overrides an action method from a base controller, the method might have its own action-filter attributes and those it inherits from the overridden action method.
To make it easier to understand how action filters work together, action methods are grouped into scopes. A scope defines where the attribute applies, such as whether it marks a class or a method, and whether it marks a base class or a derived class.
Order of Execution for Action Filters
Each action filter has an Order property, which is used to determine the order that filters are executed in the scope of the filter. The Order property takes an integer value that must be 0 (default) or greater (with one exception). Omitting the Order property gives the filter an order value of -1, which indicates an unspecified order. Any action filters in a scope whose Order property is set to -1 will be executed in a nondeterministic order, but before the filters that have a specified order.
When an Order property of a filter is specified, it must be set to a unique value in a scope. If two or more action filters in a scope have the same Order property value, an exception is thrown.
Action filters are executed in an order that meets the following constraints. If more than one ordering fulfills all these constraints, the selected ordering is undetermined.
1. The implementation of the OnActionExecuting and OnActionExecuted methods on the controller always go first. For more information, see Executing Code Before and After an Action from Within a Controller.
2. Unless the Order property explicitly set, an action filter has an implied order of -1.
3. If the order property of multiple action filters are explicitely set, the one with the lowest value executes before those with greater values, as shown in the following example.
<Filter1(Order = 2)> _
<Filter2(Order = 3)> _
<Filter3(Order = 1)> _
Public Sub Index()
View("Index")
End Sub
[Filter1(Order = 2)]
[Filter2(Order = 3)]
[Filter3(Order = 1)]
public void Index()
{
View("Index");
}
4. If two action filters have the same Order property value, and if one action filter is defined on a type and the other action filter is defined on a method, the action filter defined on the type executes first.
<FilterType(Order = 1)> _
Public Class MyController
<FilterMethod(Order = 1)> _
Public Sub Index()
View("Index")
End Sub
End Class
[FilterType(Order = 1)]
public class MyController
{
[FilterMethod(Order = 1)]
public void Index()
{
View("Index");
}
}
In this example, FilterType executes before FilterMethod.
Example of Action Filter order of Execution
The following example shows an MVC application that contains two action filters. The DebugFilter filter writes trace messages, and the ThrowExceptionFilter filter causes an exception. The application also contains a base controller, a derived controller, and a view.
The following example shows the class that defines the DebugFilter filter. The filter uses some static methods and properties to trace filter depth and to control indentation of the output.
public class DebugFilterAttribute : ActionFilterAttribute
{
public static void Reset()
{
counter = 1;
indent = 0;
incrementIndex = true;
}
public static int Counter
{
get
{
return counter++;
}
}
static int counter
{
get
{
return (int)(HttpContext.Current.Items["counter"] ?? 1);
}
set
{
HttpContext.Current.Items["counter"] = value;
}
}
static int indent
{
get
{
return (int)(HttpContext.Current.Items["indent"] ?? 1);
}
set
{
HttpContext.Current.Items["indent"] = value;
}
}
static bool incrementIndex
{
get
{
return (bool)(HttpContext.Current.Items["incrementIndex"] ?? true);
}
set
{
HttpContext.Current.Items["incrementIndex"] = value;
}
}
public string Message { get; set; }
public int Id { get; set; }
public override void OnActionExecuting(ActionExecutingContext
filterContext)
{
HttpContext.Current.Trace.Write(
"Action Filter",
string.Format("{0}: {3}(PRE) DebugFilter.OnActionExecuting - order={1} Message='{2}'",
Counter,
this.Order,
this.Message,
Indent)
);
}
public override void OnActionExecuted(ActionExecutedContext
filterContext)
{
HttpContext.Current.Trace.Write(
"Action Filter",
string.Format("{0}: {3}(POST) DebugFilter.OnActionExecuted - order={1} Message='{2}'",
Counter,
this.Order,
this.Message,
Indent)
);
}
public static string Indent
{
get
{
indent += (incrementIndex ? 1 : -1);
string indentText = string.Empty;
for (int i = 0; i < indent; i++)
indentText += " ";
return indentText;
}
}
public static void StartDecrement()
{
incrementIndex = false;
}
}
The following example shows a class that defines the base controller with action filters applied.
[DebugFilter(Message = "(CONTROLLER) MyBaseController", order = 1)]
[DebugFilter(Message = "(CONTROLLER) MyBaseController", order=2)]
public class MyBaseController : Controller
{
[DebugFilter(Message = "(ACTION) MyBaseController.Index()", order=2)]
[DebugFilter(Message = "(ACTION) MyBaseController.Index()", order=1)]
public virtual ActionResult Index()
{
return View();
}
}
The following example shows a class that defines the derived controller with action filters applied. Notice that this controller implements its OnActionExecuting and OnActionExecuted methods.
[DebugFilter(Message = "(CONTROLLER) MyDerivedController", order = 2)]
[DebugFilter(Message = "(CONTROLLER) MyDerivedController", order=1)]
public class MyDerivedController : MyBaseController
{
[DebugFilter(Message = "(ACTION) MyDerivedController.Index()", order=1)]
[DebugFilter(Message = "(ACTION) MyDerivedController.Index()", order = 2)]
// Uncomment the following line to cause an exception to be
// thrown and to see what happens in the trace messages.
//[ThrowExceptionFilter(Message = "(ACTION) Exception thrown!", order=3)]
public override ActionResult Index()
{
base.Index();
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(ACTION) MyDerivedController.Index()",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
DebugFilterAttribute.StartDecrement();
return View();
}
protected override void OnActionExecuting(ActionExecutingContext
filterContext)
{
// Processing begins here.
DebugFilterAttribute.Reset();
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(PRE) MyDerviedController.OnActionExecuting VIRTUAL METHOD",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
}
protected override void OnActionExecuted(ActionExecutedContext
filterContext)
{
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(POST) MyDerviedController.OnActionExecuted VIRTUAL METHOD",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
if (filterContext.Exception != null)
filterContext.ExceptionHandled = true;
// Processing ends here.
((MyDerivedController)filterContext.Controller).View("Index");
}
}
The following example shows the Index view for the application whose Trace property is set to true.
<%@ Page Language="C#" CodeBehind="Index.aspx.cs"
Inherits="ActionFilterTests.Views.MyDerived.Index" Trace="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Attribute Filter Test</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Hello World
</div>
</form>
</body>
</html>
The following example shows the output trace messages that are displayed when this application runs.
(PRE) MyDerviedController.OnActionExecuting VIRTUAL METHOD (PRE) DebugFilter.OnActionExecuting - order=1 Message='(CONTROLLER) MyBaseController (PRE) DebugFilter.OnActionExecuting - order=2 Message='(CONTROLLER) MyBaseController (PRE) DebugFilter.OnActionExecuting - order=1 Message='(CONTROLLER) MyDerivedController (PRE) DebugFilter.OnActionExecuting - order=2 Message='(CONTROLLER) MyDerivedController (PRE) DebugFilter.OnActionExecuting - order=1 Message='(ACTION) MyBaseController.Index() (PRE) DebugFilter.OnActionExecuting - order=2 Message='(ACTION) MyBaseController.Index() (PRE) DebugFilter.OnActionExecuting - order=1 Message='(ACTION) MyDerivedController.Index() (PRE) DebugFilter.OnActionExecuting - order=2 Message='(ACTION) MyDerivedController.Index() (ACTION) MyDerivedController.Index() 0.010142769541939 0.008739 (POST) DebugFilter.OnActionExecuted - order=2 Message='(ACTION) MyDerivedController.Index() (POST) DebugFilter.OnActionExecuted - order=1 Message='(ACTION) MyDerivedController.Index() (POST) DebugFilter.OnActionExecuted - order=2 Message='(ACTION) MyBaseController.Index() (POST) DebugFilter.OnActionExecuted - order=1 Message='(ACTION) MyBaseController.Index() (POST) DebugFilter.OnActionExecuted - order=2 Message='(CONTROLLER) MyDerivedController (POST) DebugFilter.OnActionExecuted - order=1 Message='(CONTROLLER) MyDerivedController (POST) DebugFilter.OnActionExecuted - order=2 Message='(CONTROLLER) MyBaseController (POST) DebugFilter.OnActionExecuted - order=1 Message='(CONTROLLER) MyBaseController (POST) MyDerviedController.OnActionExecuted VIRTUAL METHOD
See Also
Controllers and Controller Actions
ASP.NET Model View Controller Applications
How to: Create an Action Filter in Visual Studio
[MVC]ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器
摘要
本文将对“MVC公告发布系统”的发布公告功能添加日志功能和异常处理功能,借此来讨论ASP.NET MVC中拦截器的使用方法。
一个小难题
我们继续完善“MVC公告发布系统”,这次,我们的需求是对公告发布功能添加日志记录能力,即在发布公告前,记录一次,在公告发布成功后,再记录一次。然后还要使得其具备异常处理,即当业务组件出现问题时,跳转到相应的错误页面并显示相应提示。
有人可能笑了,这有什么难的,在DoRelease这个Action的开始和结束处各加入相应日志功能不久结了。异常处理更不在话下,直接try…catch搞定。
没错,以上方法确实行得通,但是存在以下两点问题:
1.代码重复问题。很多日志处理代码和异常处理代码是很相似的,这样就导致了各个Action中存在大量重复代码。
2.职责被破坏。不要忘了,我们的Controller仅仅是控制器,它应该只负责表示逻辑,而不应该被一大堆日志处理代码和try…catch块包围。我们要的Action,应该是干净的、工整的、仅包含表示逻辑的Action。
以上两点,造成了我们系统中的坏味代码。那么,怎么解决这个问题呢?
从厨师到AOP
先来想象一个场景:饭店里的高级厨师怎么工作?我们知道,他不用洗菜切菜、不用端着盘子送菜、如果发现手里牛肉变质了他更不用拿着牛肉去找肉店老板理论,他的工作很单一:炒菜。
当原料送来后,有专门的顺菜切菜工进行洗菜、切菜,然后把处理好的菜送给厨师,厨师只管下锅炒,炒完了送菜自然也不必关心,因为有专门的服务员负责这事。如果发现牛肉变质了,它只管说一声,自然有相应的人处理这事。
这个场景就是典型的AOP(面向切面编程)。厨师可以看成是业务组件,它有个方法就是“炒菜”,但是炒菜前要切菜,炒完了要有人送菜,可这不是厨师该关心 的事啊!于是我们的切菜工和服务员就相当于拦截器,其中切菜工在炒菜前拦截,进行切菜,服务员在炒菜后拦截,负责送菜。当然,我们还有个异常拦截器:处理 问题的人,就是那个当厨师发现肉变质了喊一声,就来处理的人。
基于这个场景,我们看看这样有什么好处。首先是厨师职责单一了,他可以专注于自己的工作:炒菜,而不必理会不该自己关心的问题。而且“拦截器们”可以复用 的,例如一个抠门的老板完全可以找3个厨师但是只招一名服务员,反正一名服务员就可以给三名厨师端菜,这样,拦截器的复用使得代码重复不见了!
回来
好的,现在回到我们的“MVC公告发布系统”。相信看了上面的场景,你的灵感一定来了:对啊,Action不就是厨师吗,如果我们可以将日志功能做成拦截 器,在DoRelease执行前先拦截一次完成记录日志功能,DoRelease执行后再拦截一次记录一次日志。最好还有个拦截器,在Action发生异 常的时候可以拦截处理(就像上文处理变质牛肉的人),不就搞定了吗。
可是要怎么实现拦截Action呢?真是幸运之极,ASP.NET MVC框架中内置了这种机制!哈哈,我们赶快来做吧!
实现拦截器
在ASP.NET MVC中,有三种拦截器:Action拦截器、Result拦截器和Exception拦截器。我要用到第一种和第三种。其实所谓的ASP.NET MVC拦截器,也没什么神秘的,就是一个普通的类而已。只不过需要继承FilterAttribute基类,Action拦截器还要实现IActionFilter接口,而Exception拦截器需要实现IExceptionFilter接口。
我们先来看实现:让我们在Controllers目录下新建一个Filters目录,然后在Filters下新建两个类,一个叫LoggerFilter一个叫ExceptionFilter。首先是LoggerFilter的代码。
LoggerFilter.cs:
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Web;5
using System.Web.Mvc;6
using System.Web.Mvc.Ajax;7

8
namespace MVCDemo.Controllers.Filters9
{10
public class LoggerFilter : FilterAttribute, IActionFilter11
{12
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)13
{14
filterContext.Controller.ViewData["ExecutingLogger"] = "正要添加公告,已以写入日志!时间:" + DateTime.Now; 15
}16

17
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)18
{19
filterContext.Controller.ViewData["ExecutedLogger"] = "公告添加完成,已以写入日志!时间:" + DateTime.Now;20
}21
}22
}
可以看到,这个类继承了FilterAttribute并实现了IActionFilter。其中关键是IActionFilter,它有两个方 法,OnActionExecuting在被拦截Action前执行,OnActionExecuted在被拦截Action后执行。两个方法都有一个参 数,虽然类型不同,但其实都是一个作用:被拦截Action的上下文。
这个地方我得解释一下,你拦截器拦截了Action,在做处理时难免要用到被拦截Action相关的东西,例如在我们的例子中,就需要想被拦截 Action所在Controller的ViewData中添加内容,所以,拦截器方法有一个参数表示被拦截Action的上下文是顺理成章的事。
下面再看ExceptionFilter这个拦截器,它是在Action出现异常时发挥作用的。
ExceptionFilter.cs:
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Web;5
using System.Web.Mvc;6
using System.Web.Mvc.Ajax;7

8
namespace MVCDemo.Controllers.Filters9
{10
public class ExceptionFilter : FilterAttribute,IExceptionFilter11
{12
void IExceptionFilter.OnException(ExceptionContext filterContext)13
{14
filterContext.Controller.ViewData["ErrorMessage"] = filterContext.Exception.Message;15
filterContext.Result = new ViewResult()16
{17
ViewName = "Error",18
ViewData = filterContext.Controller.ViewData,19
};20
filterContext.ExceptionHandled = true;21
}22
}23
}
异常拦截器一样需要继承FilterAttribute,但是不要实现IActionFilter,而是要实现IExceptionFilter接口,这 个接口只有一个方法:OnException,顾名思义,当然是发生异常时被调用了。我们看看我让它做了什么:首先将异常信息 (ExceptionContext一样也是上下文,而其成员的Exception就是一个Exception类型的实例,就是被抛出的异常)记录到 ViewData相应的键值里,然后我们要呈现Error这个视图。
注意!这里已经不是Controller里了,而是另一个类,所以当然不能调用View方法返回ViewResult实例了。我们只好新建一个ViewResult实例,并将其视图名设为Error,将上下文中的DataView传过去。
最后那行filterContext.ExcepitonHandled = true;很重要,这行的意思是告诉系统,异常已经处理,不要再次处理了。
应用拦截器
好了,拦截器建立完了,要怎么应用到相应的Action上呢?如果你使用过Spring,你一定对其AOP是实现之麻烦深有感触,如果你和我一样讨厌写各 种XML的话,你真是太幸福了。因为在ASP.NET MVC中,应用拦截器简直是轻松加愉快。只要将拦截器当做Attribute写在要应用此拦截器的Action上就行了。看代码。
AnnounceController.cs:
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Web;5
using System.Web.Mvc;6
using System.Web.Mvc.Ajax;7
using MVCDemo.Models;8
using MVCDemo.Models.Interfaces;9
using MVCDemo.Models.Entities;10
using MVCDemo.Controllers.Filters;11

12
namespace MVCDemo.Controllers13
{14
public class AnnounceController : Controller15
{16
public ActionResult Release()17
{18
ICategoryService cServ = ServiceBuilder.BuildCategoryService();19
List<CategoryInfo> categories = cServ.GetAll();20
ViewData["Categories"] = new SelectList(categories, "ID", "Name");21
return View("Release");22
}23

24
[LoggerFilter()]25
[ExceptionFilter()]26
public ActionResult DoRelease()27
{28
AnnounceInfo announce = new AnnounceInfo()29
{30
ID = 1,31
Title = Request.Form["Title"],32
Category = Int32.Parse(Request.Form["Category"]),33
Content = Request.Form["Content"],34
};35

36
IAnnounceService aServ = ServiceBuilder.BuildAnnounceService();37
aServ.Release(announce);38

39
ViewData["Announce"] = announce;40

41
System.Threading.Thread.Sleep(2000);42
ViewData["Time"] = DateTime.Now;43
System.Threading.Thread.Sleep(2000);44

45
return View("ReleaseSucceed");46
}47
}48
}
看到没有,只要在DoRelease上写这么两个Attribute,一切就完成了,至于什么时候该调用什么拦截器,都是框架帮你完成了。注意一点,为了 让我们看出拦截器的时序,我们在DoRelease中加了一点东西,就是加了一个ViewData["Time"],里面记录了执行此Action的时 间,因为日志拦截器在前后都会记录时间,我们通过比较时间就可以看出执行顺序了。至于那两个Sleep则是让效果更明显的,这行代码的意思是让程序在这里 延迟2秒。
要执行这个程序,我们还要改一下ReleaseSucceed.aspx视图,其实就是加几个地方显示ViewData里相应的数据。
ReleaseSucceed.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReleaseSucceed.aspx.cs" Inherits="MVCDemo.Views.Announce.ReleaseSucceed" %>2
<%@ Import Namespace="MVCDemo.Models.Entities" %>3

4
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">5

6
<html xmlns="http://www.w3.org/1999/xhtml" >7
<head runat="server">8
<title></title>9
</head>10
<body>11
<% AnnounceInfo announce = ViewData["Announce"] as AnnounceInfo; %>12
<div>13
<h1>MVC公告发布系统——发布公告成功</h1>14
<dl>15
<dt>ID:</dt>16
<dd><%= announce.ID %></dd>17
<dt>标题:</dt>18
<dd><%= announce.Title %></dd>19
<dt>类别ID:</dt>20
<dd><%= announce.Category %></dd>21
<dt>内容:</dt>22
<dd><%= announce.Content %></dd>23
<dt>发布时间:</dt>24
<dd><%= ViewData["Time"] %></dd>25
</dl>26
<p><%= ViewData["ExecutingLogger"] %></p>27
<p><%= ViewData["ExecutedLogger"] %></p>28
</div>29
</body>30
</html>
现在可以提交一则公告看结果了:
下面我们来看看异常拦截器的效果。要触发异常拦截器,首先要抛出一个异常,所以,我们在业务逻辑组件做点手脚。将MockAnnounceServices的Release方法改成如下:
/// <summary>2
/// 发布公告3
/// </summary>4
/// <param name="announce"></param>5
public void Release(AnnounceInfo announce)6
{7
throw new Exception("发布公告失败了!原因?没有原因!我是业务组件,我说失败就失败!");8
return;9
} 另外,我们还要实现一个Error.aspx视图,这是在异常拦截器中定义的错误视图。我们将它新建在Views/Shared下就可以了。顺便说一下, 共用的视图一般放在Shared下,因为ASP.NET MVC的视图寻找机理是当与Controller同名目录下不存在时,就到Shared下看看有没有此视图。
Error.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Error.aspx.cs" Inherits="MVCDemo.Views.Shared.Error" %>2

3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4

5
<html xmlns="http://www.w3.org/1999/xhtml" >6
<head runat="server">7
<title></title>8
</head>9
<body>10
<div>11
<h1>系统发生异常</h1>12
<%= ViewData["ErrorMessage"] %>13
</div>14
</body>15
</html>好了,现在我们再提交新公告,会返回如下结果:
我们再回过头看看,使用了拦截器后,代码是不是很清晰呢。
小结
通过本文,朋友们应该可以掌握拦截器的基本使用以及使用它在表示层实现AOP了。下一篇作为本系列的终结篇,将对ASP.NET MVC做一个全面的讨论,并与Web Form模型进行一个比较,使朋友们看清其优势、劣势,从而更好的学习使用这个框架。
[SQLServer]SQL Server数据导入导出资料大全
大家打开这个链接可以看到很多数据库的连接方法。http://www.connectionstrings.com
这些数据库之间的数据交换就是这个贴子所要总结的内容。
(一)SQL Server之间
把远程数据库中的数据导入到本地数据库。
http://community.csdn.net/Expert/topic/5079/5079649.xml?temp=.7512018
http://community.csdn.net/Expert/topic/5011/5011278.xml?temp=.1658899
http://community.csdn.net/Expert/topic/4982/4982625.xml?temp=.8189966
把A库里的其中几个表和视图导入B库
http://community.csdn.net/Expert/topic/5042/5042648.xml?temp=.2556574
SQL2005的数据库导入SQL2000中
http://community.csdn.net/Expert/topic/4954/4954820.xml?temp=.3408625
在SQL2005中 如何导入 SQL2000中的Analysis Service ?
http://community.csdn.net/Expert/topic/4713/4713032.xml?temp=2.752322E-02
英文版sql server2005中bcp导出中文乱码问题
http://community.csdn.net/Expert/topic/5024/5024662.xml?temp=.7404596
如何将一个由SQL保存出来的*.bas文件再导回到SQL中
http://community.csdn.net/Expert/topic/4944/4944630.xml?temp=.8225672
(二)SQL Server –> Access
将SQL数据导出至Access(SQL与Access同一台机器上)
http://community.csdn.net/Expert/topic/4919/4919937.xml?temp=.2461359
将SQL数据导出至Access(SQL与Access不在同一台机器上)
http://community.csdn.net/Expert/topic/4906/4906691.xml?temp=.1377222
http://community.csdn.net/Expert/topic/4917/4917015.xml?temp=.7591364
(三)Access –> SQL Server
http://faq.csdn.net/FAQUnfurl.aspx?id=214875
为什么access与SQLServer2000导入导出时,数据库结构变了,默认主键,自动编号全没了?
http://community.csdn.net/Expert/topic/4712/4712570.xml?temp=.3942224
(四)txt(记事本)–> SQL Server
http://community.csdn.net/Expert/topic/5045/5045602.xml?temp=.0278284
TXT文件导入数据库出现乱码
http://community.csdn.net/Expert/topic/4939/4939026.xml?temp=.4465296
关于上千份大文本存入SQLServer
http://community.csdn.net/Expert/topic/4973/4973969.xml?temp=.4392816
(五)SQL Server –> txt
http://community.csdn.net/Expert/topic/4906/4906039.xml?temp=.6642267
SQL导出TXT或HTML求助
http://community.csdn.net/Expert/topic/5031/5031048.xml?temp=1.302737E-02
(六)Excel –> SQL Server
http://community.csdn.net/Expert/topic/5002/5002120.xml?temp=.4375727
http://community.csdn.net/Expert/topic/5086/5086098.xml?temp=.6402094
http://community.csdn.net/Expert/topic/4940/4940738.xml?temp=.8665125
http://community.csdn.net/Expert/topic/4938/4938969.xml?temp=1.918972E-03
http://community.csdn.net/Expert/topic/4892/4892120.xml?temp=.1775324
使用Excel导入数据库时,遇到这么个奇怪的问题,当Excel的一列中的数据类型明显不同时就会直接eof,??
http://community.csdn.net/Expert/topic/4929/4929620.xml?temp=.2570154
(七)DBF –> SQL Server
http://community.csdn.net/Expert/topic/5070/5070623.xml?temp=6.957644E-02
其他问题
怎样把数据库中的题目经过vb 导到word
http://faq.csdn.net/FAQUnfurl.aspx?id=215243
使用作业来完成DTS操作。
http://community.csdn.net/Expert/topic/5046/5046974.xml?tep=.9785425
还可以看看这个链接
http://blog.csdn.net/dutguoyi/archive/2006/10/16/1337274.aspx
xml –> sql server
http://community.csdn.net/Expert/topic/5041/5041228.xml?temp=.8233911
oracle –> sql server
http://community.csdn.net/Expert/topic/5019/5019542.xml?temp=2.604312E-02
http://support.microsoft.com/kb/320125
http://fufun.cn/show.aspx?id=dC8yMDAyMDUzMC8xNS83NjUxOTEuaHRtbA_x003D__x003D_
在用Bulk Insert导入数据时的日期时间格式问题,
原因:bulk insert 不能转换数据类型,如果时间格式不正确就会出错。
http://community.csdn.net/Expert/topic/5100/5100692.xml?temp=.0559656
Excel –> SQL Server
导入时添加额外列,
例如 EXECL表的结构为 名称,内容,类别,
SQLServer表的结构为 名称,内容,类别,属性
http://community.csdn.net/Expert/topic/5105/5105613.xml?temp=.3277399
补上
Excel –> SQL Server
导入时列名调整补充
http://community.csdn.net/Expert/topic/5086/5086098.xml?temp=.5973932
SQL Server 2005 –> SQL Server 2000
http://dev.csdn.net/author/taito/840c28a03ec0432492db18a329125bb5.html
http://community.csdn.net/Expert/topic/4954/4954820.xml?temp=.495083
SQL Server 2005 –> SQL Server 2000
用sql2005的导入导出工具将所有SQL2005的表和数据导出到SQL2000下,但是所有的主键、索引、关系、默认值全部丢了。
http://community.csdn.net/Expert/topic/4905/4905590.xml?temp=6.176394E-02
MySql –> SQL Server
http://topic.csdn.net/t/20031203/09/2521118.html
http://topic.csdn.net/t/20030407/11/1627991.html
SQL Server –> DB2
http://www.21cnvip.com/csdn/default.aspx?q=20021105/10/1149089.html
大家可以在下面的链接来搜索CSDN技术社区文档,很大的技术宝藏啊。
http://search.csdn.net/search/null/1/dev/
SQL Server 2000 –> SQL Server 7.0
SQL2000数据导入到SQL7,那些设置为主键的没有了
http://community.csdn.net/Expert/topic/5004/5004254.xml?temp=.1570246
SQL Server 2005 –> SQL Server 2000
2005导出的脚本为什么在2000运行总是出错?
http://community.csdn.net/Expert/topic/4682/4682496.xml?temp=.6038324
SQL Server之间复制数据库
http://community.csdn.net/Expert/topic/4835/4835266.xml?temp=.7495233
SQL Server 2000 –> SQL Server 2000
DTS包的制作
http://community.csdn.net/Expert/topic/5006/5006594.xml?temp=.2426111
SQL Server 2005 –> Excel
数据长度为255,出错
http://community.csdn.net/Expert/topic/4951/4951804.xml?temp=.2144739
SQL Server 2005 –> SQL Server 2000
http://community.csdn.net/Expert/topic/5089/5089204.xml?temp=.4461328
SQL Server 2000 –> SQL Server 2000
导出表的所有结构、所有数据
http://community.csdn.net/Expert/topic/5092/5092752.xml?temp=.8595545
From: http://blog.csai.cn/user1/19065/archives/2006/8916.html
[Java]JavaEye网站12月期刊
同时我们还提供了12月论坛热点的PDF电子杂志,点击下载:http://www.javaeye.com/topics/download/7307b3d8-e1cb-323d-8d49-5b2dfe3d5546

[XML]在C#.net中如何操作XML
在C#.net中如何操作XML
需要添加的命名空间:
using System.Xml;
定义几个公共对象:
XmlDocument xmldoc ;
XmlNode xmlnode ;
XmlElement xmlelem ;
1,创建到服务器同名目录下的xml文件:
方法一:
xmldoc = new XmlDocument ( ) ;
//加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?>
XmlDeclaration xmldecl;
xmldecl = xmldoc.CreateXmlDeclaration("1.0","gb2312",null);
xmldoc.AppendChild ( xmldecl);
//加入一个根元素
xmlelem = xmldoc.CreateElement ( "" , "Employees" , "" ) ;
xmldoc.AppendChild ( xmlelem ) ;
//加入另外一个元素
for(int i=1;i<3;i++)
{
XmlNode root=xmldoc.SelectSingleNode("Employees");//查找<Employees>
XmlElement xe1=xmldoc.CreateElement("Node");//创建一个<Node>节点
xe1.SetAttribute("genre","李赞红");//设置该节点genre属性
xe1.SetAttribute("ISBN","2-3631-4");//设置该节点ISBN属性
XmlElement xesub1=xmldoc.CreateElement("title");
xesub1.InnerText="CS从入门到精通";//设置文本节点
xe1.AppendChild(xesub1);//添加到<Node>节点中
XmlElement xesub2=xmldoc.CreateElement("author");
xesub2.InnerText="候捷";
xe1.AppendChild(xesub2);
XmlElement xesub3=xmldoc.CreateElement("price");
xesub3.InnerText="58.3";
xe1.AppendChild(xesub3);
root.AppendChild(xe1);//添加到<Employees>节点中
}
//保存创建好的XML文档
xmldoc.Save ( Server.MapPath("data.xml") ) ;
//////////////////////////////////////////////////////////////////////////////////////
结果:在同名目录下生成了名为data.xml的文件,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
</Employees>
方法二:
XmlTextWriter xmlWriter;
string strFilename = Server.MapPath("data1.xml") ;
xmlWriter = new XmlTextWriter(strFilename,Encoding.Default);//创建一个xml文档
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Employees");
xmlWriter.WriteStartElement("Node");
xmlWriter.WriteAttributeString("genre","李赞红");
xmlWriter.WriteAttributeString("ISBN","2-3631-4");
xmlWriter.WriteStartElement("title");
xmlWriter.WriteString("CS从入门到精通");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("author");
xmlWriter.WriteString("候捷");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("price");
xmlWriter.WriteString("58.3");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Close();
//////////////////////////////////////////////////////////////////////////////////////
结果:
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
</Employees>
2,添加一个结点:
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load(Server.MapPath("data.xml"));
XmlNode root=xmlDoc.SelectSingleNode("Employees");//查找<Employees>
XmlElement xe1=xmlDoc.CreateElement("Node");//创建一个<Node>节点
xe1.SetAttribute("genre","张三");//设置该节点genre属性
xe1.SetAttribute("ISBN","1-1111-1");//设置该节点ISBN属性
XmlElement xesub1=xmlDoc.CreateElement("title");
xesub1.InnerText="C#入门帮助";//设置文本节点
xe1.AppendChild(xesub1);//添加到<Node>节点中
XmlElement xesub2=xmlDoc.CreateElement("author");
xesub2.InnerText="高手";
xe1.AppendChild(xesub2);
XmlElement xesub3=xmlDoc.CreateElement("price");
xesub3.InnerText="158.3";
xe1.AppendChild(xesub3);
root.AppendChild(xe1);//添加到<Employees>节点中
xmlDoc.Save ( Server.MapPath("data.xml") );
//////////////////////////////////////////////////////////////////////////////////////
结果:在xml原有的内容里添加了一个结点,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="张三" ISBN="1-1111-1">
<title>C#入门帮助</title>
<author>高手</author>
<price>158.3</price>
</Node>
</Employees>
3,修改结点的值(属性和子结点):
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNodeList nodeList=xmlDoc.SelectSingleNode("Employees").ChildNodes;//获取Employees节点的所有子节点
foreach(XmlNode xn in nodeList)//遍历所有子节点
{
XmlElement xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型
if(xe.GetAttribute("genre")=="张三")//如果genre属性值为“张三”
{
xe.SetAttribute("genre","update张三");//则修改该属性为“update张三”
XmlNodeList nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode xn1 in nls)//遍历
{
XmlElement xe2=(XmlElement)xn1;//转换类型
if(xe2.Name=="author")//如果找到
{
xe2.InnerText="亚胜";//则修改
}
}
}
}
xmlDoc.Save( Server.MapPath("data.xml") );//保存。
//////////////////////////////////////////////////////////////////////////////////////
结果:将原来的所有结点的信息都修改了,xml的内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="update张三" ISBN="1-1111-1">
<title>C#入门帮助</title>
<author>亚胜</author>
<price>158.3</price>
</Node>
</Employees>
4,修改结点(添加结点的属性和添加结点的自结点):
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNodeList nodeList=xmlDoc.SelectSingleNode("Employees").ChildNodes;//获取Employees节点的所有子节点
foreach(XmlNode xn in nodeList)
{
XmlElement xe=(XmlElement)xn;
xe.SetAttribute("test","111111");
XmlElement xesub=xmlDoc.CreateElement("flag");
xesub.InnerText="1";
xe.AppendChild(xesub);
}
xmlDoc.Save( Server.MapPath("data.xml") );
//////////////////////////////////////////////////////////////////////////////////////
结果:每个结点的属性都添加了一个,子结点也添加了一个,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4" test="111111">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
<flag>1</flag>
</Node>
<Node genre="李赞红" ISBN="2-3631-4" test="111111">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
<flag>1</flag>
</Node>
<Node genre="update张三" ISBN="1-1111-1" test="111111">
<title>C#入门帮助</title>
<author>亚胜</author>
<price>158.3</price>
<flag>1</flag>
</Node>
</Employees>
5,删除结点中的某一个属性:
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNodeList xnl=xmlDoc.SelectSingleNode("Employees").ChildNodes;
foreach(XmlNode xn in xnl)
{
XmlElement xe=(XmlElement)xn;
xe.RemoveAttribute("genre");//删除genre属性
XmlNodeList nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode xn1 in nls)//遍历
{
XmlElement xe2=(XmlElement)xn1;//转换类型
if(xe2.Name=="flag")//如果找到
{
xe.RemoveChild(xe2);//则删除
}
}
}
xmlDoc.Save( Server.MapPath("data.xml") );
//////////////////////////////////////////////////////////////////////////////////////]
结果:删除了结点的一个属性和结点的一个子结点,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node ISBN="2-3631-4" test="111111">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node ISBN="2-3631-4" test="111111">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node ISBN="1-1111-1" test="111111">
<title>C#入门帮助</title>
<author>亚胜</author>
<price>158.3</price>
</Node>
</Employees>
6,删除结点:
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNode root=xmlDoc.SelectSingleNode("Employees");
XmlNodeList xnl=xmlDoc.SelectSingleNode("Employees").ChildNodes;
for(int i=0;i<xnl.Count;i++)
{
XmlElement xe=(XmlElement)xnl.Item(i);
if(xe.GetAttribute("genre")=="张三")
{
root.RemoveChild(xe);
if(i<xnl.Count)i=i-1;
}
}
xmlDoc.Save( Server.MapPath("data.xml") );
//////////////////////////////////////////////////////////////////////////////////////]
结果:删除了符合条件的所有结点,原来的内容:
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="张三" ISBN="1-1111-1">
<title>C#入门帮助</title>
<author>高手</author>
<price>158.3</price>
</Node>
<Node genre="张三" ISBN="1-1111-1">
<title>C#入门帮助</title>
<author>高手</author>
<price>158.3</price>
</Node>
</Employees>
删除后的内容:
<?xml version="1.0" encoding="gb2312"?>
<Employees>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
<Node genre="李赞红" ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</Node>
</Employees>
7,按照文本文件读取xml
System.IO.StreamReader myFile =new
System.IO.StreamReader(Server.MapPath("data.xml"),System.Text.Encoding.Default);
//注意System.Text.Encoding.Default
string myString = myFile.ReadToEnd();//myString是读出的字符串
myFile.Close();
[Lucene]信息检索的函数库Lucene的使用总结
简单介绍:
Lucene是一个信息检索的函数库(Library),利用它你可以为你的应用加上索引和搜索的功能.
Lucene的使用者不需要深入了解有关全文检索的知识,仅仅学会使用库中的一个类,你就为你的应用实现全文检索的功能.
不过千万别以为Lucene是一个象google那样的搜索引擎,Lucene甚至不是一个应用程序,它仅仅是一个工具,一个Library.你也可以把它理解为一个将索引,搜索功能封装的很好的一套简单易用的API.利用这套API你可以做很多有关搜索的事情,而且很方便。
发展历史:参见《.NET 的 Lucene 》
详细使用帮助:http://www.lucene.com.cn/net.htm (包含了建立索引/对索引进行搜索/删除索引中的文档/更新索引中的文档/查询语句/多个条件查询)
90%的语法在上述使用帮助都可以找到答案。
上面的使用帮助对排序说明的比较少,补充如下:
可以通过 SortField 的构造参数,我们可以设置排序字段,排序条件,以及倒排。
Sort sort = new Sort(new SortField(FieldName, SortField.DOC, false));
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query, sort);
排序对搜索速度影响还是很大的,尽可能不要使用多个排序条件。
Lucene.Net的语言处理包中Lucene.Net.Analysis.Cn的Bug :http://www.cnblogs.com/dudu/archive…6/22/17783.aspx
如何联合两个索引查询 / 分布搜索:
我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。
MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@"c:\index"), IndexReader.Open(@"\\server\index") });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
或
IndexSearcher searcher1 = new IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
Hits hits = searcher.Search(query);
还可以使用 ParallelMultiSearcher 进行多线程并行搜索。
如何合并索引库?
将 directory1 合并到 directory2 中。
Directory directory1 = FSDirectory.GetDirectory("index1", false);
Directory directory2 = FSDirectory.GetDirectory("index2", false);
IndexWriter writer = new IndexWriter(directory2, analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();
关于IndexWriter和IndexReader
Add Optimize Merge操作都是由IndexWriter来做的
Delete则是通过IndexReader完成
文档有一句话“即同一时间只允许IndexWriter或IndexReader打开同一份索引.不能允许两个同时打开一份索引”
记住IndexReader并不是查询索引的时候要用的,从字面含有好像是读取,所以可以同时查询索引和写入索引。
我的使用Lucene.net成功案例:http://video.5913.com/
[Flex]利用HTTPService实现Flex与服务器端低数据量通信
Flex作为企业级的开发平台,与服务器端的通信是至关重要的。传统的Flash与服务器端主要通过HTTP、WebService和Flash Remoting方式通信,Flex除了保留了Flash平台与服务端通信方式外增加了一系列的高级服务功能。Flex与服务端通信主要分为两大类:一类 是通过传统的HTTP方式发送请求来和服务器端进行交互,另外一类则是通过LCDS等与服务端进行通信。
低数据量的通信我们一般会选择Http方式来进行通信。通过HTTP方式Flex可以与任意服务器端进行通信。通过HTTP与服务器端通信又可以通过 HTTP请求方式和WebService实现。前者使用异步的HTTP请求方式,使用方式与Ajax一致,而后者则是通过标准的WebService协议 与服务端进行通信。下面我们看下HTTPService方式的通信,查阅相关的帮助文档我们可以知道HTTPService一些常用的方法和属性:
属性
method:发送HTTP请求的方法
url : 请求服务的位置
request:发送请求的参数
requestTimeout:请求超时的时间
useProxy:是否使用代理的别名服务
方法:
send:参数为object类型默认为null,返回值类型为AsyncToken,执行一个HTTPService的请求
下面我们通过一个获取新浪体育新闻汇总的示例来说明HTTPService的使用
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="sinaSport.send()">
<mx:Style>
global
{
fontSize:14pt;
}
</mx:Style>
<mx:HTTPService id="sinaSport" url="http://rss.sina.com.cn/roll/sports/hot_roll.xml" useProxy="false">
</mx:HTTPService>
<mx:Panel x="53" y="90" width="975" height="461" layout="absolute" title="新浪体育要闻汇总 ">
<mx:DataGrid id="sportContent" x="23.5" y="10" width="911.5" dataProvider="{sinaSport.lastResult.rss.channel.item}" height="175">
<mx:columns>
<mx:DataGridColumn width="300" headerText="标题" dataField="title"/>
<mx:DataGridColumn width="150" headerText="作者" dataField="author" />
<mx:DataGridColumn width="150" headerText="日期" dataField="pubDate" />
</mx:columns>
</mx:DataGrid>
<mx:TextArea x="23" y="193" width="912" height="183" htmlText="{sportContent.selectedItem.description}"/>
<mx:LinkButton x="855" y="384" label="详细信息" click="navigateToURL(new URLRequest(sportContent.selectedItem.link))"/>
</mx:Panel>
</mx:Application>
示例运行效果如下图:

在上面的代码中通过 如下代码声明了HTTPService 数据的位置
<mx:HTTPService id="sinaSport" url="http://rss.sina.com.cn/roll/sports/hot_roll.xml" useProxy="false">
</mx:HTTPService>
通过
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="sinaSport.send()">
进行数据的发送
服务器端返回的结果则是通过sinaSport.lastResult来引用最后通过DataGrid来显示数据。
从这个简单的例子我们可以看出因为HTTPService不是标准协议,基于HTTPService的通信方式访问的数据格式是由服务端来制定的,所以在 使用中要求Flex端与服务端的数据处理方式和交换格式一致。基于HTTP协议访问一般都通过纯文本数据进行传输。Flex能够轻松的将之转换为 ActionScript对象。
Mikel

