// Associates the action method argument to the corresponding resource property // used to populate the argument. This is used when sending the route-info to // ASP.NET Core to resolve the corresponding URL. private void SetRouteValues(LambdaExpression expression) { // The specified controller action declared method parameters: var controllerAction = (MethodCallExpression)expression.Body; var actionParams = controllerAction.Method.GetParameters() .OrderBy(p => p.Position) .ToArray(); for (int i = 0; i < controllerAction.Arguments.Count; i++) { // The input argument to the action method parameter: var passedArg = controllerAction.Arguments[i]; if (passedArg is MemberExpression propExpArg) { var propInfo = (PropertyInfo)propExpArg.Member; var actionParam = actionParams[i]; var routeValue = new RouteParameter(actionParam.Name, propInfo); _resourceLink.AddRouteValue(routeValue); continue; } // This is the case when the action parameter specifies a default value. if (passedArg is UnaryExpression unaryExpArg) { var operand = (MemberExpression)unaryExpArg.Operand; var propInfo = (PropertyInfo)operand.Member; var actionParam = actionParams[i]; var routeValue = new RouteParameter(actionParam.Name, propInfo); _resourceLink.AddRouteValue(routeValue); } } }
/// <summary> /// Adds a mapping indicating the resource property corresponding to an action parameter. /// </summary> /// <param name="routeParam">Mapping between action parameter and corresponding resource property.</param> public void AddRouteValue(RouteParameter routeParam) { if (routeParam == null) { throw new ArgumentNullException(nameof(routeParam), "Route parameter cannot be null."); } if (_routeValues.Any(rv => rv.ActionParamName == routeParam.ActionParamName)) { throw new ArgumentException($"The action parameter named: {routeParam.ActionParamName} has already been added."); } _routeValues.Add(routeParam); }