ASP.NET-MVC-Lambda-Expression-Helpers icon indicating copy to clipboard operation
ASP.NET-MVC-Lambda-Expression-Helpers copied to clipboard

RouteValueDictionary support

Open waynebrantley opened this issue 7 years ago • 4 comments

Your methods like RedirectToActionPermanent, Url.Action, etc. all take an optional object for route values. This works most of the time.

However, if you pass in an actual ``RouteValueDictonary' to the methods they do not work. The standard MVC library code that takes this kind of value does work.

Url.Action<SomeController>(c=>c.SomeMethod(), someRouteValueDictionary) should work.

You could create overloads that accept the RouteValueDictionary and act appropriately:

        public static string Action<TController>(this UrlHelper url, Expression<Action<TController>> action, RouteValueDictionary routeValues) where TController : Controller
        {
            RouteInformation routeInformation = FromExpression<TController>(action, routeValues);
            return url.Action(routeInformation.ActionName, routeInformation.ControllerName, routeInformation.RouteValueDictionary);
        }

        public static string Action<TController>(this UrlHelper url, Expression<Func<TController, Task>> action, RouteValueDictionary routeValues) where TController : Controller
        {
            RouteInformation routeInformation = FromExpression<TController>(action, routeValues);
            return url.Action(routeInformation.ActionName, routeInformation.ControllerName, routeInformation.RouteValueDictionary);
        }

        public static RouteInformation FromExpression<TController>(LambdaExpression action, RouteValueDictionary routeValueDictionary)
                   where TController : Controller
        {
            string actionName = action.GetActionName();

            var controllerType = typeof(TController);
            string controllerName = controllerType.GetControllerName();

            routeValueDictionary.ProcessParameters(action);
            routeValueDictionary.ProcessArea(controllerType);
            var routeInformation = new RouteInformation(actionName, controllerName, routeValueDictionary);
            return routeInformation;
        }

That would be a lot of overloads.

Or you could create a shared routine that creates the initial route value dictionary correctly, something like

private RouteValueDictionary GetDictionaryFromObject( object routeValues){
   if (routeValues is RouteValueDictionary)
     return (RouteValueDictionary)routeValues;
  return new RouteValueDictionary(routeValues);

Optionally, Microsoft evidently uses TypeHelper.ObjectToDictionary() so potentially you could use that too?

waynebrantley avatar Jan 22 '17 20:01 waynebrantley

@ivaylokenov Any thoughts on the above? Also, there are no tests in this project. Would you object to adding Xunit or something with a few tests?

waynebrantley avatar Jan 28 '17 19:01 waynebrantley

@waynebrantley The above methods can be added to the library. I will have some spare time this weekend and will take a look. As for tests - I believe there are necessary, will add them too. If you are willing to help, I accept all kinds of PR. 👍

ivaylokenov avatar Jan 31 '17 11:01 ivaylokenov

Well, I created tests based on Nunit3 to validate my performance pull request. However, I did not submit a pull request of that, because was not sure you would accept it. And didn't know if Nunit was what you would use, etc. (This is why my PR had some compile issues, I copied and pasted the code into github, due to all the other project changes I made)

waynebrantley avatar Jan 31 '17 14:01 waynebrantley

@waynebrantley NUnit is fine. You can add it, if you decide. I am using it @ MyTested.WebApi 👍

ivaylokenov avatar Jan 31 '17 19:01 ivaylokenov