5.41Custom HTTP Declarative Extractor
In the 5.1 Declarative Requests section, we learned that every attribute or parameter type corresponds to an HTTP declarative extractor. The following are the system-provided attribute extractors and their corresponding implementations:
BaseAddressAttributeattribute extractor:BaseAddressDeclarativeExtractorValidationAttributeattribute extractor:ValidationDeclarativeExtractorAutoSetHostHeaderAttributeattribute extractor:AutoSetHostHeaderDeclarativeExtractorStandardRequestHeadersAttributeattribute extractor:StandardRequestHeadersDeclarativeExtractorHttpClientNameAttributeattribute extractor:HttpClientNameDeclarativeExtractorTraceIdentifierAttributeattribute extractor:TraceIdentifierDeclarativeExtractorProfilerAttributeattribute extractor:ProfilerDeclarativeExtractorSimulateBrowserAttributeattribute extractor:SimulateBrowserDeclarativeExtractorAcceptLanguageAttributeattribute extractor:AcceptLanguageDeclarativeExtractorDisableCacheAttributeattribute extractor:DisableDeclarativeExtractorEnsureSuccessStatusCodeAttributeattribute extractor:EnsureSuccessStatusCodeDeclarativeExtractorRetryAttributeattribute extractor:RetryDeclarativeExtractorTimeoutAttributeattribute extractor:TimeoutDeclarativeExtractorPathSegmentAttributeattribute extractor:PathSegmentDeclarativeExtractorQueryParamAttributeattribute extractor:QueryParamDeclarativeExtractorQuotaKeyAttributeattribute extractor:QuotaKeyDeclarativeExtractorPathAttributeattribute extractor:PathDeclarativeExtractorCookieAttributeattribute extractor:CookieDeclarativeExtractorRefererAttributeattribute extractor:RefererDeclarativeExtractorHeaderAttributeattribute extractor:HeaderDeclarativeExtractorPropertyAttributeattribute extractor:PropertyDeclarativeExtractorHttpVersionAttributeattribute extractor:HttpVersionDeclarativeExtractorSuppressExceptionsAttributeattribute extractor:SuppressExceptionsDeclarativeExtractorRemoveTrailingSlashAttributeattribute extractor:RemoveTrailingSlashDeclarativeExtractorRequestEventHandlerAttributeattribute extractor:RequestEventHandlerDeclarativeExtractorJsonResponseWrapperAttributeattribute extractor:JsonResponseWrapperDeclarativeExtractorJsonResponseStringUnwrapAttributeattribute extractor:JsonResponseStringUnwrapDeclarativeExtractorSuppressTokenManagementAttributeattribute extractor:SuppressTokenManagementDeclarativeExtractorUseETagAttributeattribute extractor:UseETagDeclarativeExtractorBodyAttributeattribute extractor:BodyDeclarativeExtractorMultipartAttributeandMultipartFormAttributeattribute extractors:MultipartDeclarativeExtractorAction<HttpRequestMessage>parameter extractor:HttpRequestMessageDeclarativeExtractorAction<HttpMultipartFormDataBuilder>parameter extractor:HttpMultipartFormDataBuilderDeclarativeExtractorAction<HttpRequestBuilder>parameter extractor:HttpRequestBuilderDeclarativeExtractor
By customizing an HTTP declarative extractor, you can provide additional functionality for HTTP declarative interfaces. The following is an example of a custom AcceptAttribute attribute and its extractor:
1. Defining the AcceptAttribute attribute
Set the AcceptAttribute attribute's scope to methods or interfaces.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)]public sealed class AcceptAttribute : Attribute{ public AcceptAttribute(string accept) { ArgumentException.ThrowIfNullOrWhiteSpace(accept); Accept = accept; } public string Accept { get; set; }}2. Implementing the AcceptDeclarativeExtractor extractor
Parse the AcceptAttribute attribute and set it on the HttpRequestBuilder instance.
public sealed class AcceptDeclarativeExtractor : IHttpDeclarativeExtractor{ // Implement the Extract method public void Extract(HttpRequestBuilder httpRequestBuilder, HttpDeclarativeParsingContext context) { // Get the AcceptAttribute attribute defined on the method or interface if (!context.IsMethodDefined<AcceptAttribute>(out var acceptAttribute, true)) { return; } // Set the Accept header httpRequestBuilder.WithHeader("Accept", acceptAttribute.Accept, replace: true); }}The context parameter of the extractor's Extract method is of type HttpDeclarativeParsingContext, which contains the following properties and methods:
-
Properties:
Method: The invoked method (of typeMethodInfo).Args: The array of argument values of the invoked method (of typeobject[]).MethodMetadata: The metadata of the invoked method (of typeHttpDeclarativeMethodMetadata).Parameters: The dictionary of parameter keys and values of the invoked method (of typeIReadOnlyDictionary<ParameterInfo, object?>).UnFrozenParameters: The dictionary of non-frozen typed parameter keys and values of the invoked method (of typeIReadOnlyDictionary<ParameterInfo, object?>).
-
Methods:
IsFrozenParameter(parameter): Determines whether a parameter is a frozen parameter type.IsMethodDefined<TAttribute>(out var attribute, inherit): Checks whether the invoked method defines the specified attribute.GetMethodDefinedCustomAttributes(inherit, methodScanFirst): Gets all instances of the specified attribute defined on the invoked method.
3. Registering the custom extractor in configuration
In the Startup.cs or Program.cs file, configure and register the HttpRemote service to enable the custom HTTP declarative extractor functionality.
services.AddHttpRemote(builder =>{ builder.AddHttpDeclarativeExtractors(() => [ new AcceptDeclarativeExtractor() ]);});4. Using the custom attribute in an HTTP declarative interface
[Accept("text/html")]public interface IHttpService : IHttpDeclarative{ // Apply on the method [Accept("text/xml")] [Get("https://furion.net/")] Task<string> GetStringAsync();}Through the steps above, you have successfully created a custom HTTP declarative extractor. This not only enhances the functionality of HTTP declarative interfaces but also makes the code more concise and easier to maintain. You can continue to extend and customize other HTTP declarative extractors according to your needs.
For more custom HTTP declarative extractors, refer to the framework's built-in HTTP declarative extractor code implementations.