@ Html.Action i Asp.Net Kjerne

stemmer
27

Hvor er @Html.Actioni Asp.net Kjerne? Jeg kan se @Html.ActionLink, men ikke en direkte oppfordring til en handling som før.

Ble det erstattet av ViewComponents?

Publisert på 13/11/2014 klokken 17:17
kilden bruker
På andre språk...                            


9 svar

stemmer
25

Ja, ViewComponents ville være den nye måten å gjøre dette på, men de er ikke akkurat det samme som det @Html.Actiongjorde før selv ... for eksempel i MVC5 og tidligere, påkalle 'barnets handlinger' vil også utføre noen filtre (for eksempel hvis kontrolleren hadde filtre dekorert på dem) å gi dem inntrykk som vanlige handlinger ... men dette er ikke sant med ViewComponents og de utføres i sammenheng med faktiske forespørselen ...

Mer info om visning komponenter: http://www.asp.net/vnext/overview/aspnet-vnext/vc#intro

Oppdatering: linken er endret til

https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components

Svarte 14/11/2014 kl. 19:03
kilden bruker

stemmer
12

ViewComponents er stor, men ikke så bra for Ajax.

Hvis du virkelig savner @ Html.RenderAction metoden, så her er en rask implementering jeg kastet sammen for AspNetCore.

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;

namespace Microsoft.AspNetCore.Mvc.Rendering    {

    public static class HtmlHelperViewExtensions
    {

        public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null)
        {
            var controller =  (string)helper.ViewContext.RouteData.Values["controller"];

            return RenderAction(helper, action, controller, parameters);
        }

        public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null)
        {
            var area = (string)helper.ViewContext.RouteData.Values["area"];

            return RenderAction(helper, action, controller, area, parameters);
        }

        public static IHtmlContent RenderAction(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");

            if (area == null)
                throw new ArgumentNullException("area");

            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 currentHttpContext = helper.ViewContext?.HttpContext;
            var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext);
            var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext);
            var actionSelector = GetServiceOrFail<IActionSelectorDecisionTreeProvider>(currentHttpContext);

            // creating new action invocation context
            var routeData = new RouteData();
            var routeParams = new RouteValueDictionary(parameters ?? new { });
            var routeValues = new RouteValueDictionary(new { area = area, controller = controller, action = action });
            var newHttpContext = httpContextFactory.Create(currentHttpContext.Features);

            newHttpContext.Response.Body = new MemoryStream();

            foreach (var router in helper.ViewContext.RouteData.Routers)
                routeData.PushState(router, null, null);

            routeData.PushState(null, routeValues, null);
            routeData.PushState(null, routeParams, null);

            var actionDescriptor = actionSelector.DecisionTree.Select(routeValues).First();
            var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);

            // invoke action and retreive the response body
            var invoker = actionInvokerFactory.CreateInvoker(actionContext);
            string content = null;

            await invoker.InvokeAsync().ContinueWith(task => {
                if (task.IsFaulted)
                {
                    content = task.Exception.Message;
                }
                else if (task.IsCompleted)
                {
                    newHttpContext.Response.Body.Position = 0;
                    using (var reader = new StreamReader(newHttpContext.Response.Body))
                        content = reader.ReadToEnd();
                }
            });

            return new HtmlString(content);
        }

        private static TService GetServiceOrFail<TService>(HttpContext httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException(nameof(httpContext));

            var service = httpContext.RequestServices.GetService(typeof(TService));

            if (service == null)
                throw new InvalidOperationException($"Could not locate service: {nameof(TService)}");

            return (TService)service;
        }
    }
}

Du kan starte fra visningen bruke en av disse metodene:

@Html.RenderAction("action", "controller", "area", new { id = 1})
@Html.RenderAction("action", "controller", new { id = 1})
@Html.RenderAction("action", new { id = 1})

Merk:

Controller navn, og eventuelt område navn, vil settes til de tilsvarende verdier fra de ActionContext hvis ikke gitt.

Svarte 10/10/2016 kl. 02:42
kilden bruker

stemmer
1

Løsning av Væren for Helper Extension er ikke mer gjennomførbar for Net Kjerne 2,0 som IActionSelectorDecisionTreeProvider har blitt fjernet fra den nyere versjonen. Se link nedenfor.

https://github.com/Microsoft/aspnet-api-versioning/issues/154

Svarte 30/09/2017 kl. 11:24
kilden bruker

stemmer
3

For Net Kjerne 2,0

using Microsoft.AspNetCore.Mvc.Infrastructure;

erstatte

// var actionSelector = GetServiceOrFail<IActionSelectorDecisionTreeProvider>(currentHttpContext); 
var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext); 

og

// var actionDescriptor = actionSelector.DecisionTree.Select(routeValues).First(); 
var actionDescriptor = actionSelector.ActionDescriptors.Items.Where(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action).First();
Svarte 21/10/2017 kl. 00:13
kilden bruker

stemmer
5

For asp.net kjernen 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));
                }
            }
        }
    }
}

Den er basert på Væren respons. Jeg rettet det ikke ble kompilering for 2.0 og jeg har lagt til et par tweaks. Det er 2 glorified statiske verdier for gjeldende httpcontext og gjeldende actioncontext. Den ene for httpcontext er satt i IHttpContextFactory.Create, og jeg satt en for actioncontext i koden.

