Skip to content

Commit

Permalink
Added ViewComponentRenderer
Browse files Browse the repository at this point in the history
  • Loading branch information
apfohl committed Dec 19, 2023
1 parent 915f2f0 commit 211a6e7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 12 deletions.
50 changes: 50 additions & 0 deletions HotwiredBooks/Components/ViewComponentRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

namespace HotwiredBooks.Components;

public sealed class ViewComponentRenderer(ActionContext context, ITempDataProvider tempDataProvider)
{
public async Task<IActionResult> RenderAsync(string viewComponentName, object viewModel)
{
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = viewModel
};

await using var writer = new StringWriter();

var viewContext = new ViewContext(
context,
new NullView(),
viewData,
new TempDataDictionary(context.HttpContext, tempDataProvider),
writer,
new HtmlHelperOptions()
);

var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService<IViewComponentHelper>();
(viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);

var viewComponent = await viewComponentHelper.InvokeAsync(viewComponentName, viewModel);
viewComponent.WriteTo(writer, HtmlEncoder.Default);

await writer.FlushAsync();
return new ContentResult
{
Content = writer.ToString(),
ContentType = "text/html"
};
}

private sealed class NullView : IView
{
public string Path => string.Empty;

public Task RenderAsync(ViewContext context) => Task.CompletedTask;
}
}
9 changes: 6 additions & 3 deletions HotwiredBooks/Controllers/BooksController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
using HotwiredBooks.Models;
using HotwiredBooks.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using MonadicBits;

namespace HotwiredBooks.Controllers;

public sealed class BooksController(IBooksRepository booksRepository) : Controller
public sealed class BooksController(IBooksRepository booksRepository, ITempDataProvider tempDataProvider)
: Controller
{
private record FormData(string Title, string Author);

private ViewComponentRenderer ViewComponentRenderer => new(ControllerContext, tempDataProvider);

[HttpGet]
public async Task<IActionResult> Index() => View(new BooksIndexViewModel(
(await booksRepository.All()).OrderByDescending(book => book.CreatedAt)));
Expand Down Expand Up @@ -41,7 +45,6 @@ public Task<IActionResult> Edit(Guid id) =>

[HttpPatch, HttpPut]
[ValidateAntiForgeryToken]
[TurboStreamResponse]
public Task<IActionResult> Update(Guid id, IFormCollection collection) =>
(
from formData in ParseFormData(collection)
Expand All @@ -55,7 +58,7 @@ book with
)
select updatedBook
)
.MapAsync<Book, IActionResult>(book => View(new BooksEditViewModel(book)))
.MapAsync(book => ViewComponentRenderer.RenderAsync("Book", new BooksEditViewModel(book)))
.OrElse(StatusCode(500, "An unexpected error occurred on the server."));

[HttpPost]
Expand Down
9 changes: 0 additions & 9 deletions HotwiredBooks/Views/Books/Update.cshtml

This file was deleted.

0 comments on commit 211a6e7

Please sign in to comment.