private static void VerifyNotConflicting(ResponseTypeInfo item, IEnumerable <ResponseTypeInfo> items) { var conflicting = FindConflictingStatusCodes(item, items); if (conflicting.Any()) { throw new InvalidOperationException( ExceptionStrings.ResponseTypeInfoCollection_ConflictingStatusCodeRanges(conflicting) ); } }
private static Type?GetAndVerifyContentType(object?content, Type?contentType) { // If both types are given, ensure that they match. Otherwise serialization will be problematic. var actualContentType = content?.GetType(); if (actualContentType != null && contentType != null && !contentType.IsAssignableFrom(actualContentType)) { throw new ArgumentException( ExceptionStrings.HttpContentSerializer_ContentTypeDoesNotMatchActualType(contentType, actualContentType), nameof(contentType) ); } // The contentType is optional. In that case, try to get the type on our own. return(contentType ?? actualContentType); }
private async Task <object?> DeserializeDefaultAsync( HttpContent?httpContent, Type contentType, CancellationToken cancellationToken) { // We are not expecting NoContent at this point. This means that an empty HttpContent // (i.e. null) should not be legal. if (httpContent is null) { throw new HttpContentSerializationException( ExceptionStrings.HttpContentSerializer_HttpContentIsNullButShouldNotBeNoContent(contentType) ); } try { return(await DeserializeAsyncCore(httpContent, contentType, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(!(ex is HttpContentSerializationException)) { throw new HttpContentSerializationException(null, ex); } }
/// <summary> /// Initializes a new instance of the <see cref="ResponseTypeInfo"/> class /// which specifies that an API returns an object of type <paramref name="responseType"/> /// for the given <paramref name="statusCodes"/>. /// </summary> /// <param name="responseType"> /// The .NET type representation of the result that the API returns for the status /// codes defined by <see cref="StatusCodes"/>. /// </param> /// <param name="statusCodes"> /// A set of status codes for which the <see cref="ResponseType"/> is the result. /// </param> /// <param name="responseDeserializerFactory"> /// A function which returns an <see cref="IHttpContentDeserializer"/> that must /// be used to deserialize the .NET object from an HTTP response. /// </param> /// <exception cref="ArgumentNullException"> /// * <paramref name="responseType"/> /// * <paramref name="statusCodes"/> /// * <paramref name="responseDeserializerFactory"/> /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="statusCodes"/> is empty. /// </exception> public ResponseTypeInfo( Type responseType, IEnumerable <StatusCodeRange> statusCodes, Func <IHttpContentDeserializer> responseDeserializerFactory) { _ = responseType ?? throw new ArgumentNullException(nameof(responseType)); _ = statusCodes ?? throw new ArgumentNullException(nameof(statusCodes)); _ = responseDeserializerFactory ?? throw new ArgumentNullException(nameof(responseDeserializerFactory)); if (!statusCodes.Any()) { throw new ArgumentException( ExceptionStrings.ResponseTypeInfo_MustProvideAtLeastOneStatusCode(), nameof(statusCodes) ); } ResponseType = responseType; ResponseDeserializerFactory = responseDeserializerFactory; StatusCodes = new HashSet <StatusCodeRange>(statusCodes); }
/// <summary> /// Attempts to deserialize the response to the specified type <typeparamref name="T"/> /// and, depending on the success, returns either the deserialized resource or information /// about an exception which occured during deserialization. /// </summary> /// <typeparam name="T"> /// The type of the resource to be deserialized. /// </typeparam> /// <param name="cancellationToken"> /// A cancellation token which can be used to cancel the operation. /// </param> /// <returns> /// The deserialized resource or information about a deserialization exception. /// </returns> private protected async Task <T> DeserializeResourceAsync <T>(CancellationToken cancellationToken = default) { if (GetCurrentResponseTypeInfo() is null) { throw new InvalidOperationException(ExceptionStrings.ApiResponse_NoResponseTypeInfoForResponse()); } var deserializer = GetCurrentResponseTypeInfo().ResponseDeserializerFactory(); if (deserializer is null) { throw new InvalidOperationException(ExceptionStrings.ApiResponse_InvalidResponseDeserializer()); } try { return(await deserializer.DeserializeAsync <T>(HttpResponseMessage.Content, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(!(ex is HttpContentSerializationException)) { // Ideally, the deserializer throws this exception by himself, but we cannot count on that. throw new HttpContentSerializationException(null, ex); } }
/// <inheritdoc/> public async Task <object?> DeserializeAsync( HttpContent?httpContent, Type contentType, CancellationToken cancellationToken = default) { _ = contentType ?? throw new ArgumentNullException(nameof(contentType)); if (contentType != typeof(T)) { throw new NotSupportedException(ExceptionStrings.Serializer_CanOnlyDeserialize(typeof(string))); } if (httpContent is null) { return(DefaultValue); } try { return(await DeserializeCoreAsync(httpContent, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(!(ex is HttpContentSerializationException)) { throw new HttpContentSerializationException(null, ex); } }
private static string GetDefaultMessage() => ExceptionStrings.HttpContentSerializationException_Message();