当action方法不采用原始类型时,使用强类型的ActionLink [英] Using a strongly typed ActionLink when the action method doesn't take a primitive type

查看:108
本文介绍了当action方法不采用原始类型时,使用强类型的ActionLink的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道我该怎么做:

Html.ActionLink(c => c.SomeAction(new MessageObject {Id = 1}))

Html.ActionLink(c => c.SomeAction(new MessageObject { Id = 1 } ))

这应该输出带有 / Controller / SomeAction / 1网址的链接,并指向以下行中的ActionMethod:

This should output a link with the url of "/Controller/SomeAction/1", pointing at an ActionMethod along the lines of:

public Controller : Controller
{
  public ActionResult SomeMethod(MessageObject message)
  {
      // do something with the message
      return View();
  }
}

我写了一些类似的形式来生成表格,但是不需要在网址末尾包含Id值。基本上,我想在路线中进行某种反向查找,但找不到有关如何执行此操作的文档。我有一个ModelBinder设置,可以从GET和POST参数构建一个MessageObject,但是我不确定如何反转该过程。

I've written something similar for generating forms, but that doens't need to include the Id value on the end of the Url. Basically I want to do some sort of reverse lookup in my routes but I can't find any doco on how I might go about doing that. I have a ModelBinder setup that is able to build a MessageObject from GET and POST parameters, but I'm not sure how I can reverse the process.

谢谢,
Matt

Thanks, Matt

推荐答案

最后,我最终将以下代码包装在HtmlHelper扩展方法中。这将允许我使用
Html.ActionLink(c => c.SomeAction(new MessageObject {Id = 1}))

In the end I ended up wrapping the following code in an HtmlHelper extension method. This would allow me to use something like Html.ActionLink(c => c.SomeAction(new MessageObject { Id = 1 } ))

 public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action)
            where TController : Controller
        {
            Guard.Against<ArgumentNullException>(action == null, @"Action passed to GetRouteValuesFromExpression cannot be null.");
            MethodCallExpression methodCall = action.Body as MethodCallExpression;
            Guard.Against<InvalidOperationException>(methodCall == null, @"Action passed to GetRouteValuesFromExpression must be method call");
            string controllerName = typeof(TController).Name;
            Guard.Against<InvalidOperationException>(!controllerName.EndsWith("Controller"), @"Controller passed to GetRouteValuesFromExpression is incorrect");

            RouteValueDictionary rvd = new RouteValueDictionary();
            rvd.Add("Controller", controllerName.Substring(0, controllerName.Length - "Controller".Length));
            rvd.Add("Action", methodCall.Method.Name);

            AddParameterValuesFromExpressionToDictionary(rvd, methodCall);
            return rvd;
        }

        /// <summary>
        /// Adds a route value for each parameter in the passed in expression.  If the parameter is primitive it just uses its name and value
        /// if not, it creates a route value for each property on the object with the property's name and value.
        /// </summary>
        /// <param name="routeValues"></param>
        /// <param name="methodCall"></param>
        private static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary routeValues, MethodCallExpression methodCall)
        {
            ParameterInfo[] parameters = methodCall.Method.GetParameters();
            methodCall.Arguments.Each(argument =>
            {
                int index = methodCall.Arguments.IndexOf(argument);

                ConstantExpression constExpression = argument as ConstantExpression;
                if (constExpression != null)
                {
                    object value = constExpression.Value;
                    routeValues.Add(parameters[index].Name, value);
                }
                else
                {
                    object actualArgument = argument;
                    MemberInitExpression expression = argument as MemberInitExpression;
                    if (expression != null)
                    {
                        actualArgument = Expression.Lambda(argument).Compile().DynamicInvoke();
                    }

                    // create a route value for each property on the object
                    foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(actualArgument))
                    {
                        object obj2 = descriptor.GetValue(actualArgument);
                        routeValues.Add(descriptor.Name, obj2);
                    }
                }
            });
        }

这篇关于当action方法不采用原始类型时,使用强类型的ActionLink的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