benfd
benfd

Reputation: 73

ControllerBase extension method for SeeOther with UrlHelper.Action that is returning null

I have a need to use a SeeOther HTTP response code for one of my API routes.

The ControllerBase class has no SeeOther method so I have made an extension method for it, trying to follow the same pattern as the AcceptedAtAction method, passing in a string for action and controller name and an object of route values, but my UrlHelper.Action method keeps returning null when trying to build the action URL for my "Location" header.

I know I must have missed something simple but I just cant spot it, any thoughts?

Here are some (simplified) snippets of code my code

Extension method

public static class ControllerBaseExtensions
{
    public static ActionResult SeeOther(this ControllerBase controller, string actionName, string controllerName, object routeValues)
    {
        var url = controller.Url.Action(
            actionName,
            controllerName,
            new RouteValueDictionary(routeValues),
            controller.Request.Scheme,
            controller.Request.Host.ToUriComponent());
    
        controller.Response.Headers.Add("Location", url);
        return new StatusCodeResult(303);
    }
}

Controller route

[ApiController]
[Route("/{id:guid}/forms")]
public class FormsController : ControllerBase
{
    [Authorize(Policy = "AuthPolicy")]
    [HttpPost]
    public async Task<IActionResult> Post([FromRoute] Guid caseId, [FromBody] PostFormResourceRepresentation body, CancellationToken cancellationToken)
    {
        if (body.Type != FormType.A) return BadRequest("Unsupported form type provided");

        var requestId = Guid.NewGuid();
        
        return this.SeeOther("Pending", "Forms", new { requestId });
    }

    [Authorize(Policy = "AuthPolicy")]
    [HttpGet("pending/{requestId:guid}")]
    public IActionResult Pending([FromRoute] Guid caseId, [FromRoute] Guid requestId, CancellationToken cancellationToken)
    {
        return Ok();
    }
}

Upvotes: 0

Views: 311

Answers (1)

benfd
benfd

Reputation: 73

Okay I worked it out, was something very simple.

I forgot to pass one of the route parameters into my Extension when I was calling it.

[Route("/{id:guid}/forms")]
public class FormsController : ControllerBase
{
    [Authorize(Policy = "AuthPolicy")]
    [HttpPost]
    public async Task<IActionResult> Post([FromRoute] Guid caseId, [FromBody] PostFormResourceRepresentation body, CancellationToken cancellationToken)
    {
        if (body.Type != FormType.A) return BadRequest("Unsupported form type provided");

        var requestId = Guid.NewGuid();
        
        return this.SeeOther("Pending", "Forms", new { requestId, id // this was missing });
    }
}

Upvotes: 1

Related Questions