Pipelines of Nancy (Before After OnError), pipelinesonerror

Source: Internet
Author: User

Pipelines of Nancy (Before After OnError), pipelinesonerror
1. Simple Description

Before: If null is returned, the interceptor transfers the initiative to the route. If Response object is returned, the route does not work.

After: no return value. You can modify or replace the current Response here.

OnError: the return value is similar to that of Before. The control code for triggering errors or exceptions can be written here.

The general role of these three brothers can also be simply understood as follows:

Before: process the previous tasks. (Return null, continue processing; return the Response object, no longer do the thing to do, but do what the Response object will do)

After: what to do After processing.

OnError: handle the error.

The definitions of these three siblings in NancyModule are as follows:

1 public AfterPipeline After { get; set; } 2 public BeforePipeline Before { get; set; }3 public ErrorPipeline OnError { get; set; }

These three pipelines inherit

AsyncNamedPipelineBase <TAsyncDelegate, TSyncDelegate> and NamedPipelineBase <TDelegate>

So they are mainly involved in five classes! Let's take a look at it at the end!

 

Ii. Simple usage

In the Module, we can directly use the Before/After/OnError three

You can also rewrite RequestStartup or ApplicationStartup in Bootstrapper.

Of course, you can also customize it. You only need to implement the IRequestStartup or IApplicationStartup interface to complete the corresponding work.

 

Next, let's explain it separately.

Usage 1: Use it directly in the Module

Define a BaseModule as follows:

1 public class BaseModule: NancyModule 2 {3 public BaseModule () 4 {5 // write a 6 Before + = ctx => {7 System. diagnostics. debug. writeLine ("BaseModule --- Before"); 8 return null; 9}; 10 After + = ctx => {11 System. diagnostics. debug. writeLine ("BaseModule --- After"); 12}; 13 OnError + = (ctx, ex) =>{ 14 System. diagnostics. debug. writeLine ("BaseModule --- OnError"); 15 System. diagnostics. debug. writeLine (ex. toString (); 16 return null; 17}; 18 // write method 2 19 // Before + = MyBefore; 20 // After + = MyAfter; 21 // OnError + = MyOnError; 22} 23 private Response MyBefore (NancyContext ctx) 24 {25 System. diagnostics. debug. writeLine ("BaseModule --- Before ---- method 2"); 26 return null; 27} 28 private void MyAfter (NancyContext ctx) 29 {30 System. diagnostics. debug. writeLine ("BaseModule --- After ---- method 2"); 31} 32 private Response MyOnError (NancyContext ctx, Exception ex) 33 {34 System. diagnostics. debug. writeLine ("BaseModule --- OnError ---- method 2"); 35 System. diagnostics. debug. writeLine (ex. toString (); 36 return null; 37} 38}

 

In BaseModule, two different forms are used to process Before, After, and OnError,

Only some simple information is printed. Reading the output information can help you understand the internal execution order!

We can see that Before and OnError are of the Response type, and After is of the void type.

In the specific handling of these three brothers, we need to decide based on the actual situation (of course, it is okay to print out some things if you want to, after all, we can still write these things into the diary )!

A HomeModule is defined as follows:

1     public class HomeModule : BaseModule2     {3         public HomeModule()4         {5             Get["/"] = _ => "Catcher Wong";6             Get["/err"] = _ => { throw new Exception("there're some errors"); };7         }8     }  

When we access http: // localhost: port, our text is displayed. When we access http: // localhost: port/err, an exception is thrown!

Run it and check out our Output window.

This is the case when accessing http: // localhost: port

 

Access http: // localhost: port/err

Failed to execute After !! The OnError execution is complete.

 

Similarly, this is also true in writing 2!

Basically consistent results.

Usage 2: rewrite RequestStartup or ApplicationStartup in bootstrapper

 

Let's take a look at rewriting RequestStartup.

 1     public class Bootstrapper : DefaultNancyBootstrapper 2     { 3         protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context) 4         { 5             base.RequestStartup(container, pipelines, context); 6             pipelines.BeforeRequest += ctx => { 7                 System.Diagnostics.Debug.WriteLine("Boorstrapper---RequestStartup---Before"); 8                 return null; 9             };10             pipelines.AfterRequest += ctx => {11                 System.Diagnostics.Debug.WriteLine("Boorstrapper---RequestStartup---After");12             };13             pipelines.OnError += (ctx,ex) => {14                 System.Diagnostics.Debug.WriteLine("Boorstrapper---RequestStartup---OnError");15                 System.Diagnostics.Debug.WriteLine(ex.ToString());16                 return null;17             };18         }       19     }  

 

We also output the corresponding information. comment out the "Three Brothers" in our BaseModule before running.

Let's take a look at overwriting ApplicationStartup.

 1      public class Bootstrapper : DefaultNancyBootstrapper 2     { 3         protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) 4         { 5             base.ApplicationStartup(container, pipelines); 6             pipelines.BeforeRequest += MyBeforeRequest; 7             pipelines.AfterRequest += MyAfterRequest; 8             pipelines.OnError += MyOnErroe; 9         }10         private Response MyBeforeRequest(NancyContext ctx)11         {12             System.Diagnostics.Debug.WriteLine("Boorstrapper---ApplicationStartup---Before");13             return null;14         }15         private void MyAfterRequest(NancyContext ctx)16         {17             System.Diagnostics.Debug.WriteLine("Boorstrapper---ApplicationStartup---After");18         }19         private Response MyOnErroe(NancyContext ctx, Exception ex)20         {21             System.Diagnostics.Debug.WriteLine("Boorstrapper---ApplicationStartup---OnError");22             System.Diagnostics.Debug.WriteLine(ex.ToString());23             return null;24         }25     }  

 

