Skip to content

Commit

Permalink
v1 to v2 upgrade guide (#441)
Browse files Browse the repository at this point in the history
* Skeleton

* MarkdownSnippets documentation changes

* Create README.source.md

* MarkdownSnippets documentation changes

* MarkdownSnippets documentation changes

* Update 1.x.x-2.0.0.source.md

* MarkdownSnippets documentation changes

* typo

* MarkdownSnippets documentation changes

* MarkdownSnippets documentation changes

* Delete 1.x.x-2.0.0.source.md

* Delete README.source.md

* Remove comment header

* Remove comment header

* Supported target frameworks

* Composition over controllers route matching

* MarkdownSnippets documentation changes

* typo

* Update 1.x.x-2.0.0.md

* run-composition-gateway-deprecation snippet

* RunCompositionGateway is deprecated

* MarkdownSnippets documentation changes

* Update 1.x.x-2.0.0.md

* MarkdownSnippets documentation changes

* Update 1.x.x-2.0.0.md

* Add composition-over-controllers-case-sensitive snippet

* snippet: composition-over-controllers-case-sensitive

* MarkdownSnippets documentation changes

* MapCompositionHandlers write support

* Update 1.x.x-2.0.0.md

* MarkdownSnippets documentation changes

* ICompositionRequestsHandler API changes

* MarkdownSnippets documentation changes

* Update README.md

* typo

* composition-context-api

* ICompositionContext upgrade guide

* MarkdownSnippets documentation changes

* Update 1.x.x-2.0.0.md

* MarkdownSnippets documentation changes

* snippet: composition-event-publisher-api

* MarkdownSnippets documentation changes

* ICompositionEventsPublisher and snippet

* MarkdownSnippets documentation changes

* snippet: composition-errors-handler-api

* MarkdownSnippets documentation changes

* ICompositionErrorsHandler and snippet

* MarkdownSnippets documentation changes

* ICompositionEventsSubscriber and snippet

* snippet: composition-event-subscriber-api

* MarkdownSnippets documentation changes

* snippet: viewmodel-preview-handler-api

* MarkdownSnippets documentation changes

Co-authored-by: GitHub Action <[email protected]>
  • Loading branch information
mauroservienti and actions-user authored Jan 2, 2023
1 parent 4854ca4 commit 3efe8d6
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 1 deletion.
10 changes: 9 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# ASP.NET Core on .NET 6
# ASP.NET Core on .NET

ServiceComposer leverages the Endpoints support to plugin into the request handling pipeline.
ServiceComposer can be added to existing or new ASP.NET Core projects, or it can be hosted in .NET console applications.

## Supported .NET versions

ServiceComposer targets .NET 6 and .NET 7.

## Note about thread safety

If resources are shared across more than one handler they must be [thread-safe](thread-safety.md).

## Upgrade guides

[Upgrade guides](upgrade-guides) are available to easy the migration from one version to another when needed.

## ASP.Net Model Binding

When handling composition requests it possible to leverage the power of ASP.Net Model Binding to bind incoming forms, bodies, query string parameters, or route data to strongly typed C# models. For more information on model binding refer to the [Model Binding](model-binding.md) section.
Expand Down
176 changes: 176 additions & 0 deletions docs/upgrade-guides/1.x.x-2.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Upgrade guide from v1.x to v2.0.0

<!-- toc -->
## Contents

* [Target frameworks](#target-frameworks)
* [ASP.Net Core endopints integration](#aspnet-core-endopints-integration)
* [Composition handlers API changes](#composition-handlers-api-changes)
* [IHandleRequests -> ICompositionRequestsHandler](#ihandlerequests---icompositionrequestshandler)
* [ISubscribeToCompositionEvents -> ICompositionEventsSubscriber](#isubscribetocompositionevents---icompositioneventssubscriber)
* [IHandleRequestsErrors -> ICompositionErrorsHandler](#ihandlerequestserrors---icompositionerrorshandler)
* [ICompositionContext](#icompositioncontext)
* [MapCompositionHandlers write support](#mapcompositionhandlers-write-support)
* [IViewModelPreviewHandler Preview](#iviewmodelpreviewhandler-preview)
* [Route matching](#route-matching)<!-- endToc -->

## Target frameworks

Starting with version 2.0.0 the `ServiceComposer.AspNetCore` package targets only the following frameworks

- net6.0
- net7.0

## ASP.Net Core endopints integration

ServiceComposer uses ASP.Net endpoints. The `RunCompositionGateway` API is deprecated in favor of explict ASP.Net endpoint configuration; Use the new endpoints mapping API:

<!-- snippet: run-composition-gateway-deprecation -->
<a id='snippet-run-composition-gateway-deprecation'></a>
```cs
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseRouting();
app.UseEndpoints(builder => builder.MapCompositionHandlers());
}
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L16-L22' title='Snippet source file'>snippet source</a> | <a href='#snippet-run-composition-gateway-deprecation' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Extending the `IRouteBuilder` intrerface to map custom route is not anymore supported. Instead, use mapping attributes on composition handlers. See below for details about the composition handlers API.

## Composition handlers API changes

Version `2.0.0` introduces a new composition API. `IHandleRequests`, `IPublishCompositionEvents`, and `IHandleRequestsErrors` are not supported anymore.

### IHandleRequests -> ICompositionRequestsHandler

The `IHandleRequests` has been replaced by `ICompositionRequestsHandler`:

<!-- snippet: composition-handler-api -->
<a id='snippet-composition-handler-api'></a>
```cs
public class SampleHandler : ICompositionRequestsHandler
{
[HttpGet("/sample/{id}")]
public Task Handle(HttpRequest request)
{
return Task.CompletedTask;
}
}
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L38-L47' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-handler-api' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

NOTE: The `IInterceptRoutes.Matches` method has been replaced by routing attributes, `HttpGet`, `HttpPost`, etc.

### ISubscribeToCompositionEvents -> ICompositionEventsSubscriber

The `ISubscribeToCompositionEvents` has been replaced by the new `ICompositionEventsSubscriber`:

<!-- snippet: composition-event-subscriber-api -->
<a id='snippet-composition-event-subscriber-api'></a>
```cs
public class SamplePublisher : ICompositionEventsSubscriber
{
[HttpGet("/sample/{id}")]
public void Subscribe(ICompositionEventsPublisher publisher)
{
// Use the publisher to subscriber to published events
publisher.Subscribe<SampleEvent>((evt, httpRequest)=>
{
// Handle the event
return Task.CompletedTask;
});
}
}
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L51-L65' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-event-subscriber-api' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

NOTE: The `IInterceptRoutes.Matches` method has been replaced by routing attributes, `HttpGet`, `HttpPost`, etc.

### IHandleRequestsErrors -> ICompositionErrorsHandler

The `IHandleRequestsErrors` has been replaced by `ICompositionErrorsHandler`:

<!-- snippet: composition-errors-handler-api -->
<a id='snippet-composition-errors-handler-api'></a>
```cs
public class SampleErrorHandler : ICompositionErrorsHandler
{
public Task OnRequestError(HttpRequest request, Exception ex)
{
return Task.CompletedTask;
}
}
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L67-L75' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-errors-handler-api' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

### ICompositionContext

`DynamicViewModel` doesn't implement `ICompositionContext` anymore. The composition context can be retrived from the current `HttpRequest`:

<!-- snippet: composition-context-api-get-context -->
<a id='snippet-composition-context-api-get-context'></a>
```cs
var context = request.GetCompositionContext();
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L94-L96' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-context-api-get-context' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

To raise an event use the composition context API:

<!-- snippet: composition-context-api-raise-event -->
<a id='snippet-composition-context-api-raise-event'></a>
```cs
await context.RaiseEvent(new AnEvent());
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L98-L100' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-context-api-raise-event' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The composition context also exposes the current request identifier:

<!-- snippet: composition-context-api-get-request-id -->
<a id='snippet-composition-context-api-get-request-id'></a>
```cs
var requestId = context.RequestId;
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L102-L104' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-context-api-get-request-id' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## MapCompositionHandlers write support

By default ServiceComposer responds only to HTTP `GET` requests, to enable write support, for example to handle `POST` requests, the following configuration can be used when adding ServiceComposer to the application:

<!-- snippet: enable-write-support -->
<a id='snippet-enable-write-support'></a>
```cs
public void ConfigureServices(IServiceCollection services)
{
services.AddViewModelComposition(options => options.EnableWriteSupport());
}
```
<sup><a href='/src/Snippets/WriteSupport/EnableWriteSupport.cs#L8-L13' title='Snippet source file'>snippet source</a> | <a href='#snippet-enable-write-support' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## IViewModelPreviewHandler Preview

## Route matching

When using composition over controllers route matching is now case insensitive by default. The previous behavior can be configured via the composition over controllers options:

<!-- snippet: composition-over-controllers-case-sensitive -->
<a id='snippet-composition-over-controllers-case-sensitive'></a>
```cs
public void ConfigureServices(IServiceCollection services)
{
services.AddViewModelComposition(config =>
{
config.EnableCompositionOverControllers(useCaseInsensitiveRouteMatching: false);
});
}
```
<sup><a href='/src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs#L27-L35' title='Snippet source file'>snippet source</a> | <a href='#snippet-composition-over-controllers-case-sensitive' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
3 changes: 3 additions & 0 deletions docs/upgrade-guides/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Upgrade guides

- [v1.x to v2.0.0](1.x.x-2.0.0.md)
107 changes: 107 additions & 0 deletions src/Snippets/UpgradeGuides/1.x-to-2.0/UpgradeGuide.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ServiceComposer.AspNetCore;

namespace Snippets.NetCore3x.UpgradeGuides._1.x_to_2._0;

public class UpgradeGuide
{
public class RunCompositionGatewayDeprecation
{
// begin-snippet: run-composition-gateway-deprecation
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseRouting();
app.UseEndpoints(builder => builder.MapCompositionHandlers());
}
// end-snippet
}

public class CompositionOverControllers
{
// begin-snippet: composition-over-controllers-case-sensitive
public void ConfigureServices(IServiceCollection services)
{
services.AddViewModelComposition(config =>
{
config.EnableCompositionOverControllers(useCaseInsensitiveRouteMatching: false);
});
}
// end-snippet
}

// begin-snippet: composition-handler-api
public class SampleHandler : ICompositionRequestsHandler
{
[HttpGet("/sample/{id}")]
public Task Handle(HttpRequest request)
{
return Task.CompletedTask;
}
}
// end-snippet

class SampleEvent{}

// begin-snippet: composition-event-subscriber-api
public class SamplePublisher : ICompositionEventsSubscriber
{
[HttpGet("/sample/{id}")]
public void Subscribe(ICompositionEventsPublisher publisher)
{
// Use the publisher to subscriber to published events
publisher.Subscribe<SampleEvent>((evt, httpRequest)=>
{
// Handle the event
return Task.CompletedTask;
});
}
}
// end-snippet

// begin-snippet: composition-errors-handler-api
public class SampleErrorHandler : ICompositionErrorsHandler
{
public Task OnRequestError(HttpRequest request, Exception ex)
{
return Task.CompletedTask;
}
}
// end-snippet

// begin-snippet: viewmodel-preview-handler-api
public class ViewModelPreviewHandler: IViewModelPreviewHandler
{
public Task Preview(HttpRequest httpRequest)
{
return Task.CompletedTask;
}
}
// end-snippet

public class CompositionContextApi : ICompositionRequestsHandler
{
class AnEvent{}

[HttpGet("/sample/{id}")]
public async Task Handle(HttpRequest request)
{
// begin-snippet: composition-context-api-get-context
var context = request.GetCompositionContext();
// end-snippet

// begin-snippet: composition-context-api-raise-event
await context.RaiseEvent(new AnEvent());
// end-snippet

// begin-snippet: composition-context-api-get-request-id
var requestId = context.RequestId;
// end-snippet
}
}
}
14 changes: 14 additions & 0 deletions src/Snippets/WriteSupport/EnableWriteSupport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using ServiceComposer.AspNetCore;

namespace Snippets.NetCore3x.WriteSupport;

public class EnableWriteSupport
{
// begin-snippet: enable-write-support
public void ConfigureServices(IServiceCollection services)
{
services.AddViewModelComposition(options => options.EnableWriteSupport());
}
// end-snippet
}

0 comments on commit 3efe8d6

Please sign in to comment.