CarterCommunity / Carter

Carter is framework that is a thin layer of extension methods and functionality over ASP.NET Core allowing code to be more explicit and most importantly more enjoyable.
MIT License
2.06k stars 174 forks source link

OpenApi Scheme mapping for Requests #219

Closed Jaxelr closed 4 years ago

Jaxelr commented 4 years ago

Hi Carter Community,

Newbie here, so pardon any ignorance in advance. I am having trouble generating a consistent json to consume a Post method, using the generated OpenApi module.

I managed to recreate the issue using the Post method AddActor on the ActorsModule inside Carter's samples (https://github.com/CarterCommunity/Carter/blob/master/samples/CarterSample/Features/Actors/ActorsModule.cs#L43-L58).

https://github.com/CarterCommunity/Carter/blob/58b8109929903f9420bc4db1aeb4497b0e6932ed/samples/CarterSample/Features/Actors/ActorsModule.cs#L43-L58

image

Using the request generated from the openapi path, the result is a validation error from fluent, since the casings are different:

image

Ive attached the OpenApi json generated:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Carter <3 OpenApi",
    "version": "3.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:5000"
    }
  ],
  "paths": {
    "/actors": {
      "post": {
        "tags": [
          "Actors"
        ],
        "description": "Create an actor in the system",
        "operationId": "Actors_AddActor",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Actor"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created Actors"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Actor": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "minLength": 1,
            "type": "string"
          },
          "id": {
            "type": "integer"
          },
          "age": {
            "minimum": 0,
            "exclusiveMinimum": true,
            "type": "integer"
          }
        }
      }
    }
}

Given the mismatch is generated using the CamelCase static method inside the CarterOpenApi class:

https://github.com/CarterCommunity/Carter/blob/58b8109929903f9420bc4db1aeb4497b0e6932ed/src/Carter/OpenApi/CarterOpenApi.cs#L144

and:

https://github.com/CarterCommunity/Carter/blob/58b8109929903f9420bc4db1aeb4497b0e6932ed/src/Carter/OpenApi/CarterOpenApi.cs#L366

This surely is done by design, so my question is, is it viable to switch the usage to the ToPascalCase static method? I did some minor testing making the change on localhost and the only issue i found is a fail test on Should_return_Carter_approved_OpenAPI_json and the reasoning is that the newly "approved" json should include the different casing.

jchannon commented 4 years ago

Ha good spot and thanks for the well written issue.

I've taken a look at this and it did confuse me for a second. The OpenAPI is a red herring as this won't bear any reflection on modelbinding etc however I did spot the issue. In BindExtensions.cs we need to have the below for this to work:

return await JsonSerializer.DeserializeAsync(request.Body, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

We probably want a test around that too.

If you'd like to get involved then feel free to send a PR or I'll send one when I have 5mins spare!

Thanks again!

Jaxelr commented 4 years ago

Ohhhh, it didnt occurred to me to actually test the behavior outside of my current usage (which was the OpenApi generation).

Sure, ill take a stab at the PR.

Thanks!

jchannon commented 4 years ago

This has been added now