Render ViewComponent inside html string
Asked Answered
E

2

1

Lets say I have a ViewComponent named MyComponent.

As of ASP.NET Core 1.1 I can render this ViewComponent by writing this inside a razor view .cshtml page:

 <vc:my-component></vc:my-component>

I want to do something like this:

@{string myHtml = "<vc:my-component></vc:my-component>";}

@(new HtmlString(myHtml))

I installed and tried RazorEngine by doing this, but this did not work:

string template = "<vc:my-component></vc:my-component>";
var result = Engine.Razor.RunCompile(template, "messageTemplateKey", null, new { Name = "some model data" });
ViewBag.result = result;

then in the .chtml file:

 @(new HtmlString(ViewBag.result))

The backstory to this is that I've created a ViewComponent with some logic on how to handle image files, now I want to search and replace all img tags in some html with my ViewComponent. Before I do that I need to make sure this even works.

Epigram answered 5/4, 2017 at 8:25 Comment(1)
Since there are examples of rendering a view to a string on stack overflow, wouldn't it work to create a view and put code in it to use your view component and then just render the view to a string? I'm pretty sure that should work for you.Winters
E
1

This is what I ended up doing:

I moved the view code from the Default.cshtml for MyComponent to a partial view (_myPartial). Then I used a IViewRenderService inspired by this post.

Then I could render and get my html string after passing in the viewmodel by doing this:

 var result = ViewRenderService.RenderToString("_myPartial", viewModel);
Epigram answered 12/4, 2017 at 11:43 Comment(1)
@TobiOwolawi this example is a view component. I just had to move the html/razor code from the view components Default.cshtml to a partial view. In that way I could both use the view component and retrieve the rendered html by using the partial view underneathEpigram
E
2

Check the code at this url on github:

https://gist.github.com/pauldotknopf/b424e9b8b03d31d67f3cce59f09ab17f


Code

public class HomeController : Controller {

  public async Task<string> RenderViewComponent(string viewComponent, object args) {

    var sp = HttpContext.RequestServices;

    var helper = new DefaultViewComponentHelper(
        sp.GetRequiredService<IViewComponentDescriptorCollectionProvider>(),
        HtmlEncoder.Default,
        sp.GetRequiredService<IViewComponentSelector>(),
        sp.GetRequiredService<IViewComponentInvokerFactory>(),
        sp.GetRequiredService<IViewBufferScope>());

    using (var writer = new StringWriter()) {
        var context = new ViewContext(ControllerContext, NullView.Instance, ViewData, TempData, writer, new HtmlHelperOptions());
        helper.Contextualize(context);
        var result = await helper.InvokeAsync(viewComponent, args);
        result.WriteTo(writer, HtmlEncoder.Default);
        await writer.FlushAsync();
        return writer.ToString();
    }
  }}

Eliott answered 30/1, 2019 at 20:29 Comment(1)
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.Slim
E
1

This is what I ended up doing:

I moved the view code from the Default.cshtml for MyComponent to a partial view (_myPartial). Then I used a IViewRenderService inspired by this post.

Then I could render and get my html string after passing in the viewmodel by doing this:

 var result = ViewRenderService.RenderToString("_myPartial", viewModel);
Epigram answered 12/4, 2017 at 11:43 Comment(1)
@TobiOwolawi this example is a view component. I just had to move the html/razor code from the view components Default.cshtml to a partial view. In that way I could both use the view component and retrieve the rendered html by using the partial view underneathEpigram

© 2022 - 2024 — McMap. All rights reserved.