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

Just updated to latest AutoRest generated code no longer builds. #2745

Closed
joshmouch opened this issue Dec 1, 2017 · 9 comments
Closed

Just updated to latest AutoRest generated code no longer builds. #2745

joshmouch opened this issue Dec 1, 2017 · 9 comments

Comments

@joshmouch
Copy link

I just updated AutoRest.CSharp from 2.0.0 to 2.2.45, and now it seams FileStream is broken. Let me clarify.

In my ASP.Net Core 2.0 project, in my API method, I have a parameter of type IFormFile. Swashbuckler converts this into a swagger parameter with "Parameter Type"="formData" and "Data Type"="file".

Before the update this caused AutoRest to generate code like this:

// Serialize Request
            string _requestContent = null;
            MultipartFormDataContent _multiPartContent = new MultipartFormDataContent();
            if (message != null)
            {
                 StreamContent _message = new StreamContent(message);
                _message.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                FileStream _messageAsFileStream = message as FileStream;
                if (_messageAsFileStream != null)
                {
                    ContentDispositionHeaderValue _contentDispositionHeaderValue = new ContentDispositionHeaderValue("form-data");
                    _contentDispositionHeaderValue.Name = "message";
                    _contentDispositionHeaderValue.FileName = _messageAsFileStream.Name;
                    _message.Headers.ContentDisposition = _contentDispositionHeaderValue;
                }
                _multiPartContent.Add(_message, "message");
            }
            _httpRequest.Content = _multiPartContent;

But now after the update, AutoRest generates this:

// Serialize Request
            string _requestContent = null;
            var values = new List<KeyValuePair<string, string>>();
            if(message != null)
            {
                values.Add(new KeyValuePair<string,string>("message", message));
            }
            var _formContent = new FormUrlEncodedContent(values);
            _httpRequest.Content = _formContent;

This causes a build error because "message" is of type System.IO.Stream. The build error is:
Argument 2: cannot convert from 'System.IO.Stream' to 'string'

@fearthecowboy fearthecowboy assigned olydis and unassigned olydis Dec 1, 2017
@fearthecowboy
Copy link
Member

Wait-- do you mean "in": "formData" in the swagger ? FormData is for key-value pairs.

That should not have been used for streams in the first place; there was a bug recently fixed to properly support formData for parameters.

You should be using "in": "body", in your parameter declaration:

 "parameters": [
     {
            "name": "body",
            "in": "body",
            "schema": {
              "type": "object",
              "format": "file"
            },
            "required": true,
            "description": "The file to upload."
          },
  ]

@joshmouch
Copy link
Author

The swagger looks like this. This was the only way I could find to get the Swashbuckler/AutoRest combination to support streams. I'll try contacting Swashbuckler to see if they have away to generate the "in": "body" in the swagger definition, instead.

{
name: "message",
in: "formData",
required: false,
type: "file"
},

@joshmouch
Copy link
Author

@fearthecowboy So using "formData" is the suggested solution in the following thread, so I don't know who to listen to:

domaindrivendev/Swashbuckle.AspNetCore#193

@joshmouch
Copy link
Author

@fearthecowboy To confuse things more, I just took a fiddler dump of what the call to the API looks like, and it is using multipart/form-data. So why would I use "body" instead of "form-data"?

POST http://... HTTP/1.1
Authorization: Bearer ...
User-Agent: FxVersion/4.7.2600.0 OSName/Windows10Pro OSVersion/6.3.16299
Content-Type: multipart/form-data; boundary="40ef5fe2-4e13-4b22-be34-8c2c566024b2"
Host: api.epreop.local:5000
Content-Length: 405859
Expect: 100-continue

--40ef5fe2-4e13-4b22-be34-8c2c566024b2
Content-Type: application/octet-stream
Content-Disposition: form-data; name=message; filename="..."

....

@fearthecowboy
Copy link
Member

Hmm. It's entirely possible at this point that I'm way off base here.

From the looks of it :

The value MUST be one of "string", "number", "integer", "boolean", "array" or "file". If type is "file", the consumes MUST be either "multipart/form-data", " application/x-www-form-urlencoded" or both and the parameter MUST be in "formData".

Apparently, I'm in the wrong... at least for a bunch of it.

We did fix a bug where form-encoded data wasn't built correct at all; It may have worked completely accidentally previously.

To support this appropriately, we'd definitely have to support multiple streams per-request (since multipart/form-data could have multiple files to upload, and I don't ever recall seeing any tests around that at all.)

I'm looking into fixing it...

@fearthecowboy
Copy link
Member

Can you give me your swagger so I can see exactly what you're specifying? (either here or send it to garretts@microsoft.com)

@fearthecowboy
Copy link
Member

Hmm. Looking at the code, that fix that went in shouldn't even have affected what you were doing at all

What's the consumes for that path? is it possible it used to be something else and is now application/x-www-form-urlencoded ? The code path diverges for that (and as far as I can tell, incorrectly ...)

@fearthecowboy
Copy link
Member

Ah, I think this is the result of a different tangential bug fix --

In https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-7 they state :

if type is "file", the consumes MUST be either "multipart/form-data", " application/x-www-form-urlencoded" or both and the parameter MUST be in "formData".

A bug got fixed where it now actually checks for the "multipart/form-data" -- your swagger has application/form-data

According to https://www.iana.org/assignments/media-types/media-types.xhtml -- there isn't an application/form-data media type.

@joshmouch
Copy link
Author

@fearthecowboy this fixed this for me. Thanks!

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

3 participants