static void Main() { Func <IFoo> getFoo = () => new DummyFoo(); var module = new CommandModule(getFoo); var resolver = new CommandHandlerResolver(module); var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { // Use a string to decouple command name from the command clr type. This will ensure // refactoring, i.e. moving CommandThatHasASyncHandler or renaming it, won't change your http API. { "CommandThatHasASyncHandler", typeof(CommandThatHasASyncHandler) }, // Can use typeof().Name if you are not concerned with backwards compat or versioning. { typeof(CommandThatHasAnAsyncHandler).Name, typeof(CommandThatHasAnAsyncHandler) }, }; var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap); var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings); // 5. Add the middleware to your owin pipeline using (WebApp.Start("http://localhost:8080", app => { app.Use(commandHandlingMiddleware); })) { Console.WriteLine("Press any key"); } }
private static void Main() { var resolver = new CommandHandlerResolver(new CommandModule()); var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { { typeof(CommandThatIsAccepted).Name, typeof(CommandThatIsAccepted) }, { typeof(CommandThatThrowsProblemDetailsException).Name, typeof(CommandThatThrowsProblemDetailsException) } }; var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap); var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings); using (WebApp.Start("http://*****:*****@"..\..\wwwroot") }); app.UseStaticFiles(new StaticFileOptions { RequestPath = new PathString("/cedarjs"), FileSystem = new PhysicalFileSystem(@"..\..\..\Cedar.CommandHandling.Http.Js") }); app.Map("/test/commands", commandsApp => commandsApp.Use(commandHandlingMiddleware)); })) { Process.Start("http://localhost:8080/index.html"); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } }
public async Task Should_invoke_predispatch_hook() { var module = new CommandHandlerModule(); string correlationId = null; const string correlationIdKey = "CorrelationId"; module.For <Command>().Handle((commandMessage, __) => { correlationId = commandMessage.Metadata.Get <string>(correlationIdKey); return(Task.FromResult(0)); }); var settings = new CommandHandlingSettings(new CommandHandlerResolver(module)) { OnPredispatch = (metadata, headers) => { var correlationIdHeader = headers.SingleOrDefault(kvp => kvp.Key == correlationIdKey); if (correlationIdHeader.Value != null) { metadata[correlationIdKey] = correlationIdHeader.Value.SingleOrDefault(); } } }; var midFunc = CommandHandlingMiddleware.HandleCommands(settings); using (var client = midFunc.CreateEmbeddedClient()) { await client.PutCommand(new Command(), Guid.NewGuid(), customizeRequest : request => { request.Headers.Add(correlationIdKey, "cor-1"); }); correlationId.Should().Be("cor-1"); } }
private static void Main() { var resolver = new CommandHandlerResolver(new CommandModule()); var settings = new CommandHandlingSettings(resolver); var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings); using (WebApp.Start("http://*****:*****@"..\..\wwwroot") }); app.UseStaticFiles(new StaticFileOptions { RequestPath = new PathString("/cedarjs"), FileSystem = new PhysicalFileSystem(@"..\..\..\Cedar.HttpCommandHandling.Js") }); app.Map("/test/commands", commandsApp => commandsApp.Use(commandHandlingMiddleware)); })) { Process.Start("http://localhost:8080/index.html"); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } }
public void Can_set_ParseMediaType() { var sut = new CommandHandlingSettings(A.Fake <ICommandHandlerResolver>(), A.Fake <ResolveCommandType>()); var parseMediaType = A.Fake <ParseMediaType>(); sut.ParseMediaType = parseMediaType; sut.ParseMediaType.Should().Be(parseMediaType); }
public async Task Example_exception_handling() { var resolver = new CommandHandlerResolver(new CommandModule()); var settings = new CommandHandlingSettings(resolver) { // 10. Specify the exception -> HttpProblemDetails mapper here MapProblemDetailsFromException = MapExceptionToProblemDetails }; var middleware = CommandHandlingMiddleware.HandleCommands(settings); using (HttpClient client = middleware.CreateEmbeddedClient()) { // 11. Handling standard exceptions. try { await client.PutCommand(new CommandThatThrowsStandardException(), Guid.NewGuid()); } catch (HttpRequestException ex) { Console.WriteLine(ex.Message); } // 12. Handling explicit HttpProblemDetailsExceptions try { await client.PutCommand(new CommandThatThrowsProblemDetailsException(), Guid.NewGuid()); } catch (HttpProblemDetailsException <HttpProblemDetails> ex) { Console.WriteLine(ex.ProblemDetails.Detail); Console.WriteLine(ex.ProblemDetails.Status); } // 13. Handling mapped exceptions, same as #6 try { await client.PutCommand(new CommandThatThrowsMappedException(), Guid.NewGuid()); } catch (HttpProblemDetailsException <HttpProblemDetails> ex) { Console.WriteLine(ex.ProblemDetails.Detail); Console.WriteLine(ex.ProblemDetails.Status); } // 14. Handling custom HttpProblemDetailExceptions try { await client.PutCommand(new CommandThatThrowsCustomProblemDetailsException(), Guid.NewGuid()); } catch (CustomHttpProblemDetailsException ex) { Console.WriteLine(ex.ProblemDetails.Detail); Console.WriteLine(ex.ProblemDetails.Status); Console.WriteLine(ex.ProblemDetails.Name); } } }
public CommandHandlingFixture() { var module = CreateCommandHandlerModule(); var handlerResolver = new CommandHandlerResolver(module); var commandHandlingSettings = new CommandHandlingSettings(handlerResolver) { MapProblemDetailsFromException = CreateProblemDetails }; _midFunc = CommandHandlingMiddleware.HandleCommands(commandHandlingSettings); }
public void Configuration(IAppBuilder app) { app.Map("/api/commands", builder => { var moviesCommandModule = TinyIoCContainer.Current.Resolve <MoviesCommandModule>(); var directorsCommandModule = TinyIoCContainer.Current.Resolve <DirectorsCommandModule>(); var resolver = new CommandHandlerResolver(moviesCommandModule, directorsCommandModule); var settings = new CommandHandlingSettings(resolver); var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings); builder.Use(commandHandlingMiddleware); }); }
public void When_deserializer_throws_then_should_throw_HttpProblemDetailsException() { var sut = new CommandHandlingSettings(A.Fake <ICommandHandlerResolver>(), A.Fake <ResolveCommandType>()); Action act = () => { using (var reader = new StringReader("xyx")) { sut.DeserializeCommand(reader, typeof(CommandHandlingSettingsTests)); } }; act.ShouldThrowExactly <HttpProblemDetailsException <HttpProblemDetails> >() .And.ProblemDetails.Status.Should().Be(400); }
public void When_custom_deserializer_throws_then_should_throw_HttpProblemDetailsException() { var sut = new CommandHandlingSettings(A.Fake <ICommandHandlerResolver>(), A.Fake <ResolveCommandType>()) { DeserializeCommand = (_, __) => { throw new Exception(); } }; Action act = () => { using (var reader = new StringReader("xyx")) { sut.DeserializeCommand(reader, typeof(CommandHandlingSettingsTests)); } }; act.ShouldThrow <HttpProblemDetailsException <HttpProblemDetails> >(); }
public async Task Can_invoke_command_over_http() { // 1. Setup the middlware var resolver = new CommandHandlerResolver(new CommandModule()); var settings = new CommandHandlingSettings(resolver); var middleware = CommandHandlingMiddleware.HandleCommands(settings); // 2. Create an embedded HttpClient. This allows invoking of the // HttpPipeline in-memory without a server / listener. using (HttpClient client = middleware.CreateEmbeddedClient()) { // 3. This is as close as you can get to simulating a real client call // without needing real server. // Can use this to do acceptance testing also. await client.PutCommand(new Command(), Guid.NewGuid()); } }
static void Main() { Func <IFoo> getFoo = () => new DummyFoo(); var resolver = new CommandHandlerResolver(new CommandModule(getFoo)); var settings = new CommandHandlingSettings(resolver); var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings); // 5. Add the middleware to your owin pipeline using (WebApp.Start("http://localhost:8080", app => { app.Use(commandHandlingMiddleware); })) { Console.WriteLine("Press any key"); } }
public CommandHandlingFixture() { var module = CreateCommandHandlerModule(); var handlerResolver = new CommandHandlerResolver(module); CommandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { { typeof(Command).Name.ToLowerInvariant(), typeof(Command) }, { typeof(CommandThatThrowsStandardException).Name.ToLowerInvariant(), typeof(CommandThatThrowsStandardException) }, { typeof(CommandThatThrowsProblemDetailsException).Name.ToLowerInvariant(), typeof(CommandThatThrowsProblemDetailsException) }, { typeof(CommandThatThrowsMappedException).Name.ToLowerInvariant(), typeof(CommandThatThrowsMappedException) }, { typeof(CommandThatThrowsCustomProblemDetailsException).Name.ToLowerInvariant(), typeof(CommandThatThrowsCustomProblemDetailsException) } }; var commandHandlingSettings = new CommandHandlingSettings(handlerResolver, CommandMediaTypeMap) { MapProblemDetailsFromException = CreateProblemDetails }; _midFunc = CommandHandlingMiddleware.HandleCommands(commandHandlingSettings); }
public async Task Can_invoke_command_over_http() { var resolver = new CommandHandlerResolver(new CommandModule()); var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { { typeof(Command).FullName.ToLower(), typeof(Command) } }; // 1. Create the serializer var jsonSerializer = new JsonSerializer(); var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap) { // 2. Customize the deserialization DeserializeCommand = (commandReader, type) => { using (var reader = new JsonTextReader(commandReader)) { return(jsonSerializer.Deserialize(reader, type)); } } }; var middleware = CommandHandlingMiddleware.HandleCommands(settings); // 3. Customize the serialization SerializeCommand serializeCommand = (writer, command) => { jsonSerializer.Serialize(writer, command); }; // 3. Create an embedded HttpClient. This allows invoking of the // HttpPipeline in-memory without a server / listener. using (HttpClient client = middleware.CreateEmbeddedClient()) { // 3. This is as close as you can get to simulating a real client call // without needing real server. // Can use this to do acceptance testing also. await client.PutCommand(new Command(), Guid.NewGuid(), commandMediaTypeMap, serializeCommand : serializeCommand); } }
public void When_custom_deserializer_throws_HttpProblemDetailsException_then_it_should_propagate() { var expected = new HttpProblemDetailsException <HttpProblemDetails>(new HttpProblemDetails()); var sut = new CommandHandlingSettings(A.Fake <ICommandHandlerResolver>(), A.Fake <ResolveCommandType>()) { DeserializeCommand = (_, __) => { throw expected; } }; Exception thrown = null; try { using (var reader = new StringReader("xyx")) { sut.DeserializeCommand(reader, typeof(CommandHandlingSettingsTests)); } } catch (Exception ex) { thrown = ex; } thrown.ShouldBe(expected); }
static void Main() { var resolver = new CommandHandlerResolver(new CommandModule()); // 1. Create a map to resolve types from a key. // This could of course be done with reflection + conventions. // For the sake of example, we're going to be explict. var commandMap = new[] { typeof(CommandVersioning.V1.Command), typeof(CommandVersioning.V2.Command), }.ToDictionary(t => t.Name.ToLowerInvariant(), t => t); var resolveCommandType = new ResolveCommandType((typeName, version) => { // 2. In this example, we're not handling unversioned commands. You // may of course handle them. if (version == null) { return(null); // 3. Return null if the command type can't be resolved. } // 4. Here we're just converting the typeName to a key that matches our // convetion. var typeNameSegments = typeName.Split('.').ToList(); // my.type.name -> { my, type, name } typeNameSegments.Insert(typeNameSegments.Count - 1, "v" + version); // { my, type, name } -> { my, type, vX, name } typeName = string.Join(".", typeNameSegments); // { my, type, vX, name } -> my.type.vX.name Type commandType; commandMap.TryGetValue(typeName, out commandType); return(commandType); }); // 5. CommandHandlingSettings has a contructor overload to pass in the command type resolver. var settings = new CommandHandlingSettings(resolver, resolveCommandType); }