Skip to content

2. Request creation

Michal Motyčka edited this page Jul 9, 2023 · 8 revisions

Ridge creates a request to the server using a pipeline composed of HttpRequestFactoryMiddleware. We can separate these middlewares into two categories, initial and final. Initial middlewares gather information about the request, and final middleware uses this information to generate an HTTP request.

Initial middlewares

Initial middlewares gather information about the request and set the properties of RequestFactoryContext. Client method parameters are mapped to the request based on information from the original action.

Mapping uses the following rules:

  • Parameters with the attribute [FromRoute] are added to the UrlGenerationParameters dictionary.
  • Parameters with the attribute [FromQuery] are added to the UrlGenerationParameters dictionary.
  • A parameter with the attribute [FromBody] is added as a request body.
  • Parameters with the attribute [FromHeader] are added to request headers.
  • A complex parameter without an attribute is added as a request body.
  • Simple parameters without an attribute are added to the UrlGenerationParameters dictionary.

The UrlGenerationParameters is a dictionary that contains route parameters, query parameters and further information about the request (e.g. area).

Final middleware

Final middleware generates an HTTP request using information from previous middlewares. UrlGenerationParameters are passed to the ASP.NET method linkGenerator.GetPathByRouteValues("", routeParams);. More information about this method can be found here.

Custom middlewares

You can add a custom HttpRequestFactoryMiddleware to alter the request creation process. Custom middlewares are added between initial and final middlewares in the order in which they were registered.

The following middleware adds a header to the request:

public class AddEnglishLanguageHeader : HttpRequestFactoryMiddleware
{
    public override Task<HttpRequestMessage> CreateHttpRequest(
        IRequestFactoryContext requestFactoryContext)
    {
        requestFactoryContext.Headers.Add("Accept-Language", "en-US");
        return base.CreateHttpRequest(requestFactoryContext);
    }
}

Example usage of AddHeaderHttpRequestFactoryMiddleware:

[Test]
public async Task HttpRequestFactoryExample()
{
    using var webApplicationFactory = new WebApplicationFactory<Program>().WithRidge(x =>
    {
            x.UseHttpRequestFactoryMiddleware(new AddEnglishLanguageHeader());
    });
    var ridgeHttpClient = webApplicationFactory.CreateClient();
    var examplesControllerClient = new ExamplesControllerClient(ridgeHttpClient, webApplicationFactory.Services);

    // endpoint which returns Accept-Language header 
    var response = await examplesControllerClient.ReturnLanguage();
    Assert.AreEqual("en-US", response.Result);
}

IRequestFactoryContext

IRequestFactoryContext contains information about the request. This information is used by final middleware to generate an HTTP request. It contains the following properties:

  • Body - body of the request.
  • RequestHasBody - true if request has body. There is a difference between a body with null value and no body.
  • Headers - headers of the request.
  • UrlGenerationParameters – a dictionary that contains route parameters, query parameters and further information about the request (e.g. area).
  • HttpMethod - HTTP method of the request.
  • CallId – a unique id of the request, which is added to the header.
  • CalledControllerMethodInfo - information about the controller method that is the target of this request.
  • ServiceProvider – the service provider that can be used to resolve services.
  • ParameterProvider - can be used to gather information about client and controller parameters.

All of these properties are quite self-explanatory. One exception is ParameterProvider, which is quite complex. ParameterProvider contains the following methods:

  • GetClientParameters - returns collection that contains information about client parameters and their values. Client parameters contain values passed to client method call and meta information about the parameters.
  • GetControllerParameters - returns collection that contains information about controller parameters and their values. Note that ControllerParameters don't contain any values, only various information about the parameters.
  • GetActionAndClientParametersLinked - returns collection that contains information about client and controller parameters linked. Parameters are linked even if they were transformed using the transform attribute.
  • GetAdditionalParameters - returns collection of additionalParameters passed to client. Additional parameters are described here.

Request generation tips

  • It is recommended to use [FromXXX] parameters to help Ridge map parameters correctly.
  • If you aren't sure if the parameters were mapped correctly, you can always use logger and check test output.
  • If you aren't satisfied with how Ridge maps parameters you can always add HttpRequestFactoryMiddleware and change the mapping process.
  • Ridge can handle attribute routing and standard routing. It doesn't matter which one you use.
  • Ridge can handle areas.

Special parameters

When Ridge generates a caller, it automatically removes parameters with the attribute [FromServices] and parameters with the type CancellationToken.