-1

I am trying to display Asset information on different pages using partial View but I am having the error below

"InvalidOperationException: A view component named 'AssetInfo' could not be found. A view component must be a public non-abstract class, not contain any generic parameters, and either be decorated with 'ViewComponentAttribute' or have a class name ending with the 'ViewComponent' suffix. A view component must not be decorated with 'NonViewComponentAttribute'."

Controller

  public ActionResult AssetInfo(int? Id)
  {
        var model = _context.Asset.Where(x => x.Id == Id).ToList();
        return PartialView("_AssetInfo", model);
  }

Partial View

@model IEnumerable<InformationAssetRegister.Models.Asset>
<table border="1" cellpadding="4" cellspacing="4">
<tr>
    <th style="background-color: Yellow;color: blue">
        Asset Name
    </th>
    <th style="background-color: Yellow;color: blue">
       Asset type
    </th>
</tr>

@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.AssetName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.AssetType)
        </td>
    </tr>

}

I tried to use Html.RenderAction but Renderaction cannot be use in .Net Core

  @{
    Html.RenderAction("AssetInfo", "Assets", new {Id= ViewBag.AssetId });
   }

I also tried the code below

   @await Component.InvokeAsync("AssetInfo", new { Id = ViewBag.AssetId })

Can anyone help to solve this issue I am new to .Net Core

SAM
  • 21
  • 5

1 Answers1

1

As far as I know, the Html.RenderAction has been removed in asp.net core. ASP.NET Core uses a new feature called ViewComponents to achieve the same thing. Article. For more details about how to replace Renderaction with ViewComponents, you could refer to this answer.

If you still want to use Html.RenderAction in asp.net core.

I suggest you could implement it by yourself, you could create a class and add below codes into your project.

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 retrieve 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;
        }
    }
}

View:

@Html.RenderAction("AssetInfo", "Home", new { Id = 2 });

Home Controller:

    public ActionResult AssetInfo(int? Id)
    {
        //var model = _context.Asset.Where(x => x.Id == Id).ToList();
        var model = new List<Asset>() {
         new Asset(){ AssetName="te", AssetType="te2" }
        };

        return PartialView("_AssetInfo", model);
    }

Result:

enter image description here

VahidNaderi
  • 2,448
  • 1
  • 23
  • 35
Brando Zhang
  • 22,586
  • 6
  • 37
  • 65