I am trying to return a HTTP 500 or BadRequest() result from my View Component in Asp.Net Core however this return type does not appear to be available for View Components. Should status code return types be available for View Components or have i got my design wrong?
I am calling my controller action via ajax as per below...
<a asp-controller="Client" asp-action="LoadVisit" asp-route-id="@item.VisitID" data-ajax="true" data-ajax-method="GET" data-ajax-update="#ClientVisit" data-ajax-mode="replace" data-ajax-failure="AjaxOnFailure(xhr, status, error)" role="button"><i class="fa fa-folder-open-o"></i></a>
My controller action is calling/returning my View Component as per below...
public IActionResult LoadVisit(int? id)
{
if (id == null || id == 0)
{
return NotFound();
}
return ViewComponent("ClientVisit", new { visitID = id.GetValueOrDefault() });
}
My ClientVisit View Component has the following...
public async Task<IViewComponentResult> InvokeAsync(int? clientID, int? visitID)
{
try
{
var model = new VisitViewModel();
model = await visitAPI.GetVisit(clientID, visitID);
return View(model);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
When my database call model = await visitAPI.GetVisit(clientID, visitID)
fails I want to return return StatusCode(500, ex.ToString())
but it's not available so my ajax call thinks my request was successful which is wrong.
As long as you have the HttpResponse in the access it should work. Alternatively, due to the return of the ViewComponent prerequisite check then set the status.
try
{
var model = new VisitViewModel();
model = await visitAPI.GetVisit(clientID, visitID);
return View(model);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return null;
}
The containing controller should own the logic deciding whether to return status codes and then only if there isn't a problem should it pass the required data to the view component. This should eliminate any need for the view component to interact with the pipeline.
View components don't use model binding, and only depend on the data provided when calling into it.
So move the call to the api out of the view component and into the controller and then pass the resultant data into the view component if the call to the api was okay.
ref https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.1
So something like this for your example:
public IActionResult LoadVisit(int? id)
{
if (id == null || id == 0)
{
return NotFound();
}
var model = new VisitViewModel();
try
{
model = await visitAPI.GetVisit(clientID, visitID);
}
catch (Exception ex)
{
return Content(ex.Message);
}
return ViewComponent("ClientVisit", model });
}
and
public async Task<IViewComponentResult> InvokeAsync(VisitViewModel model)
{
return View(model);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With