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 settings = new CommandHandlingSettings( resolver, new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())); 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(); } }
/// <summary> /// Creats a command handling middlware. /// </summary> /// <param name="settings">Settings to configure the middleware.</param> /// <returns>An owin middleware function (MidFunc) that represents </returns> public static MidFunc HandleCommands(CommandHandlingSettings settings) { Condition.Requires(settings, "settings").IsNotNull(); return(next => { var webApiConfig = ConfigureWebApi(settings); var appBuilder = new AppBuilder(); appBuilder .UseWebApi(webApiConfig) .Run(ctx => next(ctx.Environment)); return appBuilder.Build(); }); }
/// <summary> /// Creats a command handling middlware. /// </summary> /// <param name="settings">Settings to configure the middleware.</param> /// <returns>An owin middleware function (MidFunc) that represents </returns> public static MidFunc HandleCommands(CommandHandlingSettings settings) { Ensure.That(settings, "settings").IsNotNull(); return next => { var webApiConfig = ConfigureWebApi(settings); var appBuilder = new AppBuilder(); appBuilder .UseWebApi(webApiConfig) .Run(ctx => next(ctx.Environment)); return appBuilder.Build(); }; }
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 CommandHandlerController(CommandHandlingSettings settings) { _settings = settings; var temp = _settings.OnPredispatch ?? ((_, __) => { }); _predispatch = (metadata, headers) => { metadata[CommandMessageExtensions.UserKey] = (User as ClaimsPrincipal) ?? new ClaimsPrincipal(new ClaimsIdentity()); try { temp(metadata, headers); } catch (Exception ex) { Logger.ErrorException("Exception occured invoking the Predispatch hook", ex); } }; }
public async Task Can_invoke_command_over_http() { // 1. Setup the middlware var resolver = new CommandHandlerResolver(new CommandModule()); var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { { typeof(Command).FullName.ToLower(), typeof(Command) } }; var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap); 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(), commandMediaTypeMap); } }
private static HttpConfiguration ConfigureWebApi(CommandHandlingSettings settings) { var container = new TinyIoCContainer(); container.Register(settings); container.Register(new RecyclableMemoryStreamManager()); var config = new HttpConfiguration { DependencyResolver = new TinyIoCDependencyResolver(container) }; config.Services.Replace(typeof(IHttpControllerTypeResolver), new CommandHandlingHttpControllerTypeResolver()); config.Filters.Add(new HttpProblemDetailsExceptionFilterAttribute(settings.MapProblemDetailsFromException)); config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never; config.MapHttpAttributeRoutes(); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+json")); config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.None; return config; }
public CommandHandlerController( CommandHandlingSettings settings, RecyclableMemoryStreamManager recyclableMemoryStreamManager) { _settings = settings; _recyclableMemoryStreamManager = recyclableMemoryStreamManager; var temp = _settings.OnPredispatch ?? ((_, __) => { }); _predispatch = (metadata, headers) => { metadata[CommandMessageExtensions.UserKey] = (User as ClaimsPrincipal) ?? new ClaimsPrincipal(new ClaimsIdentity()); try { temp(metadata, headers); } catch(Exception ex) { s_logger.ErrorException("Exception occured invoking the Predispatch hook", ex); } }; }
private static HttpConfiguration ConfigureWebApi(CommandHandlingSettings settings) { var container = new TinyIoCContainer(); container.Register(settings); var config = new HttpConfiguration { DependencyResolver = new TinyIoCDependencyResolver(container) }; config.Services.Replace(typeof(IHttpControllerTypeResolver), new CommandHandlingHttpControllerTypeResolver()); config.Filters.Add(new HttpProblemDetailsExceptionFilterAttribute(settings.MapProblemDetailsFromException)); config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never; config.MapHttpAttributeRoutes(); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+json")); config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.None; return(config); }
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 commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()) { { typeof(Command).Name.ToLower(), typeof(Command) } }; var settings = new CommandHandlingSettings(new CommandHandlerResolver(module), commandMediaTypeMap) { 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(), commandMediaTypeMap, customizeRequest: request => { request.Headers.Add(correlationIdKey, "cor-1"); }); correlationId.Should().Be("cor-1"); } }
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.Should().Be(expected); }