[Entlib] Microsoft Enterprise Library 5.0 learning path -- step 9, using policyinjection module for AOP-PART4 -- Build Custom call handler to achieve user operation log record

Source: Internet
Author: User

In the previous Part3, I introduced the use of the call handler built in the Policy injection module. Today I will continue to introduce the call Handler -- custom call handler, create a m call handler to record user operation logs in the project.CodeYou can find it in the entlib. helper Project, for example:

This article will introduce the attribute M call handler method and configuration method in two ways.

 

I. Core code

To create a custom call handler, follow these steps:

1. Create a class implementation interface icallhandler.

2. Create a corresponding attribute class or implement the features for custom call handler as needed [configurationelementtype (typeof (mcmcallhandlerdata)]

First, we will introduce the specific core code. Because I want to implement the user's operation log, we need to add, delete, modify, and record user data and some special operations, such: login,

1. Create a table to store user operation records:

Create Table [DBO]. [userlog] ([ID] [int] Identity (1,1) not null, -- primary key [studentid] [int] not null, -- corresponding student ID [Message] [nvarchar] (256) not null, -- operation message [logdate] [datetime] not null, -- Record time constraint [pk_userlog] primary key clustered ([ID] ASC) with (pad_index = OFF, expiration = OFF, ignore_dup_key = OFF, allow_row_locks = on, allow_page_locks = on) on [primary]) on [primary]

2. Create a class named userlogcallhandler to implement the interface icallhandler and implement the method invoke (Specific interception operation method) and attribute order. The specific code is as follows (I have written comments to the key points.)

Using system; using system. collections. generic; using system. collections. specialized; using system. data; using system. data. common; using system. LINQ; using system. text; using Microsoft. practices. enterpriselibrary. common. configuration; using Microsoft. practices. enterpriselibrary. data; using Microsoft. practices. unity. interceptionextension; namespace entlibstudy. helper. entlibextension. policyinjectionextension {[Configurationelementtype (typeof (customcallhandlerdata)] public class userlogcallhandler: icallhandler {// <summary> // constructor, which cannot be omitted here, otherwise, an exception may occur. // </Summary> // <Param name = "attributes"> parameters configured in the configuration file </param> Public userlogcallhandler (namevaluecollection attributes) {// obtain the key from the configuration file. If the key does not exist, specify the default key this. message = string. isnullorempty (attributes ["message"])? "": Attributes ["message"]; this. parametername = string. isnullorempty (attributes ["parametername"])? "": Attributes ["parametername"];} // <summary> // constructor, this constructor is used for Attribute call // </Summary> /// <Param name = "message"> message </param> /// <Param name = "parametername"> parameter name </param> Public userlogcallhandler (string message, string parametername) {This. message = message; this. parametername = parametername;} // <summary> // implement icallhandler. invoke method, used to process the specific Interception Method // </Summary> /// <Param name = "input"> </Param> /// <Param name = "getnext"> </param> /// <returns> </returns> Public imethodreturn invoke (imethodinvocation input, getnexthandlerdelegate getnext) {// check whether the parameter has if (input = NULL) throw new argumentnullexception ("input"); If (getnext = NULL) throw new argumentnullexception ("getnext "); // start interception. You can write the specific business logic code as needed // call the specific method var result = getnext () (input, getnext ); // determine whether the intercepted method return value is of the bool type. // if it is of the bool type Determines whether the return value is false. False: indicates that the call is unsuccessful. If (result. returnvalue. getType () = typeof (bool) {If (convert. toboolean (result. returnvalue) = false) {return result ;}// operation log if (result. exception = NULL) {// obtain the user name currently logged on from cookies. If the session record is used, change it to get var uid = utils from session. getcookies ("Sid"); // if not logged on, an exception is thrown if (string. isnullorempty (UID) throw new exception ("the user has not logged on! "); // Operation additional message, used to obtain the operation record identifier var actionmessage =" "; object para = NULL; // determines whether the main parameter name of the method to be called is null, if not empty, the parameter object if (string. isnullorempty (this. parametername) = false) {para = input. inputs [this. parametername];} // determines whether the parameter object is null. If the parameter object is not null, the parameter identifier is obtained. // The tostring method of the specific parameter corresponds to this parameter, I have override the tostring method in the specific class if (para! = NULL) {actionmessage = "No.: [" + para. tostring () + "]" ;}// insert operation log database DB = dbhelper. createdatabase (); stringbuilder sb = new stringbuilder (); sb. append ("insert into userlog (studentid, message, logdate) values (@ studentid, @ message, @ logdate);"); dbcommand cmd = dB. getsqlstringcommand (sb. tostring (); dB. addinparameter (CMD, "@ studentid", dbtype. int32, UID); dB. addinparameter (CMD, "@ message", dbtype. string, this. message + actionmessage); dB. addinparameter (CMD, "@ logdate", dbtype. datetime, datetime. now); dB. executenonquery (CMD);} // return method. The return result is intercepted.} Public String message {Get; set;} Public String parametername {Get; set ;} private int _ order = 0; Public int order {get {return _ order;} set {_ order = value ;}}}}

The main part of this Code is the specific invoke method implementation. This method has two parameters:

InputThis parameter encapsulates useful information such as intercepted methods and method parameters.

GetnextA delegate is used to call the interception method. Through this delegate, We can well control how to perform specific business logic operations after intercepting specific methods.

Use getnext () (input, getnext); this code to call a method. You can decide whether to perform a specific operation before or after calling a method based on your needs.

As I want to implement a user operation record, I need to know some specific information:Who performed operations on the data?Here, I need to obtain three parameters: specific operator, operation data, and specific description.

First, let's look at the first parameter:

Specific OperatorBecause this project uses cookies to record the current login user, I can directly obtain the current login user from cookies. For details, see the code 69-71.

Operated dataHere, I have created a parametername attribute in this call handler to specify the parameter name for storing the operation data in the method intercepted by the record. For details, see line of the Code.

Because the specific parameter name is specified, we need to obtain the specific data value based on the parameter. Let's look at the added, deleted, and modified method signature:

Int add (Student );
Bool Update (Student );
Bool Delete (int id );

As you can see, we can get the data ID of the user's specific operations from these three methods, such as student. ID and ID. In this way, we only need to modify the tostring method and return the specific ID in a specific class, such as student. The Code is as follows:

 
Public override string tostring () {return this. Id. tostring ();}

In this way, in call handler, we can obtain the specific operation data based on the parameter name (If you need to describe specific data in detail, you need a more complex design, so we will not go into depth here.), The Code is as follows:

 
// Operation additional message, used to obtain the operation record identifier var actionmessage = ""; object para = NULL; // determines whether the main parameter name of the method to call is null, if not empty, the parameter object if (string. isnullorempty (this. parametername) = false) {para = input. inputs [this. parametername];} // determines whether the parameter object is null. If the parameter object is not null, the parameter identifier is obtained. // The tostring method of the specific parameter corresponds to this parameter, I have override the tostring method in the specific class if (para! = NULL) {actionmessage = "No.: [" + para. tostring () + "]";}

DescriptionThis is also a message data that is used to store the specific description of the operation.

Special CasesOf course, operation logs cannot be added, deleted, or modified only in three cases, such as logon or logout. In this case, you only need to specify the specific message, and the parameter name does not need to be specified, if there are more special cases, you need to change the design based on your specific needs. Here is just the most basic.

 

Ii. Attribute implementation

After completing the core code, we can establish the attribute interception or configuration interception as needed.

To implement attribute interception, you need to create a class to implement the handlerattribute class and implement the createhandler method to call the specific call handler method. The specific code is as follows:

 using system; using system. collections. generic; using system. LINQ; using system. text; using Microsoft. practices. unity; using Microsoft. practices. unity. interceptionextension; namespace entlibstudy. helper. entlibextension. policyinjectionextension {[attributeusage (attributetargets. method)] public class userlogcallhandlerattribute: handlerattribute {public userlogcallhandlerattribute (string message, string parametername) {This. message = message; this. parametername = parametername;} Public String message {Get; set;} Public String parametername {Get; set;} public override icallhandler createhandler (iunitycontainer container) {// create a specific call handler, and call userlogcallhandler handler = new userlogcallhandler (this. message, this. parametername); Return handler ;}}

This feature class is relatively simple, but it still needs to be processed in call handler to add a constructor to receive parameters passed from attribute:

 
/// <Summary> /// constructor, this constructor is used for Attribute call // </Summary> /// <Param name = "message"> message </param> /// <Param name = "parametername"> parameter name </param> Public userlogcallhandler (string message, string parametername) {This. message = message; this. parametername = parametername ;}

 

Iii. configuration method

If you want to configure custom call Handler through the enterprise database configuration tool, you need to add a feature to call handler:

[Configurationelementtype (typeof (mcmcallhandlerdata)]

Then add a new constructor.

/// <Summary> /// constructor, which cannot be omitted here, otherwise, an exception may occur. // </Summary> // <Param name = "attributes"> parameters configured in the configuration file </param> Public userlogcallhandler (namevaluecollection attributes) {// obtain the key from the configuration file. If the key does not exist, specify the default key this. message = string. isnullorempty (attributes ["message"])? "": Attributes ["message"]; this. parametername = string. isnullorempty (attributes ["parametername"])? "": Attributes ["parametername"];}

After completing the above two steps, we can use the enterprise database configuration tool for configuration. See:

 

Iv. Usage

FinishedCall handler coding and logon interception ConfigurationThen we can use it. I have changed the project structure and established an ibll interface layer. The existing BLL layer class implements the interface in the ibll layer, in addition, to implement AOP in the Policy injection module, the specific class must inherit from alalbyrefobject or implement an interface (if not clear, you can view Part1 ), therefore, an ibll layer is created to decouple various modules of the project and facilitate policy injection to pave the way for the creation of specific classes and the introduction of unity in the future. (For details, refer to the project code)

Because the ibll layer is created, the code of the presentation layer needs to be changed. All BLL layer creation needs to be created through the yyinjection. Create method. The specific code is as follows:

 
Istudentmanage studentbll = policyinjection. Create <studentmanage, istudentmanage> ();

In this way, after running the code, you can view the operation log in the database.

The above describes how to use configuration to record operation logs. If we want to use attribute to record log messages, we need to perform operations at the specific BLL layer. The Code is as follows:

 
[Userlogcallhandler ("Updating student information", "student")] public bool Update (Student) {return studentservice. Update (student );}

Note: here you need to reference Microsoft for the project. practices. unity. interception, because the attribute of the call handler is inherited from the handlerattribute, which is stored in Microsoft. practices. unity. interception. Otherwise, the custom call handler attribute cannot be displayed.

In this way, after updating the student information, we can see the specific operation log, see:

 

The above is all the content in this article. It mainly introduces how to use custom call handler to implement user operation logging. If there is anything wrong, please point out, thank you :)

Now, the introduction to the policy injection module is complete. Next we will introduce the most widely used IOC container-unity in the Enterprise Library, so stay tuned!

 

Microsoft enterprise database 5.0 learning path SeriesArticleIndex:

Step 1: getting started

Step 2: Use the vs2010 + data access module to create a multi-database project

Step 3: Add exception handling to the project (record to the database using custom extension)

Step 4: Use the cache to improve the website's performance (entlib caching)

Step 5: Introduce the entlib. validation module information, the implementation level of the validators, and the use of various built-in validators-Part 1

Step 5: Introduce the entlib. validation module information, the implementation level of the validators, and the use of various built-in validators-Part 1

Step 5: Introduce the entlib. validation module information, the implementation level of the validators, and the use of various built-in validators-Part 2

Step 6: Use the validation module for server-side data verification

Step 7: Simple Analysis of the cryptographer encryption module, custom encryption interfaces, and usage-Part 1

Step 7: Simple Analysis of the cryptographer encryption module, custom encryption interfaces, and usage-Part 2

Step 8. Use the configuration setting module and other methods to classify and manage enterprise database configuration information

Step 9: Use the policyinjection module for AOP-PART1-basic usage

Step 9: Use the policyinjection module for AOP-PART2-custom matching rule

Step 9: Use the policyinjection module for AOP-PART3 -- Introduction to built-in call Handler

Step 9: Use the policyinjection module for AOP-PART4 -- create a custom call handler to achieve user operation Logging

Step 10: Use unity to decouple your system-Part1-Why use unity?

Step 10: Use unity to decouple your system-Part2-learn how to use Unity (1)

Step 10. Use unity to decouple your system-Part2-learn how to use Unity (2)

Step 10: Use unity to decouple your system-Part2-learn how to use Unity (3)

Step 10: Use unity to decouple your system-Part3-dependency Injection

Step 10: Use unity to decouple your system-part4 -- unity & piab

Extended learning:

Extended learning and dependency injection in libraries (rebuilding Microsoft Enterprise Library) [go]

 

Source codeDownload: Click here to download

 

Note:

1. The MSSQL database is in the database directory (you need to attach the database yourself), and The SQLite database is in the app_data directory of the web directory. Because of the project size, the bin directory of each project has been deleted, if a project cannot be generated, add the DLL of the relevant enterprise library.

2. As Microsoft enterprise database 5.0 is a learning path, this series is intended to introduce the modules of the enterprise database in the form of a small project, so the source code will be updated according to the updates in the series of articles, therefore, the source code cannot be the same as the Code posted in the article.

3. The project development environment is vs2010 + sql2005.

4. Administrator Account: Admin

Password: Admin

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.