Code Monkey home page Code Monkey logo

restfulsense's Introduction

RESTFulSense

.NET Nuget Nuget The Standard - COMPLIANT The Standard The Standard Community

RESTFulSense

I designed & developed this library as a wrapper around the existing .NET Core HttpClient implementation to provide the following values:

  1. Meaningful Exceptions for APIs response status codes.

  2. Simplified API communications.

  3. Test-friendly implementation.

You can get RESTFulSense Nuget package by typing:

Install-Package RESTFulSense

Standard-Compliance

This library was built according to The Standard. The library follows engineering principles, patterns and tooling as recommended by The Standard.

This library is also a community effort which involved many nights of pair-programming, test-driven development and in-depth exploration research and design discussions.

Standard-Promise

The most important fulfillment aspect in a Standard complaint system is aimed towards contributing to people, its evolution, and principles. An organization that systematically honors an environment of learning, training, and sharing knowledge is an organization that learns from the past, makes calculated risks for the future, and brings everyone within it up to speed on the current state of things as honestly, rapidly, and efficiently as possible.

We believe that everyone has the right to privacy, and will never do anything that could violate that right. We are committed to writing ethical and responsible software, and will always strive to use our skills, coding, and systems for the good. We believe that these beliefs will help to ensure that our software(s) are safe and secure and that it will never be used to harm or collect personal data for malicious purposes.

The Standard Community as a promise to you is in upholding these values.

Details of what this library has to offer:

1. Meaningful Exceptions

RESTFulSense provide the following exceptions for erroring HTTP Status Codes as follows:
Status Code Exception
BadRequest 400 HttpResponseBadRequestException
Unauthorized 401 HttpResponseUnauthorizedException
PaymentRequired 402 HttpResponsePaymentRequiredException
Forbidden 403 HttpResponseForbiddenException
NotFound 404 HttpResponseNotFoundException
NotFound 404 HttpResponseUrlNotFoundException
MethodNotAllowed 405 HttpResponseMethodNotAllowedException
NotAcceptable 406 HttpResponseNotAcceptableException
ProxyAuthenticationRequired 407 HttpResponseProxyAuthenticationRequiredException
RequestTimeout 408 HttpResponseRequestTimeoutException
Conflict 409 HttpResponseConflictException
Gone 410 HttpResponseGoneException
LengthRequired 411 HttpResponseLengthRequiredException
PreconditionFailed 412 HttpResponsePreconditionFailedException
RequestEntityTooLarge 413 HttpResponseRequestEntityTooLargeException
RequestUriTooLong 414 HttpResponseRequestUriTooLongException
UnsupportedMediaType 415 HttpResponseUnsupportedMediaTypeException
RequestedRangeNotSatisfiable 416 HttpResponseRequestedRangeNotSatisfiableException
ExpectationFailed 417 HttpResponseExpectationFailedException
MisdirectedRequest 421 HttpResponseMisdirectedRequestException
UnprocessableEntity 422 HttpResponseUnprocessableEntityException
Locked 423 HttpResponseLockedException
FailedDependency 424 HttpResponseFailedDependencyException
UpgradeRequired 426 HttpResponseUpgradeRequiredException
PreconditionRequired 428 HttpResponsePreconditionRequiredException
TooManyRequests 429 HttpResponseTooManyRequestsException
RequestHeaderFieldsTooLarge 431 HttpResponseRequestHeaderFieldsTooLargeException
UnavailableForLegalReasons 451 HttpResponseUnavailableForLegalReasonsException
InternalServerError 500 HttpResponseInternalServerErrorException
NotImplemented 501 HttpResponseNotImplementedException
BadGateway 502 HttpResponseBadGatewayException
ServiceUnavailable 503 HttpResponseServiceUnavailableException
GatewayTimeout 504 HttpResponseGatewayTimeoutException
HttpVersionNotSupported 505 HttpResponseHttpVersionNotSupportedException
VariantAlsoNegotiates 506 HttpResponseVariantAlsoNegotiatesException
InsufficientStorage 507 HttpResponseInsufficientStorageException
LoopDetected 508 HttpResponseLoopDetectedException
NotExtended 510 HttpResponseNotExtendedException
NetworkAuthenticationRequired 511 HttpResponseNetworkAuthenticationRequiredException

2. Simplified API Communications