We also output the corresponding information. comment out the "Three Brothers" in our BaseModule and RequestStartup before running.

 

Usage 3: Custom usage (there are many things in Nancy that can be customized. This is flexible and nice !)

Next, let's see how to use custom settings!

 1     public class CustomRequest : IApplicationStartup 2     {        3         public void Initialize(IPipelines pipelines) 4         { 5             pipelines.BeforeRequest.AddItemToEndOfPipeline(ctx => 6             { 7                 System.Diagnostics.Debug.WriteLine("CustomRequest---IApplicationStartup---Before");                 8                 return null; 9             });10             pipelines.AfterRequest.AddItemToEndOfPipeline(ctx =>11             {12                 System.Diagnostics.Debug.WriteLine("CustomRequest---IApplicationStartup---After");13             });14             pipelines.OnError.AddItemToEndOfPipeline((ctx, ex) =>15             {16                 System.Diagnostics.Debug.WriteLine("CustomRequest---IApplicationStartup---OnError");17                 System.Diagnostics.Debug.WriteLine(ex.ToString());18                 return null;19             });20         }21     }  

We can customize a CustomRequest to implement the IApplicationStartup interface!

The rest is the processing of Before, After, and OnError !!

Comment out and run the previous processing.

The effect is as follows:

As mentioned above, the execution results are executed separately in each usage. What is the execution sequence of each usage? Next let's take a look and remove all comments and run them.

Is it clear now?

Before execution sequence: IApplicationStartup> ApplicationStartup> RequestStartup> BaseModule

OnError execution sequence BaseModule> IApplicationStartup> ApplicationStartup> RequestStartup to check the execution sequence of After.

The processing sequence is the same as that of OnError !!

Iii. Simple internal implementation analysis

As mentioned above, the implementation of these three brothers mainly includes these classes.

BeforePipeline, AfterPipeline, ErrorPipeline, and abstract classes NamedPipelineBase, AsyncNamedPipelineBase

The corresponding Before, After, and OnError definitions are also available in the NancyModule!

Let's take a look at BeforePipeline.

BeforePipeline is an abstract class that implements AsyncNamedPipelineBase.

Implicit operator. For details, refer

Implicit (C # Reference)

There is an override of the Wrap method, which is used to package synchronization into an asynchronous form.

 1         protected override PipelineItem<Func<NancyContext, CancellationToken, Task<Response>>> Wrap(PipelineItem<Func<NancyContext, Response>> pipelineItem) 2         { 3             var syncDelegate = pipelineItem.Delegate; 4             Func<NancyContext, CancellationToken, Task<Response>> asyncDelegate = (ctx, ct) => 5             { 6                 var tcs = new TaskCompletionSource<Response>(); 7                 try 8                 { 9                     var result = syncDelegate.Invoke(ctx);10                     tcs.SetResult(result);11                 }12                 catch (Exception e)13                 {14                     tcs.SetException(e);15                 }16                 return tcs.Task;17             };18             return new PipelineItem<Func<NancyContext, CancellationToken, Task<Response>>>(pipelineItem.Name, asyncDelegate);19         }

The other code can be summarized as follows:

Pipeline. AddItemToEndOfPipeline (xxxx );

Add xxxx to the end of the MPs queue.

Similarly, AfterPipeline and ErrorPipeline are similar,

The difference is that ErrorPipeline implements the abstract class NamedPipelineBase,

There is no such Wrap method, and there is an additional dynamic Invoke method.

 1         public dynamic Invoke(NancyContext context, Exception ex) 2         { 3             dynamic returnValue = null; 4             using (var enumerator = this.PipelineDelegates.GetEnumerator()) 5             { 6                 while (returnValue == null && enumerator.MoveNext()) 7                 { 8                     returnValue = enumerator.Current.Invoke(context, ex); 9                 }10             }11             return returnValue;12         }  

 

 

The Invoke method is used to call each MPs queue project until an MPS queue project is returned or all MPs queue projects have been called!

Both NamePipelineBase (synchronous and asynchronous) define a pipelineItems (pipeline project set to be executed)

There are many other virtual methods !! Most of them are inserted and one is deleted.

Insert can be divided into the beginning and end of the Pipeline, and whether to replace the existing Pipeline with the same name

The following is an important method: InsertItemAtPipelineIndex

Synchronized

1          public virtual void InsertItemAtPipelineIndex(int index, PipelineItem<TDelegate> item, bool replaceInPlace = false)2         {3             var existingIndex = this.RemoveByName(item.Name);4             var newIndex = (replaceInPlace && existingIndex != -1) ? existingIndex : index;5             this.pipelineItems.Insert(newIndex, item);6         }  

Asynchronous

1         public virtual void InsertItemAtPipelineIndex(int index, PipelineItem<TAsyncDelegate> item, bool replaceInPlace = false)2         { 3             var existingIndex = this.RemoveByName(item.Name);4             var newIndex = (replaceInPlace && existingIndex != -1) ? existingIndex : index;5             this.pipelineItems.Insert(newIndex, item);6         }  

 

The main function of this method is to insert the item to the specified position of the Pipeline! (Both synchronous and asynchronous operations are implemented accordingly !! The difference is the item type !) For internal implementation, the simple saying is: add what we write to Pipline for processing.

Finally, let's take a look at the IPipelines we use in Bootstrapper and custom.

1     public interface IPipelines2     {   3         BeforePipeline BeforeRequest { get; set; }     4         AfterPipeline AfterRequest { get; set; }5         ErrorPipeline OnError { get; set; }6     }  

Very simple definition!

 

Related Article

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.