Extension: .netstandard - quandis/qbo3-Documentation GitHub Wiki
Components designed to work with .netstandard
, including use of IConfiguration
, IServiceProvider
and ILogger
can be incorporated into qbo3.
While developers may not modify a Startup.cs
class as they would in a traditional .netcore
application, qbo exposes an ApplicationStartup
class that exposes IConfiguration
, IServiceProvider
to calling code.
To inject configuration data and services into ApplicationStartup:
- include the
qbo4.Configuration.HttpApplication
Nuget package in your project - add configuration by creating an extension method tagged with a
ConfigurationMethod
attribute:
[ConfigurationMethod]
public static IConfigurationBuilder AddMyServices(this IConfigurationBuilder builder)
{
builder.AddJsonObject(new { Foo = "Bar" });
return builder;
}
- add services by creating an extension method tagged with a
ServiceCollectionMethod
attribute:
[ServiceCollectionMethod]
public static IServiceCollection AddMyServices(this IServiceCollection services, IConfiguration configuration)
{
var providers = new List<string>();
configuration.GetSection("MyServices").Bind(providers);
foreach (var name in providers)
{
services.AddSingleton<MyService>(sp => { return new MyService(name); });
}
return services;
}
While the qbo3 stack is still running on traditional ASP.NET
, it's straight forward to port Middleware to a qbo3 BaseHandler
. For example, the qbo4.Document module includes a ConvertMiddleware
to handle document conversion:
public async Task Invoke(HttpContext context, Transformers transformers)
{
_transformers = transformers;
var toMimeType = (context.Request.Headers.ContainsKey("Accept")) ? context.Request.Headers["Accept"].ToString() : throw new ArgumentNullException("Accept", "You must specify an Accept header with the mime type you wish to convert to.");
using (var cache = new CacheStream())
{
// ... omitted for brevity...
}
}
To port this to a BaseHandler
:
public override async Task ProcessRequestAsync(HttpContext context)
{
// Dependency injection via ApplicationStartup
var _transformers = ApplicationStartup.Instance.Services.GetRequiredService<Transformers>();
var toMimeType = (context.Request.Headers.ContainsKey("Accept")) ? context.Request.Headers["Accept"].ToString() : throw new ArgumentNullException("Accept", "You must specify an Accept header with the mime type you wish to convert to.");
var fromMimeType = context.Request.ContentType;
using (var cache = new CacheStream())
{
// ... omitted for brevity...
}
}
One your custom handler is deployed, create a custom route to tell qbo3 to route requests to it:
<ConfigurationEntryCollection>
<ConfigurationEntryItem>
<ConfigurationEntry>CustomRoutes/qbo4_document_convert</ConfigurationEntry>
<Source>CustomRoutes.config</Source>
<ConfigurationType>qbo.Application.Configuration.CustomRouteCollection</ConfigurationType>
<ConfigurationKey>qbo4_document_convert</ConfigurationKey>
<ConfigurationXml>
<CustomRoute Name="qbo4_document_convert" Url="api/qbo4/document/convert" Version="1" Handler="qbo4.Document.Bridge.ConvertHandler, qbo4.Document.Bridge" />
</ConfigurationXml>
</ConfigurationEntryItem>
</ConfigurationEntryCollection>
If you wish to extend existing qbo3 classes, simply write an extension method for them:
[DbVoidMethod(RequireStream = true)]
public static async Task ConvertAsync(this AttachmentObject attachment, IDictionary<string, object> parameters)
{
var transformers = ApplicationStartup.Instance.Services.GetRequiredService<Transformers>();
await attachment.SelectAsync(parameters);
var toMimeType = (parameters.ContainsKey("Accept")) ? parameters["Accept"].ToString()
: throw new ArgumentNullException("Accept", "You must specify an Accept parameter with the mime type you wish to convert to.");
var responseStream = (parameters.ContainsKey("ResponseStream")) ? parameters["ResponseStream"] as Stream
: throw new ArgumentNullException("ResponseStream", "No response stream is available in the parameters.");
using (var cache = await attachment.CacheStreamAsync())
{
// ... omitted for brevity ...
}
}
There is a large overlap in the use cases around which one might choose to create an IService vs an extension method vs a custom route. Consider:
Technique | Guidance |
---|---|
Extension Methods | Create extension methods when the functionality is specific to a QBO module. Attachment.ViewHtmlAsync that converts a document to an HTML viewer requires a document. |
Custom Routes | Create custom routes when the functionality crosses multiple QBO models (or none). Single page applications are an excellent example of this. |
IServices | Create an IService when you need QBO to transform data into a request payload, or transform the response payload. IService has hooks for this which would be cumbersome to re-implement in code. |
- If the person develping