In this post, I show how an ASP.NET Core MVC view can send a Javascript parameter value to an ASP.NET Core view component. Invoking a view component in the view using ‘@await Component.InvokeAsync’ will not work, as this is rendered before the Javascript value has been created.
Code: https://github.com/damienbod/AspNetCoreBootstrap4Validation
History
2019-01-24 Added an Anti-Forgery token to Javascript view component ajax request
Creating the view component
The view component is setup in the standard way as described in the Microsoft docs:
The view component called MyComponent was created which uses the MyComponentModel model. This model is used to pass the parameters to the component and also to display the view. The ScreenWidth property is read from a Javascript value, and set in the model.
using AspNetCoreBootstrap4Validation.ViewModels; using Microsoft.AspNetCore.Mvc; namespace AspNetCoreBootstrap4Validation.Views { public class MyComponent : ViewComponent { public MyComponent() {} public IViewComponentResult Invoke(MyComponentModel model) { model.ScreenWidth = "Read on the server:" + model.ScreenWidth; return View(model); } } }
The Default.cshtml view for the component displays the values as required.
@using AspNetCoreBootstrap4Validation.ViewModels @model MyComponentModel @{ ViewData["Title"] = "View Component"; } <h5>Result from Component:server</h5> <text><em>ScreenWidth: </em>@Model.ScreenWidth</text> <br /> <text><em>Name:</em> @Model.StandardValidation.Name</text><br /> <text><em>IsCool:</em> @Model.StandardValidation.IsCool</text><br /> <text><em>Age: </em>@Model.StandardValidation.Age</text><br />
An action method in an ASP.NET Core MVC controller is used to call the view component.
public class AjaxWithComponentController : Controller { [HttpPost] [ValidateAntiForgeryToken] public IActionResult LoadComponent(MyComponentModel model) { return ViewComponent("MyComponent", model); }
Javascript using jQuery and Ajax is used to request the action method in the MVC controller, which calls the view component. The screenWidth uses the document.documentElement.clientWidth value to get the screen width and the form is serialized and sent as a Json object in the model used to request the view component.
The Anti-Forgery token needs to be added to the header for each request. See the Microsoft Docs for details.
<script language="javascript"> function loadComponentView() { var paramsFromForm = {}; $.each($("#partialformAjaxWithComponent").serializeArray(), function (index, value) { paramsFromForm[value.name] = paramsFromForm[value.name] ? paramsFromForm[value.name] || value.value : value.value; }); var componentData = {}; componentData.standardValidation = paramsFromForm; componentData.screenWidth = document.documentElement.clientWidth; console.log(componentData); $.ajax({ url: window.location.origin + "/AjaxWithComponent/LoadComponent", type: "post", dataType: "json", beforeSend: function (x) { if (x && x.overrideMimeType) { x.overrideMimeType("application/json;charset=UTF-8"); }; x.setRequestHeader('RequestVerificationToken', document.getElementById('RequestVerificationToken').value); }, data: componentData, complete: function (result) { console.log(result.responseText); $("#partialComponentResult").html(result.responseText); } }); }; </script>
The result of the ajax request is displayed in the div with the id partialComponentResult.
@model AspNetCoreBootstrap4Validation.ViewModels.StandardValidationModel @{ ViewData["Title"] = "Ajax with Component Page"; } @inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf @functions{ public string GetAntiXsrfRequestToken() { return Xsrf.GetAndStoreTokens(Context).RequestToken; } } <input type="hidden" id="RequestVerificationToken" name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()"> <h4>Ajax with Component View</h4> <div id="partialComponentResult"> <h5>change a value to do a component load</h5> <text><em>ScreenWidth:</em> ...</text> <br /> <text><em>Name:</em> ...</text><br /> <text><em>IsCool:</em> ...</text><br /> <text><em>Age:</em> ...</text><br /> </div> <hr /> <form id="partialformAjaxWithComponent" onchange="loadComponentView()" method="post" asp-action="Index" asp-controller="AjaxWithComponent"> <div asp-validation-summary="All" class="text-danger"></div> <div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" asp-for="Name" id="name" aria-describedby="nameHelp" placeholder="Enter name"> <small id="nameHelp" class="form-text text-muted">We'll never share your name ...</small> <span asp-validation-for="Name" class="text-danger"></span> </div> <div class="form-group"> <label for="age">Age</label> <input type="number" class="form-control" id="age" asp-for="Age" placeholder="0"> <span asp-validation-for="Age" class="text-danger"></span> </div> <div class="form-check ten_px_bottom"> <input type="checkbox" class="form-check-input big_checkbox" asp-for="IsCool" id="IsCool"> <label class="form-check-label ten_px_left" for="IsCool">IsCool</label> <span asp-validation-for="IsCool" class="text-danger"></span> </div> <button type="submit" class="btn btn-primary">Submit</button> </form>
Links:
https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.2
https://andrewlock.net/passing-variables-to-a-view-component/
https://mariusschulz.com/blog/view-components-in-asp-net-mvc-6