API controllers in ASP.NET Core today don't offer the full range of HTTP Codes that can be used to communicate certain events and errors to end users, in this library we managed to implement all the missing methods to communicate the full range of error codes as follows:

2.1 On Controller Level

Controller Method Code
PaymentRequired(object value) 402
MethodNotAllowed(object value) 405
NotAcceptable(object value) 406
ProxyAuthenticationRequired(object value) 407
RequestTimeout(object value) 408
Gone(object value) 410
LengthRequired(object value) 411
PreconditionFailed(object value) 412
RequestEntityTooLarge(object value) 413
RequestUriTooLong(object value) 414
UnsupportedMediaType(object value) 415
RequestedRangeNotSatisfiable(object value) 416
ExpectationFailed(object value) 417
MisdirectedRequest(object value) 421
UnprocessableEntity(object value) 422
Locked(object value) 423
FailedDependency(object value) 424
UpgradeRequired(object value) 426
PreconditionRequired(object value) 428
TooManyRequests(object value) 429
RequestHeaderFieldsTooLarge(object value) 431
UnavailableForLegalReasons(object value) 451
InternalServerError(object value) 500
NotImplemented(object value) 501
BadGateway(object value) 502
ServiceUnavailable(object value) 503
GatewayTimeout(object value) 504
HttpVersionNotSupported(object value) 505
VariantAlsoNegotiates(object value) 506
InsufficientStorage(object value) 507
LoopDetected(object value) 508
NotExtended(object value) 510
NetworkAuthenticationRequired(object value) 511

This can be achieved by simply replacing the inheritance ControllerBase in your ASP.NET Core Controller class with RESTFulController as follows:

    [ApiController]
    [Route("api/[controller]")]
    public class ContactsController : RESTFulController
    {
        ...
    }

Once that's done, you will have full access to use any of the methods above to communicate more meaningful errors to your API consumers and clients.

2.2 On Consumer Level

Passing or retrieving objects from an API should be as simple as one method call, for RESTFulSense, you don't have to worry about how to serialize your input or deserialize the API output, here's how simple it works:

2.2.1 Initialization

The initialization of the RESTFulSense Client can be done in two different ways:

2.2.1.1 HttpClientFactory Approach

In your ASP.NET Core application, you can initialize the IRESTFulApiFactoryClient in your startup.cs as follows:

services.AddHttpClient<IRESTFulApiFactoryClient, RESTFulApiFactoryClient>(client => client.BaseAddress = new Uri(YOUR_API_URL));
2.2.1.2 Basic Initialization

You can also use the RESTFulClient simple initialize in a console app for instance as follows:

var apiClient = new RESTFulApiClient();
2.2.1 Deserialization
List<Student> students = 
    await restfulApiClient.GetContentAsync<List<Student>>(relativeUrl: "api/students");
2.2.2 Serialization
Student student = 
    await restfulApiClient.PostContentAsync<Student>(relativeUrl: "api/students", content: inputStudent); 

In addition to the wrappers around API calls and serialization/deserialization, this library also provides a simplified way to execute communications without any workarounds.

For instance, to execute a PUT API call without a body, to update a status for instance, you don't have to fake a PUT body to execute a successful call, you can just do the follows:

Account activatedAccount = 
    await restfulApiClient.PutContentAsync(relativeUrl: $"api/accounts/{accountId}/activate");

3. MultipartFormDataContent support

RESTFulSense allows you to easily convert a C# class with attributes into a MultipartFormDataContent and send it as a POST request using the PostFormAsync method.

The library includes the following attributes:

Attribute Description
RESTFulByteArrayContentAttribute Specifies a byte array content type
RESTFulStreamContentAttribute Specifies a stream content type
RESTFulStringContentAttribute Specifies a string content type
RESTFulFileNameAttribute Adds a file name to the content

These attributes allow you to specify the content types and names of the form data. The RESTFulFileNameAttribute also allows you to add a file name to the content. Simply apply the attributes to your class properties and the library will handle the rest.

Here's an example usage:

public class FormUpload
{
    [RESTFulStreamContent(name: "file")]
    public Stream Stream { get; set; }

    [RESTFulStringContent(name: "purpose")]
    public string Purpose { get; set; }

    [RESTFulFileName(name: "file")]
    public string FileName { get; set; }
}

