ELBartoTn
ELBartoTn

Reputation: 137

Render AngularJs index.html in an ASP.NET Core MVC view

I'm currently working on migrating a web app with the following tech:

  1. ASP.NET MVC
  2. AngularJs
  3. Gulp
  4. Azure cloud service

to :

  1. ASP.NET Core MVC
  2. AngularJs
  3. Webpack
  4. Azure App service

The migrated app correctly bundle and serve AngularJs index.html to wwwroot. Currently, I need to add two views to the ASP.NET Core MVC app and inject the index.html to these views.

I can't figure out how to :

to finally have an URL pattern:

localhost/View1/#/angularJs-state 

or

localhost/View2/#/angularJs-state

wwwroot : enter image description here

Home :

public class BaseController : Controller
{
    public IActionResult Index()
    {
        return View("portal");
    }
}

First view :

 public class PortalController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

Startup.cs

 app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(name: "portal",
            pattern: "Portal",
            defaults: new { controller = "Portal", action = "Index" });
            endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Base}/{action=Index}/{id?}");
        });

Upvotes: 0

Views: 372

Answers (1)

Brando Zhang
Brando Zhang

Reputation: 27987

According to your description, if you want to render the html page in the view, I suggest you could write a custom render method in mvc and return the index file as the file result to the mvc view.

More details, you could refer to below codes:

1.Create render extension method:

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

2.Add controller method as below:

    public IActionResult IndexFile()
    {
        return File("index.html", "text/html");
    }

3.Add below codes into view:

@Html.RenderAction("IndexFile", "Yourcontrollername")

Upvotes: 0

Related Questions