Code Monkey home page Code Monkey logo

restfulsense's People

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: 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.

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: 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)
// ...

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);
    }
}

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"
    ]
  }
}

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);
        }

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.

CLIENTS: Add PATCH methods

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

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.

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

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.

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

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.

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

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.

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'.

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!

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.

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!

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!

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.