// ...

var formUpload = new FormUpload
{
    Stream = GetStream(),
    Purpose = "fine-tune",
    FileName = "SomeFile.jsonl"
};

var result = await PostFormAsync<FormUpload, ResultType>("https://example.com/upload", formUpload);

Note the linking of the FileName to the StreamContent via the name parameter in the attributes.

4. Custom serialization/deserialization support

RESTFulSense uses by default NewtonSoft serialization/deserialization support. However, in some scenarios this could present some drawbacks. Imagine:

  1. Your models don´t have NewtonSoft annotations (because your main project doesn´t uses NewtonSoft).
  2. You have some types which they need custom converters to specify how to deal with those types. For example, TimeOnly type. This type if you try serializate it with NewtonSoft or System.Text then raises an exception because it doesn´t know how to deal with it.
  3. You need to use a custom JsonSerializerSettings or JsonSerializerOptions.

Here we have an example for a POST using System.Text.Json.JsonSerializer:

private readonly var jsonSerializerOptions =
    new JsonSerializerOptions
    {
    // ...
    };

private async ValueTask<string> Serialize<TContent>(TContent requestToSerialize)
{
    using var memoryStream = new MemoryStream();
    await JsonSerializer.SerializeAsync(memoryStream, requestToSerialize, jsonSerializerOptions);
    using var streamReader = new StreamReader(memoryStream, Encoding.UTF8);
    memoryStream.Position = 0;
    return streamReader.ReadToEnd();
}

private async ValueTask<TResult> Deserialize<TResult>(string responseToDeserialize)
{
    byte[] responseBytes = Encoding.UTF8.GetBytes(responseToDeserialize);
    using var memoryStream = new MemoryStream(responseBytes);
    var responseObject =
        await JsonSerializer.DeserializeAsync<TResult>(memoryStream, jsonSerializerOptions);

    return responseObject;
}

var result =
    await restfulApiClient.PostContentAsync<Student>(
        relativeUrl: "api/students",
        content: inputStudent,
        cancellationToken,
        mediaType: "text/json",
        ignoreDefaultValues: false,
        serializationFunction: Serialize<TContent>,
        deserializationFuntion: Deserialize<TResult>);

5. Testing-Friendly Implementation

RESTFulSense provides an interface to the API client class, to make it easier to mock and leverage dependency injection for the testability of the client consumers, here's an example:

var restfulApiClientMock = new Mock<IRestfulApiClient>();

