public static FormFlowInstanceId GenerateForRouteValues( FormFlowDescriptor flowDescriptor, HttpRequest httpRequest, RouteData routeData) { if (flowDescriptor == null) { throw new ArgumentNullException(nameof(flowDescriptor)); } if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (routeData == null) { throw new ArgumentNullException(nameof(routeData)); } if (flowDescriptor.IdGenerationSource != IdGenerationSource.RouteValues) { throw new ArgumentException( $"{nameof(flowDescriptor)}'s {nameof(flowDescriptor.IdGenerationSource)} must be {IdGenerationSource.RouteValues}."); } if (!TryResolveForRouteValues(flowDescriptor, routeData, out var instanceId)) { var routeParameterNameList = string.Join(", ", flowDescriptor.IdRouteParameterNames); throw new InvalidOperationException( $"One or more route parameters are missing. Flow requires: {routeParameterNameList}."); } return(instanceId); }
public async Task GetOrCreateInstanceAsync_StateTypeDoesNotMatchDescriptor_ThrowsInvalidOperationException() { // Arrange var key = "test-flow"; var stateType = typeof(TestState); var state = new TestState(); var flowDescriptor = new FormFlowDescriptor(key, stateType, IdGenerationSource.RandomId); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); var actionDescriptor = new ActionDescriptor(); actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var stateProvider = new Mock <IUserInstanceStateProvider>(); var instanceFactory = new FormFlowInstanceFactory(flowDescriptor, actionContext, stateProvider.Object); // Act & Assert await Assert.ThrowsAsync <InvalidOperationException>( () => instanceFactory.GetOrCreateInstanceAsync(() => Task.FromResult(new AnotherTestState()))); }
public static FormFlowInstanceId Generate( FormFlowDescriptor flowDescriptor, HttpRequest httpRequest, RouteData routeData) { if (flowDescriptor == null) { throw new ArgumentNullException(nameof(flowDescriptor)); } if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (routeData == null) { throw new ArgumentNullException(nameof(routeData)); } if (flowDescriptor.IdGenerationSource == IdGenerationSource.RandomId) { return(GenerateForRandomId()); } else if (flowDescriptor.IdGenerationSource == IdGenerationSource.RouteValues) { return(GenerateForRouteValues(flowDescriptor, httpRequest, routeData)); } else { throw new NotSupportedException($"Unknown IdGenerationSource: '{flowDescriptor.IdGenerationSource}'."); } }
public async Task GetOrCreateInstanceAsync_InstanceDoesNotAlreadyExist_CreatesNewInstance() { // Arrange var key = "test-flow"; var stateType = typeof(TestState); var state = new TestState(); var flowDescriptor = new FormFlowDescriptor(key, stateType, IdGenerationSource.RandomId); var stateProvider = new InMemoryInstanceStateProvider(); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); var actionDescriptor = new ActionDescriptor(); actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var instanceFactory = new FormFlowInstanceFactory(flowDescriptor, actionContext, stateProvider); var newState = new TestState(); // Act var instance = await instanceFactory.GetOrCreateInstanceAsync(() => Task.FromResult(newState)); // Assert Assert.NotNull(instance); Assert.Same(newState, instance.State); }
public FormFlowInstanceFactory( FormFlowDescriptor flowDescriptor, ActionContext actionContext, IUserInstanceStateProvider stateProvider) { _flowDescriptor = flowDescriptor ?? throw new ArgumentNullException(nameof(flowDescriptor)); _actionContext = actionContext ?? throw new ArgumentNullException(nameof(actionContext)); _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); }
public void OnActionExecuting_OptionsHaveNullHandler_DoesNotSetResult() { // Arrange var key = "key"; var stateType = typeof(MyState); MissingInstanceHandler handler = null; var options = new FormFlowOptions() { MissingInstanceHandler = handler }; var services = new ServiceCollection() .AddSingleton(Options.Create(options)) .BuildServiceProvider(); var flowDescriptor = new FormFlowDescriptor(key, stateType, IdGenerationSource.RandomId); var httpContext = new DefaultHttpContext(); httpContext.RequestServices = services; var routeData = new RouteData(); var actionDescriptor = new ActionDescriptor() { Parameters = new List <ParameterDescriptor>() { new ParameterDescriptor() { Name = "instance", ParameterType = typeof(FormFlowInstance) } } }; actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var actionArguments = new Dictionary <string, object>(); var context = new ActionExecutingContext( actionContext, new List <IFilterMetadata>(), actionArguments, controller: null); var filter = new MissingInstanceActionFilter(); // Act filter.OnActionExecuting(context); // Assert Assert.Null(context.Result); }
public void CreateInstance_CreatesInstanceWithStateProvider() { // Arrange var key = "test-flow"; var stateType = typeof(TestState); var flowDescriptor = new FormFlowDescriptor(key, stateType, IdGenerationSource.RandomId); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); var actionDescriptor = new ActionDescriptor(); actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var stateProvider = new InMemoryInstanceStateProvider(); var instanceFactory = new FormFlowInstanceFactory(flowDescriptor, actionContext, stateProvider); var state = new TestState(); var properties = new Dictionary <object, object>() { { "foo", 42 }, { "bar", "baz" } }; // Act var instance = instanceFactory.CreateInstance(state, properties); // Assert Assert.NotNull(instance); Assert.Equal(key, instance.Key); Assert.Equal(stateType, instance.StateType); Assert.Same(state, instance.State); Assert.Equal(2, instance.Properties.Count); Assert.Equal(42, instance.Properties["foo"]); Assert.Equal("baz", instance.Properties["bar"]); var feature = httpContext.Features.Get <FormFlowInstanceFeature>(); Assert.NotNull(feature); Assert.Same(instance, feature.Instance); }
public void TryResolve_RandomIdGenerationSourceMissingQueryParameter_ReturnsFalse() { // Arrange var flowDescriptor = new FormFlowDescriptor( key: "key", stateType: typeof(MyState), idGenerationSource: IdGenerationSource.RandomId); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); // Act var created = FormFlowInstanceId.TryResolve(flowDescriptor, httpContext.Request, routeData, out var instanceId); // Assert Assert.False(created); }
public static bool TryResolveForRouteValues( FormFlowDescriptor flowDescriptor, RouteData routeData, out FormFlowInstanceId instanceId) { if (flowDescriptor == null) { throw new ArgumentNullException(nameof(flowDescriptor)); } if (routeData == null) { throw new ArgumentNullException(nameof(routeData)); } if (flowDescriptor.IdGenerationSource != IdGenerationSource.RouteValues) { throw new ArgumentException( $"{nameof(flowDescriptor)}'s {nameof(flowDescriptor.IdGenerationSource)} must be {IdGenerationSource.RouteValues}."); } var routeValues = routeData.Values; var instanceRouteValues = new RouteValueDictionary(); foreach (var routeParam in flowDescriptor.IdRouteParameterNames) { var routeValue = routeValues[routeParam]?.ToString(); if (string.IsNullOrEmpty(routeValue)) { instanceId = default; return(false); } instanceRouteValues.Add(routeParam, routeValue); } var id = GenerateIdForRouteValues(flowDescriptor.Key, instanceRouteValues); instanceId = new FormFlowInstanceId(id, instanceRouteValues); return(true); }
public async Task GetOrCreateInstanceAsync_InstanceAlreadyExists_ReturnsExistingInstance() { // Arrange var key = "test-flow"; var stateType = typeof(TestState); var state = new TestState(); var flowDescriptor = new FormFlowDescriptor(key, stateType, IdGenerationSource.RandomId); var stateProvider = new InMemoryInstanceStateProvider(); var instanceId = FormFlowInstanceId.GenerateForRandomId(); var existingInstance = FormFlowInstance.Create( stateProvider, key, instanceId, stateType, state, new Dictionary <object, object>()); var httpContext = new DefaultHttpContext(); httpContext.Features.Set(new FormFlowInstanceFeature(existingInstance)); var routeData = new RouteData(); var actionDescriptor = new ActionDescriptor(); actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var instanceFactory = new FormFlowInstanceFactory(flowDescriptor, actionContext, stateProvider); // Act var instance = await instanceFactory.GetOrCreateInstanceAsync(() => Task.FromResult(new TestState())); // Assert Assert.Same(existingInstance, instance); }
public void TryResolve_RandomIdGenerationSourceContainsQueryParameter_ReturnsTrue() { // Arrange var flowDescriptor = new FormFlowDescriptor( key: "key", stateType: typeof(MyState), idGenerationSource: IdGenerationSource.RandomId); var httpContext = new DefaultHttpContext(); httpContext.Request.QueryString = new QueryString("?ffiid=some-id"); var routeData = new RouteData(); // Act var created = FormFlowInstanceId.TryResolve(flowDescriptor, httpContext.Request, routeData, out var instanceId); // Assert Assert.True(created); Assert.Equal("some-id", instanceId.ToString()); }
public void CreateInstance_RouteValuesIdGenerationSource_CreatesInstanceWithGeneratedId() { // Arrange var key = "test-flow"; var stateType = typeof(TestState); var flowDescriptor = new FormFlowDescriptor( key, stateType, IdGenerationSource.RouteValues, idRouteParameterNames: new[] { "id1", "id2" }); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(new RouteValueDictionary() { { "id1", "foo" }, { "id2", "bar" } }); var actionDescriptor = new ActionDescriptor(); actionDescriptor.SetProperty(flowDescriptor); var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); var stateProvider = new InMemoryInstanceStateProvider(); var instanceFactory = new FormFlowInstanceFactory(flowDescriptor, actionContext, stateProvider); var state = new TestState(); // Act var instance = instanceFactory.CreateInstance(state); // Assert Assert.NotNull(instance); Assert.Equal("test-flow?id1=foo&id2=bar", instance.InstanceId); }
public void TryResolve_RouteValuesGenerationSourceMissingRouteParameter_ReturnsFalse() { // Arrange var flowDescriptor = new FormFlowDescriptor( key: "key", stateType: typeof(MyState), idGenerationSource: IdGenerationSource.RouteValues, idRouteParameterNames: new[] { "id1", "id2" }); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(new RouteValueDictionary() { { "id1", "foo" } }); // Act var created = FormFlowInstanceId.TryResolve(flowDescriptor, httpContext.Request, routeData, out var instanceId); // Assert Assert.False(created); }
public void TryResolve_RouteValuesGenerationSourceContainsAllRouteParameters_ReturnsTrue() { // Arrange var flowDescriptor = new FormFlowDescriptor( key: "key", stateType: typeof(MyState), idGenerationSource: IdGenerationSource.RouteValues, idRouteParameterNames: new[] { "id1", "id2" }); var httpContext = new DefaultHttpContext(); var routeData = new RouteData(new RouteValueDictionary() { { "id1", "foo" }, { "id2", "bar" } }); // Act var created = FormFlowInstanceId.TryResolve(flowDescriptor, httpContext.Request, routeData, out var instanceId); // Assert Assert.True(created); Assert.Equal("key?id1=foo&id2=bar", instanceId.ToString()); }
private void AddMetadataToAction(ActionModel action) { var descriptor = new FormFlowDescriptor(Key, StateType, IdGenerationSource, IdRouteParameterNames); action.Properties.Add(typeof(FormFlowDescriptor), descriptor); }