Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling Streams as Body parameters #369

Closed
dcbroad3 opened this issue Oct 14, 2016 · 6 comments
Closed

Handling Streams as Body parameters #369

dcbroad3 opened this issue Oct 14, 2016 · 6 comments

Comments

@dcbroad3
Copy link

I have a Web API assembly with something like the following:

        /// <summary>
        /// Update a thing.
        /// </summary>
        /// <param name="id">
        /// The ID of the thing to update.
        /// </param>
        /// <param name="thing">
        /// A partial thing containing the desired changes.
        /// </param>
        [HttpPatch, Route("things/{id}", Name = "UpdateThing")]
        [RequestType(typeof(ThingDTO))]
        public HttpResponseMessage Update(string id, Stream thing)
        {
            Thing thingToUpdate = Restorer.RestoreByID<Thing>(id);
            thing.Deserialize(thingToUpdate);
            return ApiResponses.NoContent(this.Request);
        }

NSwag thinks this means we are passing in the properties of a Stream (canRead, canWrite, position, length, etc.). What we're actually doing is passing in partial properties of the ThingDTO, indicated by the RequestType attribute, as a Body parameter.

This may be too custom to be included in the master branch, but I've been able to make a tweak that allows this to work. In WebApiToSwaggerGenerator.LoadParameters, I check whether the parametertype is a Stream. If so, I check for a RequestType attribute, and get the Type off of it. I generate a JsonObjectTypeDescription using:
var typeDescription = JsonObjectTypeDescription.FromType(type, parameter.GetCustomAttributes(), Settings.DefaultEnumHandling);
I add the type from the RequestType attribute to the schema:
var schema = swaggerGenerator.GenerateAndAppendSchemaFromType(type, false, parameter.GetCustomAttributes());
Then I construct a custom SwaggerParameter (using the Body kind) and add it to the operation Parameters.

I can submit a PR if something like this might be included in NSwag, but figured I would ask first since it feels pretty custom.

@RicoSuter
Copy link
Owner

I think we could do this the other way around: If there is a RequestType attribute, treat the body parameter as this type and ignore the actual type?

@dcbroad3
Copy link
Author

Yeah I was thinking the same thing just after posting - the reverse makes more sense. That'd work for me. Let me know if you're interested in a PR - it just comes down to grabbing the Type off the RequestType attribute and using that instead of the actual type.

@RicoSuter
Copy link
Owner

Do you already have the code for a PR? Where does the RequestTypeAttribute come from? Is this a custom attribute? Maybe we should call it RequestBodyTypeAttribute?

@dcbroad3
Copy link
Author

It is a custom attribute. Actually, I don't have the ability to change its name, which makes me think it may be the wrong approach to really build in this functionality too specifically. I'm honestly not sure what the right approach would be. I was able to get this to work in Swashbuckle because it accepts a method to be called after each operation has been processed that allows you to modify the result using the Api Documentation, and I'm able to use that to change the type to the type on one of the attributes. I would imagine it would be a lot of work to duplicate that kind of setup in NSwag.

@RicoSuter
Copy link
Owner

With NSwag, you can also define OperationProcessors: https://github.com/NSwag/NSwag/wiki/Middlewares#enable-authorization-in-generator-and-swagger-ui

@dcbroad3
Copy link
Author

Awesome! Well, honestly, that might be all I need. I'll look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants