Runtime

From Bistro
Jump to: navigation, search

This page serves as an overview of the Bistro runtime, its lifecyles and components

Contents

Main Components

The Bistro runtime operates using 3 main components

  • The Controller Dispatcher (IControllerDispatcher) for computing execution chains
  • The Controller Manager (IControllerManager) for maintaining the full set of available controllers
  • Controller Handlers (IControllerHandler) for marshalling Controller instances

Each of these components can be substituted out via the configuration options available for the bistro runtime.

The rest of this article will focus on the various flows within the bistro runtime, and how they consume the components outlined above. For documentation on customizing the individual components, or their default implementations, please consult the Bistro Class Library


Bistro Application Lifecycle

The Bistro runtime is represented at the top level via the Application Class. This class is responsible for bootstrapping the Bistro runtime, and is in turn initialized through the Bistro Module as pictured.

Each step is driven through the default-first configuration setting. The application class and factories can be overriden. Typically, only the definition of an additional component, one not already covered by one of the factories present, would require the extension or re-definition of the application class.

Error creating thumbnail: convert.exe: unable to open image `C:\inetpub\wwwroot\bistro/images/1/15/B_app_lc.png': No such file or directory @ error/blob.c/OpenBlob/2642.
convert.exe: unable to open file `C:\inetpub\wwwroot\bistro/images/1/15/B_app_lc.png' @ error/png.c/ReadPNGImage/3733.
convert.exe: no images defined `C:\Windows\TEMP/transform_6431abbb5cd3-1.png' @ error/convert.c/ConvertImageCommand/3044.

Bistro Request Lifecycle

The bistro runtime integrates with the ASP.NET pipeline to implement it's functionality. Once invoked, the runtime goes through the following steps:
  1. Determine if the request is a bistro request.
    1. If a bistro request, place the bistro handler in the pipeline
  2. Compute the controller chain
  3. Validate security
  4. Execute controllers
  5. Recursively process transfers
Error creating thumbnail: convert.exe: unable to open image `C:\inetpub\wwwroot\bistro/images/b/b0/B_rqst.png': No such file or directory @ error/blob.c/OpenBlob/2642.
convert.exe: unable to open file `C:\inetpub\wwwroot\bistro/images/b/b0/B_rqst.png' @ error/png.c/ReadPNGImage/3733.
convert.exe: no images defined `C:\Windows\TEMP/transform_1b7a790b7c56-1.png' @ error/convert.c/ConvertImageCommand/3044.

ASP.NET Interception

The bistro runtime intergrates with asp.net via a module and a handler. The module, executing for all requests, determines if the inbound request is a bistro method invocation (as determined by url recognition rules). Each module Init() invocation determines whether the bistro application class has been instantiated, and does so if it has not. From that point forward, each module will reference the same instance of the application class. Do note that the invocation of the bistro handler is done through the HttpContext.RemapHandler() method, which requires .NET 3.5 SP1+ or 2.0 SP2+.

Once the handler has been invoked, the bistro pipeline begins as depicted above.

Error creating thumbnail: convert.exe: unable to open image `C:\inetpub\wwwroot\bistro/images/3/3d/B_asp_lce.png': No such file or directory @ error/blob.c/OpenBlob/2642.
convert.exe: unable to open file `C:\inetpub\wwwroot\bistro/images/3/3d/B_asp_lce.png' @ error/png.c/ReadPNGImage/3733.
convert.exe: no images defined `C:\Windows\TEMP/transform_1de67f3e70aa-1.png' @ error/convert.c/ConvertImageCommand/3044.

Controller Chain Computation

Controller chain computation is delegated to the current active implementation of IControllerDispatcher. The default implementation works as follows:

  1. For each bind point in the full list, a determination is made whether the bind point applies to this request
  2. The set of matched bind points is then sorted, according to the BindType specified (currently Before, Payload and After
  3. A secondary sort is then applied, enforcing dependencies
    1. If a cyclical dependency is identified, a runtime exception is generated
    2. If a hard requirement is not met (a controller in the execution chain with a Requires that has no corresponding Provides resource), a runtime exception is generated
  4. Finally, all controllers identified as security controllers, are moved to the top of the execution chain, regardless of BindType or resource rules. If a security controller has a dependency on a standard controller, a runtime exception is generated.

Once computed, the list is returned to the caller, as an ordered list of controller invocation infos. This structure encodes which specific bind point on the controller class matched the inbound request, and the parameter values that were supplied to it.

Something to remember
The controller dispatcher is expected to be a thread-safe singleton implementation. It is used during bootstrapping to register the full list of controllers, and is expected to retain this information.

Security

The runtime expects the controller chain returned to have all security controllers, if any, at the top. When processing the execution chain, the request is not considered authorized until all security controllers are processed.

  • For all security controllers, the ProcessRequest method is invoked first, followed by the HasAccess method.
  • Security controllers are allowed to have dependencies amongst themselves
    • They are also allowed to provide data to non-security controllers.

As security policy is being applied, the full set of security controllers will be processed prior to a determination being made, as a subsequent controller can override a failure of a previous one. Each controller is provided with a list of security demands that have currently failed, and security controllers are allowed to remove elements from this list. Specifically, if a standard SecurityController marked with Deny("admin") fails, a subsequent Allow("admin") will need to override this determination, and will do so by removing the failure from the list. Once the full list of security controllers has been processed, the list of failures will be examined. If there is at least one element, the request is considered unauthorized, and the FailAction is taken

  • If the FailAction is Redirect, an immediate Transfer is requested to the redirect destination
  • If the FailAction is Fail, a HTTP:403 is returned to the browser.

If there are no failures, the rest of the controller chain is processed.

Controller Execution

Controller execution consists of the following steps

  1. An instance of the controller is obtained.
    1. This instance is retrieved through the ControllerManager, which in turn uses a ControllerHandler to both retrieve, and populate an instance of the requested controller.
    2. The controller is returned with all of it's resource and parameter fields/properties populated with data from the context and session
  2. The ProcessRequest method is invoked
  3. The controller is then returned to the ControllerManager, which in turn uses the ControllerHandler to read the data from the controller and back onto the respective targets (session, request, etc.). The handler will then invoke the Recycle method for controllers that have been marked as Reusable

During execution, controllers may use the IExecutionContext.Transfer method to request the execution of another bistro method. This will be done after all controllers in the current execution chain have been processed. The transfer requests will not be queued, and the last transfer request made will be the one to be executed. If a transfer request is made, the bistro handler will re-start the pipeline from the beginning, recomputing the execution chain, and re-validating security policy, as a different policy may apply to the new request. If a controller needs to stop execution, a WebException can be thrown. This will stop the execution of the controller chain, and return the http status code and message to the browser.

Output

Output in bistro is handled via controllers provided by the system. Currently there are two controllers for this

  • The RenderingController provides integration with various templating engines, and typically provides HTML output. It reads the RenderTarget field on the context, and uses that as the name of the template to invoke.
    • This controller will not execute if a transfer request is pending
    • This controller will not execute if the current ReturnType is not ReturnType.Template
  • The ReturnTypesController provides structured data output, such as XML and JSON. This controller will read the various fields set by the IResponse.ReturnXXX methods.
    • This controller will not execute if a transfer request is pending
    • This controller will not execute if the current ReturnType is ReturnType.Template

Exceptions

With the exception of the WebException, exceptions raised during request processing are allowed to bubble up

Future direction
Runtime support for centralized exception handling will be provided in an upcoming release
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox