Asp.Net核心中的@ Html.Action [英] @Html.Action in Asp.Net Core

查看:62
本文介绍了Asp.Net核心中的@ Html.Action的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Asp.net Core中的@Html.Action在哪里? 我可以看到@Html.ActionLink,但不能像以前那样直接调用Action.

Where is @Html.Action in Asp.net Core? I can see @Html.ActionLink but not a direct call to an Action as before.

它是否已被ViewComponents取代?

Was it replaced by ViewComponents?

推荐答案

更新:从2.2.2版开始,HttpContextAccessor将上下文保留在一个对象中(据说是为了防止内部请求混淆),这会影响当前解决方案...因此您需要为IHttpContextAccessor(旧版本)提供以下实现并将其注册为单例:

Update: As of 2.2.2 HttpContextAccessor keep the context in an object (supposedly to prevent inter request mix up) and it impacts the current solution... So you need to provide the following implementation for IHttpContextAccessor (an old version) and register it as a singleton:

public class HttpContextAccessor : IHttpContextAccessor
{
    private static AsyncLocal<HttpContext> _httpContextCurrent = new AsyncLocal<HttpContext>();
    HttpContext IHttpContextAccessor.HttpContext { get => _httpContextCurrent.Value; set => _httpContextCurrent.Value = value; }
}


对于asp.net核心2


For asp.net core 2

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.0版未编译的内容,并进行了一些调整.当前的httpcontext和当前的actioncontext有2个美化的静态值.在IHttpContextFactory.Create中设置了一个用于httpcontext的代码,在代码中设置了一个用于actioncontext的代码.请注意,根据使用的功能,IActionContextAccessorIHttpContextAccessor可能默认情况下未注册,因此您可能需要在启动时添加它们:

It is based on Aries response. I corrected what wasn't compiling for 2.0 and I added a couple of tweaks. There are 2 glorified static values for the current httpcontext and the current actioncontext. The one for httpcontext is set in IHttpContextFactory.Create and I set the one for actioncontext in the code. Note that depending on the features you use IActionContextAccessor and IHttpContextAccessor may not be registered by default, so you may need to add them in your startup:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

HttpContext只是HttpContext.Features的包装器,因此,如果您在其中一个更改了某些内容,则在另一个更改中也做了更改...我将在最后的try/catch中重置我所知道的内容.

HttpContext is just a wrapper around HttpContext.Features, so if you change something in one, it also changes in the other... I reset what I know about in the finally of the try/catch.

我从Items缓存中删除了IUrlHelper,因为即使构建urlHelper的actionContext不同(IUrlHelperFactory.GetUrlHelper),该值也将被重用.

I removed the IUrlHelper from the Items cache since this value will be reused even if the actionContext to build the urlHelper is different(IUrlHelperFactory.GetUrlHelper).

Asp.net core 2.0假设您不会这样做,那么很有可能还有其他缓存的东西,因此我建议在使用此方法时要小心,如果不需要,请不要这样做.

Asp.net core 2.0 assumes you won't do this, there is a good chance there are other cached things, so I recommend to be careful when using this and just don't if you don't need to.

这篇关于Asp.Net核心中的@ Html.Action的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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