• 续篇:新型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)。

    开源,真好! 

  • 相关阅读:
    建站两个月,说说我的想法
    我见过的郭弃疾先生(兰亭集势CEO)
    C#数组和集合互相转换的几种方法的效率分析
    (五)React Ant Design Pro + .Net5 WebApi:后端环境搭建Autofac注入+ 泛型仓储
    关于C++中对私有的测试总结
    uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型(转)
    GDB调试
    linux删除乱码文件
    转:C++ nan
    vim
  • 原文地址:https://www.cnblogs.com/dudu/p/mvc_renderaction_lamda_2.html
Copyright © 2020-2023  润新知