zoukankan      html  css  js  c++  java
  • 续篇:新型Lamda版Html.RenderAction

    在前一篇博文中,我们实现了一个简单的支持Lamda表达式的Html.RenderAction。

    在评论中,向晚提到了Html.RenderAction的一个优点:

    ChildAciton的优势是可以应用OutputCahce特性实现局部缓存。

    我们当时用Html.RenderAction,而不用Html.RenderPartial,这也是一个重要原因。

    总结一下ChildAciton+PartialView的优势:

    1. 可以在“不同Action相同View”中方便地被共享
    2. 可以在“不同Action不同View”中方便地被共享
    3. “可以应用OutputCahce特性实现局部缓存”

    我们在解决另外一个问题时,发现它还有一个优势:

      4. 可以用ChildAciton直接处理Ajax请求。

    比如博客园首页加载“最新随笔列表”的应用场景,在用户打开页面时直接显示最新随笔(非ajax加载);在用户点击页面上的“刷新”链接时,通过ajax更新“最新随笔列表”。

    使用ChildAciton+PartialView,在首页页面视图中只需Html.RenderAction即可。

    @{ Html.RenderAction<AggSiteController>(c => c.PostList(1,20)); }

    同样的ChildAction可以直接服务于Ajax请求,实现了ChildAciton+PartialView的重用。

    这时,我们遇到了一个问题,在RenderAction的时候需要向Action传递参数,之前实现的简陋的Html.RenderAction并没有对此提供支持,需要改进一下。

    testzhangsan评论中获知,ASP.NET MVC 4中已经在实现Lamda版Html.RenderAction。签出ASP.NET MVC 4的源代码一下,果然实现了,向Action传参数的问题自然也被微软解决了。参照那段代码,精简一下就能解决我们的问题。

    向Action传参数,需要通过RouteValueDictionary,我们所要做的工作就是从Lamda表达式中获取参数名称与参数值,并还添加至RouteValueDictionary。

    完整代码如下:

    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    using System.Linq.Expressions;
    using System.Web.Routing;
    
    namespace System.Web.Mvc.Html
    {
        public static class HtmlHelperExtensions
        {
            public static void RenderAction<TController>(this HtmlHelper htmlHelper,
                Expression<Action<TController>> operation)
                where TController : Controller
            {
                var controllerName = typeof(TController).Name;
                if (controllerName.EndsWith("Controller"))
                {
                    controllerName = controllerName.Substring(0, 
                        controllerName.Length - "Controller".Length);
                }
    
                var call = operation.Body as MethodCallExpression;
                if (call != null)
                {
                    var actionName = call.Method.Name;
                    var parameters = call.Method.GetParameters();
                    if (parameters.Length > 0)
                    {
                        var routeValues = new RouteValueDictionary();
                        for (int i = 0; i < parameters.Length; i++)
                        {
                            var ce = call.Arguments[i] as ConstantExpression;
                            if (ce != null)
                            {
                                routeValues.Add(parameters[i].Name, ce.Value);
                            }
                            else
                            {
                                var lambda = Expression.Lambda(call.Arguments[i],
                                                             operation.Parameters);
                                Delegate d = lambda.Compile();
                                var value = d.DynamicInvoke(new object[1]);
                                routeValues.Add(parameters[i].Name, value);
                            }
                            
                        }
                        htmlHelper.RenderAction(actionName, controllerName, routeValues);
                    }
                    else
                    {
                        htmlHelper.RenderAction(actionName, controllerName);
                    }
                }
            }
        }
    }

    注:目前的这个实现不支持可空类型的参数,比如:public ActionResult PostList(int? pageIndex)。

    开源,真好! 

  • 相关阅读:
    递归函数及Java范例
    笔记本的硬盘坏了
    “References to generic type List should be parameterized”
    配置管理软件(configuration management software)介绍
    WinCE文件目录定制及内存调整
    使用Silverlight for Embedded开发绚丽的界面(3)
    wince国际化语言支持
    Eclipse IDE for Java EE Developers 与Eclipse Classic 区别
    WinCE Heartbeat Message的实现
    使用Silverlight for Embedded开发绚丽的界面(2)
  • 原文地址:https://www.cnblogs.com/dudu/p/mvc_renderaction_lamda_2.html
Copyright © 2011-2022 走看看