Submit a form and execute controller actions from ViewComponent in ASP.NET Core

I want to add ListItems from a form in ViewComponent to an ASP.NET 5 main application, Mvc.

Component view (Views \ Shared \ Components \ AddListItem \ Default.cshtml):

@model ShoppingList.Models.ListItem <form asp-action="Create"> <div class="form-horizontal"> <hr /> <div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div> <!-- some fields omitted for brevity --> <div class="form-group"> <label asp-for="Description" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="Description" class="form-control" /> <span asp-validation-for="Description" class="text-danger" /> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> </form> 

ViewComponent controller (ViewComponents \ AddListItem.cs):

 namespace ShoppingList.ViewComponents { public class AddListItem : ViewComponent { private readonly ApplicationDbContext _context; public AddListItem(ApplicationDbContext context) { _context = context; } public IViewComponentResult Invoke(string listId) { return View(); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IViewComponentResult> Create (ListItem listItem) { _context.ListItem.Add(listItem); await _context.SaveChangesAsync(); return View(listItem); } } } 

The component is called in home.cshtml:

 @{ ViewData["Title"] = "Home Page"; } @Component.Invoke("AddListItem", @ViewBag.DefaultListId) 

However, I cannot get this to work. Nothing added.

+7
c # asp.net-core asp.net-core-viewcomponent
source share
2 answers

Rename AddListItem to AddListItemViewComponent . This is the convention used by ASP.NET to find the component — that is, ViewComponents must be completed with the suffix ViewComponent . If you do not want to do this, you can decorate the class with the [ViewComponent] attribute and set the name property for any name you need.

In addition, the Create method will never be called, and ViewComponents will never respond to HttPost , as it is intended only to display the view and not to execute code in response to the postback. The view will either invoke only Invoke , or its asynchronous version of InvokeAsync and nothing more.

This is a bit confusing at first, but the easy way to think of it as a powerful Partial in the sense that you can do more things in the DI-friendly component class, and is also easier to test.

The ASP.NET team has a page that explains ViewComponents here

+3
source share

Thanks for your help, @Dealdiane.

In case anyone is interested, here is the working code:

Views \ Shared \ Components \ AddListItem \ Default.cshtml

 <form asp-controller="ListItems" asp-action="QuickCreate"> <div class="form-horizontal"> <hr /> <div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="No" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="No" class="form-control" /> <span asp-validation-for="No" class="text-danger" /> </div> </div> ... 

Controllers \ ListItemsController.cs

  // POST: ListItems/QuickCreate // Create item without showing view, return to home [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> QuickCreate(ListItem listItem) { _context.ListItem.Add(listItem); await _context.SaveChangesAsync(); return Redirect("/"); } 

The full source code of the project in the work can be found here: GitHub ShoppingList

+2
source share

All Articles