HttpContext er bare en wrapper rundt HttpContext.Features, så hvis du endrer noe i en, endrer det også i den andre ... Jeg nullstiller det jeg vet om i endelig i Try / fangst.

Jeg fjernet IUrlHelperfra Items cache siden denne verdien vil bli gjenbrukt selv om actionContext å bygge urlHelper er annerledes ( IUrlHelperFactory.GetUrlHelper).

Asp.net kjerne 2.0 forutsetter at du ikke vil gjøre dette, det er en god sjanse det er andre bufrede ting, så jeg anbefaler å være forsiktig når du bruker dette, og bare ikke hvis du ikke må.

Svarte 01/11/2017 kl. 21:37
kilden bruker

stemmer
0

Jeg brukte kodene av mennesker på denne siden for å få riktig resultat.

https://stackoverflow.com/a/39951006/6778726

https://stackoverflow.com/a/46859170/6778726

For eksempel, i den gamle klasse, ved utføring av følgende kode, en feil ble vist

@Html.RenderAction("About", "Home")

Følgende kode er blitt fikset:

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Routing;

namespace Microsoft.AspNetCore.Mvc.Rendering
{

    public static class HtmlHelperViewExtensions
    {
        public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null)
        {
            var controller = (string)helper.ViewContext.RouteData.Values["controller"];
            return RenderAction(helper, action, controller, parameters);
        }

        public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null)
        {
            var area = (string)helper.ViewContext.RouteData.Values["area"];
            return RenderAction(helper, action, controller, area, parameters);
        }

        public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(controller));
            if (controller == null)
                throw new ArgumentNullException(nameof(action));

            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 currentHttpContext = helper.ViewContext.HttpContext;
            var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext);
            var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext);
            var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext);

            // creating new action invocation context
            var routeData = new RouteData();
            var routeParams = new RouteValueDictionary(parameters ?? new { });
            var routeValues = new RouteValueDictionary(new { area, controller, action });
            var newHttpContext = httpContextFactory.Create(currentHttpContext.Features);

            newHttpContext.Response.Body = new MemoryStream();

            foreach (var router in helper.ViewContext.RouteData.Routers)
                routeData.PushState(router, null, null);

            routeData.PushState(null, routeValues, null);
            routeData.PushState(null, routeParams, null);

            var actionDescriptor = actionSelector.ActionDescriptors.Items.First(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action);
            var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);

            // invoke action and retreive the response body
            var invoker = actionInvokerFactory.CreateInvoker(actionContext);
            string content = null;

            await invoker.InvokeAsync().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    content = task.Exception.Message;
                }
                else if (task.IsCompleted)
                {
                    newHttpContext.Response.Body.Position = 0;
                    using (var reader = new StreamReader(newHttpContext.Response.Body))
                        content = reader.ReadToEnd();
                }
            });

            return new HtmlString(content);
        }

        private static TService GetServiceOrFail<TService>(HttpContext httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException(nameof(httpContext));

            var service = httpContext.RequestServices.GetService(typeof(TService));

            if (service == null)
                throw new InvalidOperationException($"Could not locate service: {nameof(TService)}");

            return (TService)service;
        }
    }
}

De følgende eksempler ble vellykket testet:

@Html.RenderAction("About")
@Html.RenderAction("About", "Home")
@Html.RenderAction("About", new { data1 = "test1", data2 = "test2" })
@Html.RenderAction("About", "Home", new { data1 = "test1", data2 = "test2" })
Svarte 12/06/2018 kl. 20:51
kilden bruker

stemmer
1

For asp.net core 2 løsning levert av Yepeekai, kan du legge til følgende i din Startup.cs:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

Dette er ikke lenger registrert som standard i 2.0.

Svarte 28/09/2018 kl. 14:57
kilden bruker

stemmer
0

MRT2017 sa: ... De følgende eksempler ble testet: ...

Først takk for deling.

Men denne overbelastning metoden kan være årsak "HTTP ERROR 500":

@Html.RenderAction("About")

Fordi 'controller' kanskje små bokstaver kontrolleren navn, ex. "Hjem", "grid", osv:

helper.ViewContext.RouteData.Values["controller"]

Du må kapitalisere kontrolleren navn, ex. "Grid" -> "Grid", fordi regulatoren klassenavn er små og store bokstaver i Assembly, er virkningen den samme navn.

* Visual Studio 2019 / NET kjerne 2.2.

Svarte 04/10/2019 kl. 04:45
kilden bruker

stemmer
0

@ Html.Action ble erstattet med ViewComponents. Jeg liker ViewComponents for flere grunner.

Men jeg bruker alternativ mønster til @ Html.Action

Først lager jeg Handling på kontrolleren som er tilbake delvis utsikt med et innhold som jeg ønsker å vise i siden ie

    [HttpGet]
    public async Task<IActionResult> GetFoo()
    {
        return PartialView("_Foo", new Foo());
    }

Da jeg sted div på siden der foo visningen skal legges og inkludere Iivet nederst på siden. Dvs kode Bellow vil laste GetFoo utsikt og sett at html til div med id foo-visning.

<div class="page">
    <div id="foo-view" data-url="@Url.Action(action: "GetFoo", controller: "Home")"></div>
</div>

<script>
    $(document).ready(function () {
        (function () {
            var url = $("#foo-view").data("url");
            $("#foo-view").load(url);
        })();
    });
</script>

Du kan også være lurt å vise spinner mens utsikten er beign hentes fra serveren.

Svarte 20/11/2019 kl. 11:06
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more