restfulApiClient.Setup(client =>
    client.GetContentAsync<Student>(relativeUrl: $"api/students/{studentId}")
        .ReturnsAsync(student);

If you have any suggestions, comments or questions, please feel free to contact me on:

Twitter

LinkedIn

E-Mail

Important Notice

This library is a community effort.

Huge thanks to Mr. Brian Parker @BrianLParker for his RESTfulSense Web Assembly effort.

restfulsense's People

Contributors

aliceluo2048 avatar brianlparker avatar catalin-andronie avatar cjdutoit avatar dependabot[bot] avatar elbekdeveloper avatar glhays avatar hassanhabib avatar imjane5 avatar lboullosa avatar pwongchaiya avatar shrihumrudha avatar terrypalo avatar tobidub avatar vishwanadhagoli avatar weitzhandler avatar yusc3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

restfulsense's Issues

FEATURE: Add support for injecting a serialization/deserialization Func

As current RESTFulSense version uses NewtonSoft, there are some scenarios in our applications which

  • doesn´t uses NewtonSoft, so no model annotations based on NewtonSoft,
  • there is no way to specify custom JsonSerialization settings (NewtonSoft or System.Text).
  • there is no way to use any other serialization library.

This feature allows us to take care about the serialization/deserialization process from outside the library.

This solution is a workaround to deal with different serializations libraries allowing the power and true value of RestFulSense to be used regardless of the serializer you want to use.

A better approach would be to implement SPAL inside RESTFulSense and add as many serialization implementations we need as new packages.

Use InnerHandler

Hi,

I didn't experiment with it, but I thought instead of overriding the entire HttpClient, we might be able to create a DelegatingHnalder etc. that manages it all for us.
The reason is so that we don't block services like from IHttpClientFactory etc.

FOUNDATIONS: Allow nullable value properties to be skipped or be part on the multipart-form

Currently we cannot construct a multipart-form for a model which has null or empty value properties.

public class Person
{
    [RESTFulStringContent(name: "firstName")]
    public string FirstName { get; set; }

    [RESTFulStringContent(name: "middleName")]
    public string? MiddleName { get; set; }
}

async Task MakeRequestAsync()
{
    var person = new Person
    {
        FirstName = "John Smith",
        MiddleName = null
    };

    var httpClient = SetupHttpClient();
    var apiClient = new RESTFulApiFactoryClient(httpClient);

    var response = await apiClient.PostFormAsync<Person, string>("/users", person);
}

Since no value was provided for middleName property, the next exception is thrown:

RESTFulSense.Models.Coordinations.Forms.Exceptions.FormCoordinationDependencyValidationException : Form coordination dependency validation error occurred, fix the errors and try again.
---- RESTFulSense.Models.Orchestrations.Forms.Exceptions.FormOrchestrationDependencyValidationException : Form orchestration dependency validation error occurred, fix the errors and try again.
-------- RESTFulSense.Models.Foundations.Forms.Exceptions.FormValidationException : Form validation error occurred, fix errors and try again.
------------ RESTFulSense.Models.Foundations.Forms.Exceptions.InvalidFormArgumentException : Invalid form arguments.Please fix the errors and try again.
Stack Trace:
at RESTFulSense.Services.Coordinations.Forms.FormCoordinationService.TryCatch(ReturningMultipartFormDataContentFunction returningMultipartFormDataContentFunction)
at RESTFulSense.Services.Coordinations.Forms.FormCoordinationService.ConvertToMultipartFormDataContent[T](T object)
at RESTFulSense.Clients.RESTFulApiFactoryClient.PostFormAsync[TContent, TResult](String relativeUrl, TContent content, CancellationToken cancellationToken)
// ...

FEATURE: Create HTTP Errors Easily in `WebAssembly` Project

Currently if you want to create exceptions for unit tests, when you are using WebAssembly library, you have to do the following:

public static TheoryData CriticalDependencyExceptions()
{
    string someMessage = GetRandomMessage();
    var someResponseMessage = new HttpResponseMessage();

    return new TheoryData<Xeption>()
    {
        new HttpResponseUrlNotFoundException(
            someResponseMessage,
            someMessage),

        new HttpResponseUnauthorizedException(
            someResponseMessage,
            someMessage),

        new HttpResponseForbiddenException(
            someResponseMessage,
            someMessage)
    };
}

At the same time Core project made it easier to create the above exceptions without response message and message.

SERVICES: Add service method to set the HttpClient Authorization header

Hello,

Is it possible to add (or maybe there is) a way to set the Authorization request header to the httpClient inside RESTFulApiFactoryClient

Mybe something like that:

public void SetAuthenticationHeaderValue(AuthenticationHeaderValue authenticationHeaderValue)
            => this.httpClient.DefaultRequestHeaders.Authorization = authenticationHeaderValue;

Thanks!

Error in MapExceptionDataToProblemDetail with some SqlExceptions

I had a Microsoft.Data.SqlClient.SqlException bubble up to the controller which then threw the following exception:

System.InvalidCastException: 'Unable to cast object of type 'System.String' to type 'System.Collections.Generic.List``1[System.String]'.'

The exception had the following Data:

{ "HelpLink.ProdName", "Microsoft SQL Server" }
{ "HelpLink.ProdVer", "15.00.2080" }
{ "HelpLink.EvtSrc", "MSSQLServer" }
{ "HelpLink.EvtID", "208" }
{ "HelpLink.BaseHelpUrl", "https://go.microsoft.com/fwlink" }
{ "HelpLink.LinkId", "20476" }

i.e. A Dictionary<string, string> rather than a Dictionary<string, List<string>>.

Happy to submit a PR if it's something you want to handle.

MEDIUM FIX: Enable creation of multipart-form with non-string types

Currently when trying to construct a multipart-form for a model which has properties of another type except for string type, the next exception is thrown: Unable to cast object of type 'System.Decimal' to type 'System.String'.

public class Person
{
    [RESTFulStringContent(name: "firstName")]
    public string FirstName { get; set; }

    [RESTFulStringContent(name: "salary")]
    public decimal Salary { get; set; }
}

async Task MakeRequestAsync()
{
    var person = new Person
    {
        FirstName = "Jane Smith",
        Salary = 10_500M
    };

    var httpClient = SetupHttpClient();
    var apiClient = new RESTFulApiFactoryClient(httpClient);

    var response = await apiClient.PostFormAsync<Person, string>("/users", person);
}

Exception thrown:

RESTFulSense.Models.Client.Exceptions.RESTFulApiClientDependencyException : Form coordination dependency error occurred, fix the errors and try again.
---- RESTFulSense.Models.Orchestrations.Forms.Exceptions.FormOrchestrationServiceException : Form orchestration service error occurred, contact support.
-------- RESTFulSense.Models.Orchestrations.Forms.Exceptions.FailedFormOrchestrationServiceException : Failed form orchestration service occurred, please contact support
------------ System.InvalidCastException : Unable to cast object of type 'System.Decimal' to type 'System.String'.

Add PostContent/PutContent overloads on IRESTFulApiFactoryClient

Next overloads on the IRESTFulApiFactoryClient allow for scenarios where multipart form-data payload can be sent to the server and still have the response validation is place.

In some scenarios, it is useful to return the HttpResponseMessage directly and allow the client to deserialize the response. In other scenarios, the TResponse is the expected type of deserialization.

namespace RESTFulSense.Clients
{
    public partial interface IRESTFulApiFactoryClient
    {
        ValueTask<HttpResponseMessage> PostContentAsync(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
        ValueTask<TResponse> PostContentAsync<TResult>(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);

        ValueTask<HttpResponseMessage> PutContentAsync(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
        ValueTask<TResponse> PutContentAsync<TResult>(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
    }
}

namespace RESTFulSense.WebAssembly.Clients
{
    public partial interface IRESTFulApiFactoryClient
    {
        ValueTask<HttpResponseMessage> PostContentAsync(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
        ValueTask<TResponse> PostContentAsync<TResult>(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);

        ValueTask<HttpResponseMessage> PutContentAsync(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
        ValueTask<TResponse> PutContentAsync<TResult>(string relativeUrl, HttpContent content, CancellationToken cancellationToken = default);
    }
}

Error Self referencing.

I get an error Self referencing loop detected for property 'X' with type 'XX'.
My method in ApiBroker:

private async ValueTask<T> PutAsync<T>(string relativeUrl, T content)
{
return await apiCient.PutContentAsync(relativeUrl, content);
}
Before I used System.Text.Json and to go around this error, I just create JsonSerializerOptions where ReferenceHandler = ReferenceHandler.IgnoreCycles and then I send this option with PutAsJsonAsync like this:
JsonSerializerOptions options = new() { ReferenceHandler = ReferenceHandler.IgnoreCycles };
await client.PutAsJsonAsync(url, obj, options);
My question:
How can I add this option in PutAsync?
Thanks.

CLIENTS: Add PATCH methods

Some APIs use PATCH instead of PUT and RESTFulSense should support that. Currently, neither client in RESTFulSense exposes PATCH methods.

CODE RUB: Remove access modifiers from IRESTFulApiClient interfaces

Currently, interfaces IRESTFulApiClient and IRESTFulApiFactoryClient define the public access modifier on some of the methods.

Remove public access modifiers from the next interfaces:

  • RESTFulSense.Clients.IRESTFulApiClient
  • RESTFulSense.Clients.IRESTFulApiFactoryClient
  • RESTFulSense.WebAssembly.Clients.IRESTFulApiClient
  • RESTFulSense.WebAssembly.Clients.IRESTFulApiFactoryClient

MEDIUM FIX: `JsonSerializationException` leakage

If the serialization goes wrong, for example, when the value to be deserialized is outside the valid range of the target datatype, the library will throw a JsonSerializationException which will leak to the customer. But this exception should be wrapped by the library.

Send an empty string or null in the uri

I have a method get request that has a parameter and some time this parameter has no value, so the default value is empty string or null:

public async ValueTask<List<Order>> GetOrdersAsync(string properties = null) => await this.GetAsync<List<Order>>($"{OrderUrl}/includeProperties/{properties}");

But I got error and it doesn't hit the end point of my controller!
Thanks for help.

JsonPropertyName is not getting recognized while serializing due to Newtonsoft Dependency

While Acceptance and Integration testing using PostContentAsync method, I was going through the source code and I see a dependency to serialize using Newtonsoft JsonSerializerSettings (in ConvertToJsonStringContent within RESTFulApiFactoryClient).

In case the underlying object uses System.Text.Json JsonPropertyName Attribute . Those json settings are ignored, and I get BadRequest Error..

I tried handcrafting the object using ExpandoObject() with desired serialized property names and it worked.

In case the underlying "Type" uses System.Text.Json then serialization should honor System.Text.Json serialization logic instead of defaulting to Newtonsoft

MAJOR FIX: Property Naming Convention Violates JSON Naming Conventions

When controllers are configured to use Camel Case for JSON Serialization, it correctly returns the data, but when an exception is thrown, the properties under errors are returned with Pascal Case convention.

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Invalid city. Please correct the errors and try again.",
  "status": 400,
  "errors": {
    "Name": [
      "Text is required"
    ],
    "CreatedDate": [
      "Date is required",
      "Date is not recent"
    ],
    "CreatedByUser": [
      "Text is required"
    ],
    "UpdatedDate": [
      "Date is required"
    ],
    "UpdatedByUser": [
      "Text is required"
    ]
  }
}

DOCUMENTATIONS: Cleanup Readme HTML Tags

This is further cleanup of the Readme markdown to remove the irrelevant HTML markup that adds no value to markdown syntax.
It also displays as rendered HTML text in the nuget.org RESTFulSense package when the readme is uploaded.

Current nuget images.

html-1
html-3
html-2
html-4

FOUNDATIONS: Add Built-In Caching for Existing Calls within Interval

Proposal:

We need to consider adding an option to supporting In-Memory or Redis caching integration out of the box with RESTfulSense.

Here's a scenario:
Consider a system that makes several calls to the same API with the same parameters in less than 1 second. And optimization effort here can be done to offload some of the latency cost on the API consumer side.

Here's how I visualize this to look like:

Specific Operation Configuration

        private async ValueTask<T> GetAsync<T>(string relativeUrl) =>
            await this.apiClient.GetContentAsync<T>(relativeUrl, enableCaching: true, cacheInvalidation: 1000);

Global Configuration

        private readonly IRESTFulApiFactoryClient apiClient;

        public ApiBroker(IRESTFulApiFactoryClient apiClient)
        {    
            this.apiClient = apiClient;
            this.apiClient.ConfigureCache(enableCaching: true, cacheInvalidation: 1000);
        }

External Source Configuration

Contract

public interface IRESTFulSenseCaching
{
    ValueTask<T> TryGetCachedValue(string key);
}

Utilization

        public ApiBroker(IRESTFulApiFactoryClient apiClient, IRESTFulSenseCache externalCacheSource)
        {    
            this.apiClient = apiClient;
            this.apiClient.ConfigureCache(enableCaching: true, cacheInvalidation: 1000, source: externalCacheSource);
        }

FEATURE: Handle `HTTPRequestException`

Currently, we are only handling httpResponseException. However, some api are also throwing httpRequestException (for example, Azure AAD, while login). So, come up with purposing, modellling and simulation of this feature. Once approved here, you can start coding!

CLIENTS: Need a way to output HttpResponseMessage before deserializing

Hi!

I have a problem when posting a request to an endpoint. Deserializing the response causes

Unexpected character encountered while parsing value: <. Path '', line 0, position 0.

image

It´s curious if I run the post from Postman with the exact input json I retrieved the output json. It seems correct

image

So I don´t know what´s trying to deserialize.
I try to import all the RESTFulSense project to debug it without success because wrong references between NetStandard RESTFulSense project conflicts with my .Net6 project so not able to compile. I tried adding some Console.WriteLine on responseString inside DeserializeResponseContent but i don´t know why something it´s blocking the messages to console. I tried too some static Action to "listen" the value from my broker but MissingMethodException at runtime.

Any suggestion?

Thanks in advance!

CODE RUB: Fix Swagger Failure For RESTFulController

Swagger fails since some methods inside RESTFulSense.Controller class are public but have no attributes on them.

Error Message:

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Ambiguous HTTP method for action - XXXXXXXXX.YYYYController.BadRequest. Actions require an explicit HttpMethod binding for Swagger/OpenAPI 3.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.