• Asp.Net Core 之 @Html.Action 迁移


    想必只要 接触了 net core的小伙伴们 已经发现 @html.Action()方法 官方已经不提供支持了,转而使用 ViewComponents替代了,同时也增加了TagHelper。但是 如果想用以前的@Html.Action()方法,我们其实可以自己动手去实现它。

    下面就开始 实现之旅吧!

    1、创建 静态类 HtmlHelperViewExtensions,其命名空间为  Microsoft.AspNetCore.Mvc.Rendering。这样我们直接用@Html直接可以 使用Action方法了。

    using Microsoft.AspNetCore.Html;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Infrastructure;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Extensions.DependencyInjection;
    using System;
    using System.IO;
    using System.Threading.Tasks;
    
    namespace Microsoft.AspNetCore.Mvc.Rendering
    {
        public static class HtmlHelperViewExtensions
        {
            public static IHtmlContent Action(this IHtmlHelper helper, string action, object parameters = null)
            {
                var controller = (string)helper.ViewContext.RouteData.Values["controller"];
    
                return Action(helper, action, controller, parameters);
            }
    
            public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, object parameters = null)
            {
                var area = (string)helper.ViewContext.RouteData.Values["area"];
    
                return Action(helper, action, controller, area, parameters);
            }
    
            public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
            {
                if (action == null)
                    throw new ArgumentNullException("action");
    
                if (controller == null)
                    throw new ArgumentNullException("controller");
    
    
                var task = RenderActionAsync(helper, action, controller, area, parameters);
    
                return task.Result;
            }
    
            private static async Task<IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
            {
                // fetching required services for invocation
                var serviceProvider = helper.ViewContext.HttpContext.RequestServices;
                var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
                var httpContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IHttpContextAccessor>();
                var actionSelector = serviceProvider.GetRequiredService<IActionSelector>();
    
                // creating new action invocation context
                var routeData = new RouteData();
                foreach (var router in helper.ViewContext.RouteData.Routers)
                {
                    routeData.PushState(router, null, null);
                }
                routeData.PushState(null, new RouteValueDictionary(new { controller = controller, action = action, area = area }), null);
                routeData.PushState(null, new RouteValueDictionary(parameters ?? new { }), null);
    
                //get the actiondescriptor
                RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext) { RouteData = routeData };
                var candidates = actionSelector.SelectCandidates(routeContext);
                var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates);
    
                var originalActionContext = actionContextAccessor.ActionContext;
                var originalhttpContext = httpContextAccessor.HttpContext;
                try
                {
                    var newHttpContext = serviceProvider.GetRequiredService<IHttpContextFactory>().Create(helper.ViewContext.HttpContext.Features);
                    if (newHttpContext.Items.ContainsKey(typeof(IUrlHelper)))
                    {
                        newHttpContext.Items.Remove(typeof(IUrlHelper));
                    }
                    newHttpContext.Response.Body = new MemoryStream();
                    var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
                    actionContextAccessor.ActionContext = actionContext;
                    var invoker = serviceProvider.GetRequiredService<IActionInvokerFactory>().CreateInvoker(actionContext);
                    await invoker.InvokeAsync();
                    newHttpContext.Response.Body.Position = 0;
                    using (var reader = new StreamReader(newHttpContext.Response.Body))
                    {
                        return new HtmlString(reader.ReadToEnd());
                    }
                }
                catch (Exception ex)
                {
                    return new HtmlString(ex.Message);
                }
                finally
                {
                    actionContextAccessor.ActionContext = originalActionContext;
                    httpContextAccessor.HttpContext = originalhttpContext;
                    if (helper.ViewContext.HttpContext.Items.ContainsKey(typeof(IUrlHelper)))
                    {
                        helper.ViewContext.HttpContext.Items.Remove(typeof(IUrlHelper));
                    }
                }
            }
        }
    }
    

      

    2、 在Startup中的 ConfigureServices 方法添加:

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor();

    services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

    (备注:因为net core 默认不将IHttpContextAccessor,IActionContextAccessor 依赖注入,所以需要手动进行依赖注入)

    3、在页面中,我们就可以直接用 @Html.Action()方法 直接请求 控制器的方法了。          

    4、小结:如今微软官方已经提供了 新的 TagHelper、View components 来替代之前的写法。这个教程只适用于对视图层不想做更变的小伙伴使用。如果 是新项目的,还是建议使用 View components!

    转自:https://blog.csdn.net/huanghuangtongxue/article/details/78987833

  • 相关阅读:
    phalcon之视图缓存
    Java NIO框架Netty教程(一) – Hello Netty
    setsockopt的作用
    支持向量机通俗导论(理解SVM的三层境地)
    quartz中的corn表达式(转)
    Applet 数字签名技术全然攻略
    SJTU 3001. 二哥的幸运
    OGRE之跳出漫长的编译等待
    VB.NET 数组的定义 动态使用 多维数组
    【Python】用Python的“结巴”模块进行分词
  • 原文地址:https://www.cnblogs.com/GavinSun/p/9244833.html
Copyright © 2020-2023  润新知