public async void SelectAsync_AmbiguousActions_LogIsCorrect() { // Arrange var sink = new TestSink(); var loggerFactory = new TestLoggerFactory(sink, enabled: true); var actions = new ActionDescriptor[] { new ActionDescriptor() { DisplayName = "A1" }, new ActionDescriptor() { DisplayName = "A2" }, }; var selector = CreateSelector(actions, loggerFactory); var routeContext = CreateRouteContext("POST"); var actionNames = string.Join(Environment.NewLine, actions.Select(action => action.DisplayName)); var expectedMessage = "Request matched multiple actions resulting in " + $"ambiguity. Matching actions: {actionNames}"; // Act await Assert.ThrowsAsync<AmbiguousActionException>(async () => { await selector.SelectAsync(routeContext); }); // Assert Assert.Empty(sink.Scopes); Assert.Single(sink.Writes); Assert.Equal(expectedMessage, sink.Writes[0].State?.ToString()); }
public void Accept_RejectsActionMatchWithMissingParameter() { // Arrange var action = new ActionDescriptor(); action.Parameters = new List<ParameterDescriptor>() { new ParameterDescriptor() { BindingInfo = new BindingInfo() { BindingSource = (new FromUriAttribute()).BindingSource, }, Name = "id", ParameterType = typeof(int), }, }; var constraint = new OverloadActionConstraint(); var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(action, new [] { constraint }), }; context.CurrentCandidate = context.Candidates[0]; context.RouteContext = CreateRouteContext(); // Act & Assert Assert.False(constraint.Accept(context)); }
public void Select_PrefersActionWithConstraints() { // Arrange var actionWithConstraints = new ActionDescriptor() { ActionConstraints = new List<IActionConstraintMetadata>() { new HttpMethodConstraint(new string[] { "POST" }), }, Parameters = new List<ParameterDescriptor>(), }; var actionWithoutConstraints = new ActionDescriptor() { Parameters = new List<ParameterDescriptor>(), }; var actions = new ActionDescriptor[] { actionWithConstraints, actionWithoutConstraints }; var selector = CreateSelector(actions); var context = CreateRouteContext("POST"); // Act var action = selector.Select(context); // Assert Assert.Same(action, actionWithConstraints); }
public ActionLogScope(ActionDescriptor action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } _action = action; }
/// <summary> /// Creates a new <see cref="ActionSelectorCandidate"/>. /// </summary> /// <param name="action">The <see cref="ActionDescriptor"/> representing a candidate for selection.</param> /// <param name="constraints"> /// The list of <see cref="IActionConstraint"/> instances associated with <paramref name="action"/>. /// </param> public ActionSelectorCandidate(ActionDescriptor action, IReadOnlyList<IActionConstraint> constraints) { if (action == null) { throw new ArgumentNullException(nameof(action)); } Action = action; Constraints = constraints; }
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action) { if(routeContext.HttpContext.Request.Method != "POST") { return false; } var value = routeContext.HttpContext.Request.Form[_submitButtonName]; return !string.IsNullOrEmpty(value); }
public static void ExecutedAction(this ILogger logger, ActionDescriptor action, long startTimestamp) { // Don't log if logging wasn't enabled at start of request as time will be wildly wrong. if (startTimestamp != 0) { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsed = new TimeSpan((long)(TimestampToTicks * (currentTimestamp - startTimestamp))); _actionExecuted(logger, action.DisplayName, elapsed.TotalMilliseconds, null); } }
public void GetApiDescription_IgnoresNonReflectedActionDescriptor() { // Arrange var action = new ActionDescriptor(); action.SetProperty(new ApiDescriptionActionData()); // Act var descriptions = GetApiDescriptions(action); // Assert Assert.Empty(descriptions); }
public static void AfterAction( this DiagnosticSource diagnosticSource, ActionDescriptor actionDescriptor, HttpContext httpContext, RouteData routeData) { if (diagnosticSource.IsEnabled("Microsoft.AspNet.Mvc.AfterAction")) { diagnosticSource.Write( "Microsoft.AspNet.Mvc.AfterAction", new { actionDescriptor, httpContext = httpContext, routeData = routeData }); } }
public void Accept_AcceptsActionWithSatisfiedParameters() { // Arrange var action = new ActionDescriptor(); action.Parameters = new List<ParameterDescriptor>() { new ParameterDescriptor() { BindingInfo = new BindingInfo() { BindingSource = (new FromUriAttribute()).BindingSource, }, Name = "id", ParameterType = typeof(int), }, new ParameterDescriptor() { BindingInfo = new BindingInfo() { BindingSource = (new FromUriAttribute()).BindingSource, }, Name = "quantity", ParameterType = typeof(int), }, }; var constraint = new OverloadActionConstraint(); var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(action, new [] { constraint }), }; context.CurrentCandidate = context.Candidates[0]; context.RouteContext = CreateRouteContext("?quantity=5", new { id = 17 }); // Act & Assert Assert.True(constraint.Accept(context)); }
private async Task InvokeActionAsync(HttpContext httpContext, ActionDescriptor actionDescriptor) { var routeData = httpContext.GetRouteData(); try { _diagnosticSource.BeforeAction(actionDescriptor, httpContext, routeData); using (_logger.ActionScope(actionDescriptor)) { _logger.ExecutingAction(actionDescriptor); var startTimestamp = _logger.IsEnabled(LogLevel.Information) ? Stopwatch.GetTimestamp() : 0; var actionContext = new ActionContext(httpContext, routeData, actionDescriptor); if (_actionContextAccessor != null) { _actionContextAccessor.ActionContext = actionContext; } var invoker = _actionInvokerFactory.CreateInvoker(actionContext); if (invoker == null) { throw new InvalidOperationException( Resources.FormatActionInvokerFactory_CouldNotCreateInvoker( actionDescriptor.DisplayName)); } await invoker.InvokeAsync(); _logger.ExecutedAction(actionDescriptor, startTimestamp); } } finally { _diagnosticSource.AfterAction(actionDescriptor, httpContext, routeData); } }
/// <summary> /// Creates a new <see cref="ActionConstraintProviderContext"/>. /// </summary> /// <param name="action">The <see cref="ActionDescriptor"/> for which constraints are being created.</param> /// <param name="items">The list of <see cref="ActionConstraintItem"/> objects.</param> public ActionConstraintProviderContext( HttpContext context, ActionDescriptor action, IList<ActionConstraintItem> items) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } if (items == null) { throw new ArgumentNullException(nameof(items)); } HttpContext = context; Action = action; Results = items; }
public void GetNormalizedRouteValue_ReturnsValueFromRouteConstraints_IfKeyHandlingIsRequired() { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { RouteConstraints = new[] { new RouteDataActionConstraint(key, "Route-Value") } }; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = "route-value"; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Equal("Route-Value", result); }
private static ActionContext GetActionContextWithActionDescriptor( IDictionary<string, object> routeValues, IDictionary<string, string> routesInActionDescriptor, bool isAttributeRouted) { var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); foreach (var kvp in routeValues) { routeData.Values.Add(kvp.Key, kvp.Value); } var actionDescriptor = new ActionDescriptor(); if (isAttributeRouted) { actionDescriptor.AttributeRouteInfo = new AttributeRouteInfo(); foreach (var kvp in routesInActionDescriptor) { actionDescriptor.RouteValueDefaults.Add(kvp.Key, kvp.Value); } } else { actionDescriptor.RouteConstraints = new List<RouteDataActionConstraint>(); foreach (var kvp in routesInActionDescriptor) { actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(kvp.Key, kvp.Value)); } } return new ActionContext(httpContext, routeData, actionDescriptor); }
private static ActionContext GetActionContext(IDictionary<string, object> routeValues) { var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); foreach (var kvp in routeValues) { routeData.Values.Add(kvp.Key, kvp.Value); } var actionDesciptor = new ActionDescriptor(); actionDesciptor.RouteConstraints = new List<RouteDataActionConstraint>(); return new ActionContext(httpContext, routeData, actionDesciptor); }
public void GetNormalizedRouteValue_ConvertsRouteValueToString() { using (new CultureReplacer()) { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { AttributeRouteInfo = new AttributeRouteInfo(), }; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = 43; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Equal("43", result); } }
private static ActionDescriptor CreateActionDescriptor(string area, string controller, string action) { var actionDescriptor = new ActionDescriptor() { Name = string.Format("Area: {0}, Controller: {1}, Action: {2}", area, controller, action), RouteConstraints = new List<RouteDataActionConstraint>(), }; actionDescriptor.RouteConstraints.Add( area == null ? new RouteDataActionConstraint("area", null) : new RouteDataActionConstraint("area", area)); actionDescriptor.RouteConstraints.Add( controller == null ? new RouteDataActionConstraint("controller", null) : new RouteDataActionConstraint("controller", controller)); actionDescriptor.RouteConstraints.Add( action == null ? new RouteDataActionConstraint("action", null) : new RouteDataActionConstraint("action", action)); return actionDescriptor; }
private static HttpContext GetHttpContext(ActionDescriptor actionDescriptor) { var actionProvider = new Mock<IActionDescriptorProvider>(MockBehavior.Strict); actionProvider .SetupGet(p => p.Order) .Returns(-1000); actionProvider .Setup(p => p.OnProvidersExecuting(It.IsAny<ActionDescriptorProviderContext>())) .Callback<ActionDescriptorProviderContext>(c => c.Results.Add(actionDescriptor)); actionProvider .Setup(p => p.OnProvidersExecuted(It.IsAny<ActionDescriptorProviderContext>())) .Verifiable(); var context = new Mock<HttpContext>(); context.Setup(o => o.RequestServices .GetService(typeof(IEnumerable<IActionDescriptorProvider>))) .Returns(new[] { actionProvider.Object }); context.Setup(o => o.RequestServices .GetService(typeof(IActionDescriptorCollectionProvider))) .Returns(new DefaultActionDescriptorCollectionProvider(context.Object.RequestServices)); return context.Object; }
public async Task SelectAsync_WithCatchAll_NoMatch() { // Arrange var actions = new ActionDescriptor[] { CreateAction(area: null, controller: "Store", action: "Buy"), CreateAction(area: null, controller: "Store", action: "Buy"), CreateAction(area: null, controller: "Store", action: "Buy"), }; actions[0].RouteConstraints.Add(new RouteDataActionConstraint("country", "CA")); actions[1].RouteConstraints.Add(new RouteDataActionConstraint("country", "US")); actions[2].RouteConstraints.Add(RouteDataActionConstraint.CreateCatchAll("country")); var selector = CreateSelector(actions); var context = CreateRouteContext("GET"); context.RouteData.Values.Add("controller", "Store"); context.RouteData.Values.Add("action", "Buy"); // Act var action = await selector.SelectAsync(context); // Assert Assert.Null(action); }
private IReadOnlyList<ApiDescription> GetApiDescriptions( ActionDescriptor action, List<MockFormatter> formatters) { var context = new ApiDescriptionProviderContext(new ActionDescriptor[] { action }); var options = new MvcOptions(); foreach (var formatter in formatters) { options.OutputFormatters.Add(formatter); } var optionsAccessor = new Mock<IOptions<MvcOptions>>(); optionsAccessor.SetupGet(o => o.Value) .Returns(options); var constraintResolver = new Mock<IInlineConstraintResolver>(); constraintResolver.Setup(c => c.ResolveConstraint("int")) .Returns(new IntRouteConstraint()); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var provider = new DefaultApiDescriptionProvider( optionsAccessor.Object, constraintResolver.Object, modelMetadataProvider); provider.OnProvidersExecuting(context); provider.OnProvidersExecuted(context); return new ReadOnlyCollection<ApiDescription>(context.Results); }
private IReadOnlyList<ApiDescription> GetApiDescriptions(ActionDescriptor action) { return GetApiDescriptions(action, CreateFormatters()); }
public async Task SelectAsync_ConstraintsInOrder_MultipleStages() { // Arrange var best = new ActionDescriptor() { ActionConstraints = new List<IActionConstraintMetadata>() { new BooleanConstraint() { Pass = true, Order = 0, }, new BooleanConstraint() { Pass = true, Order = 1, }, new BooleanConstraint() { Pass = true, Order = 2, }, }, }; var worst = new ActionDescriptor() { ActionConstraints = new List<IActionConstraintMetadata>() { new BooleanConstraint() { Pass = true, Order = 0, }, new BooleanConstraint() { Pass = true, Order = 1, }, new BooleanConstraint() { Pass = true, Order = 3, }, }, }; var actions = new ActionDescriptor[] { best, worst }; var selector = CreateSelector(actions); var context = CreateRouteContext("POST"); // Act var action = await selector.SelectAsync(context); // Assert Assert.Same(action, best); }
public void GetNormalizedRouteValue_ReturnsRouteDataValue_IfRouteConstraintKeyHandlingIsCatchAll() { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { RouteConstraints = new[] { RouteDataActionConstraint.CreateCatchAll(key) } }; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = "route-value"; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Equal("route-value", result); }
public async Task SelectAsync_Ambiguous() { // Arrange var expectedMessage = "Multiple actions matched. " + "The following actions matched route data and had all constraints satisfied:" + Environment.NewLine + Environment.NewLine + "Ambiguous1" + Environment.NewLine + "Ambiguous2"; var actions = new ActionDescriptor[] { CreateAction(area: null, controller: "Store", action: "Buy"), CreateAction(area: null, controller: "Store", action: "Buy"), CreateAction(area: null, controller: "Store", action: "Cart"), }; actions[0].DisplayName = "Ambiguous1"; actions[1].DisplayName = "Ambiguous2"; var selector = CreateSelector(actions); var context = CreateRouteContext("GET"); context.RouteData.Values.Add("controller", "Store"); context.RouteData.Values.Add("action", "Buy"); // Act var ex = await Assert.ThrowsAsync<AmbiguousActionException>(async () => { await selector.SelectAsync(context); }); // Assert Assert.Equal(expectedMessage, ex.Message); }
public void GetNormalizedRouteValue_ReturnsRouteValue_IfValueDoesNotMatchRouteConstraint() { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { RouteConstraints = new[] { new RouteDataActionConstraint(key, "different-value") } }; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = "route-value"; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Equal("route-value", result); }
private IReadOnlyList<IActionConstraint> GetConstraints(HttpContext httpContext, ActionDescriptor action) { if (action.ActionConstraints == null || action.ActionConstraints.Count == 0) { return null; } var items = new List<ActionConstraintItem>(action.ActionConstraints.Count); for (var i = 0; i < action.ActionConstraints.Count; i++) { items.Add(new ActionConstraintItem(action.ActionConstraints[i])); } var context = new ActionConstraintProviderContext(httpContext, action, items); for (var i = 0; i < _actionConstraintProviders.Length; i++) { _actionConstraintProviders[i].OnProvidersExecuting(context); } for (var i = _actionConstraintProviders.Length - 1; i >= 0; i--) { _actionConstraintProviders[i].OnProvidersExecuted(context); } var count = 0; for (var i = 0; i < context.Results.Count; i++) { if (context.Results[i].Constraint != null) { count++; } } if (count == 0) { return null; } var results = new IActionConstraint[count]; for (int i = 0, j = 0; i < context.Results.Count; i++) { var constraint = context.Results[i].Constraint; if (constraint != null) { results[j++] = constraint; } } return results; }
public void GetNormalizedRouteValue_ReturnsNull_IfRouteConstraintKeyHandlingIsDeny() { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { RouteConstraints = new[] { new RouteDataActionConstraint(key, routeValue: string.Empty) } }; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = "route-value"; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Null(result); }
public async Task SelectAsync_Fallback_ToActionWithoutConstraints() { // Arrange var nomatch1 = new ActionDescriptor() { ActionConstraints = new List<IActionConstraintMetadata>() { new BooleanConstraint() { Pass = true, Order = 0, }, new BooleanConstraint() { Pass = true, Order = 1, }, new BooleanConstraint() { Pass = false, Order = 2, }, }, }; var nomatch2 = new ActionDescriptor() { ActionConstraints = new List<IActionConstraintMetadata>() { new BooleanConstraint() { Pass = true, Order = 0, }, new BooleanConstraint() { Pass = true, Order = 1, }, new BooleanConstraint() { Pass = false, Order = 3, }, }, }; var best = new ActionDescriptor(); var actions = new ActionDescriptor[] { best, nomatch1, nomatch2 }; var selector = CreateSelector(actions); var context = CreateRouteContext("POST"); // Act var action = await selector.SelectAsync(context); // Assert Assert.Same(action, best); }
public void GetNormalizedRouteValue_UsesRouteValue_IfRouteValueDefaultsDoesNotMatchRouteValue() { // Arrange var key = "some-key"; var actionDescriptor = new ActionDescriptor { AttributeRouteInfo = new AttributeRouteInfo(), }; actionDescriptor.RouteValueDefaults[key] = "different-value"; var actionContext = new ActionContext { ActionDescriptor = actionDescriptor, RouteData = new RouteData() }; actionContext.RouteData.Values[key] = "route-value"; // Act var result = RazorViewEngine.GetNormalizedRouteValue(actionContext, key); // Assert Assert.Equal("route-value", result); }
private Task InvokeActionAsync(RouteContext context, ActionDescriptor actionDescriptor) { var actionContext = new ActionContext(context.HttpContext, context.RouteData, actionDescriptor); _actionContextAccessor.ActionContext = actionContext; var invoker = _actionInvokerFactory.CreateInvoker(actionContext); if (invoker == null) { throw new InvalidOperationException( Resources.FormatActionInvokerFactory_CouldNotCreateInvoker( actionDescriptor.DisplayName)); } return invoker.InvokeAsync(); }