Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return HTTP Status Codes for errors from Asp.Net Core View Component

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.

like image 464
OjM Avatar asked Mar 11 '23 13:03

OjM


2 Answers

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;
}
like image 62
Carsten Cors Avatar answered Apr 08 '23 21:04

Carsten Cors


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);
}
like image 31
Tim Abell Avatar answered Apr 08 '23 21:04

Tim Abell