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

Allow Set for ContentType property of Parameter #2112

Open
pboisso opened this issue Jul 10, 2023 · 15 comments
Open

Allow Set for ContentType property of Parameter #2112

pboisso opened this issue Jul 10, 2023 · 15 comments

Comments

@pboisso
Copy link

pboisso commented Jul 10, 2023

Is your feature request related to a problem? Please describe.
I can't find a way to not write Content-Type for multipart form-data post. Migrating from v106.

Describe the solution you'd like
Could allow public Set to the ContentType property of the Parameter class?

Additional context
Please check difference between v106.15.0 on the left and v110.2.0 on the right.

image

@alexeyzimarev
Copy link
Member

alexeyzimarev commented Jul 13, 2023

It's a usage question, please do not ignore the contribution guidelines when opening issues.

As for the question itself, you can create an instance of BodyParameter and specify the content type in the constructor call. The add it using AddParameter.

@alexeyzimarev alexeyzimarev closed this as not planned Won't fix, can't repro, duplicate, stale Jul 13, 2023
@pboisso
Copy link
Author

pboisso commented Jul 13, 2023

Hi @alexeyzimarev,

Thanks for the answer. However, I feel this is still a feature request.

Trying to add BodyParameter the way you described, but when I do, the parameters do not even appear in the request. There is no body in that request, only Post parameters.

                request.AddParameter(new BodyParameter(s.Key, s.Value, null) { Type = ParameterType.GetOrPost });

Does NOT work.

                request.AddParameter(s.Key, s.Value, ParameterType.GetOrPost);

Does work, but by adding Content-Type and charset.

I've tried several ways, but I could not find a way to just add a plan Post parameter without Content-Type/charset being added.

Note that

                request.AddParameter(s.Key, s.Value);

Was working fine in v106 without any other settings being changed.

Could you consider adding ContentType in the AddParameter method?

Thanks.

Patrice

@alexeyzimarev
Copy link
Member

Of course it doesn't work as you override the parameter type.

@pboisso
Copy link
Author

pboisso commented Jul 17, 2023

@alexeyzimarev,

Here is the code in v106:

var client = new RestSharp.RestClient();
client.BaseUrl = strUrlToCall;
var request = new RestSharp.RestRequest(RestSharp.Method.POST);
request.AlwaysMultipartFormData = true;
request.AddParameter("name", strFrom);
request.AddParameter("email", strEmail);
request.AddParameter("body", strHTMLBody);
var response = client.Execute(request);

The following code in v110:

var client = new RestClient();
var request = new RestRequest(urlToCall, Method.Post);
request.AlwaysMultipartFormData = true;
request.AddParameter("name", strFrom);
request.AddParameter("email", strEmail);
request.AddParameter("body", strHTMLBody);
var response = client.Execute(request);

does NOT give the same post. Content-type is added for each parameter (as displayed in the image in the first post of this thread).

If I use

request.AddParameter(new BodyParameter("name", strFrom));
request.AddParameter(new BodyParameter("email", strEmail));
request.AddParameter(new BodyParameter("body", strHTMLBody));

as you suggested, I get a "Invalid content type string" error message.

Please advise how to run the v106 code above in v110 so that I get the same exact post output.

Thanks from a simple developer just trying to migrate to latest version.

Patrice

@alexeyzimarev
Copy link
Member

Ok, that should've been there from the beginning. It's hard to understand what your goal is when there's no code.

So, basically, you don't want to set the content type, you want to remove it. RestSharp doesn't explicitly add content type to multipart-form request body parameters. It's the default message handler from .NET who does that.

Here's the StringContent constructor, which always sets the content type:

        public StringContent(string content, Encoding? encoding, string? mediaType)
            : base(GetContentByteArray(content, encoding))
        {
            // Initialize the 'Content-Type' header with information provided by parameters.
            MediaTypeHeaderValue headerValue = new MediaTypeHeaderValue((mediaType == null) ? DefaultMediaType : mediaType);
            headerValue.CharSet = (encoding == null) ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName;

            Headers.ContentType = headerValue;
        }

@alexeyzimarev alexeyzimarev reopened this Jul 19, 2023
@pboisso
Copy link
Author

pboisso commented Jul 19, 2023

Hello @alexeyzimarev,

Thanks for re-opening and the consideration. I use RestSharp to post a form to a ticket service. For some reason, if the content type is set for post parameters, they handle the message differently.

Also note that I'm also talking about the post parameter content-type here, not the message content-type, which is still properly set to multipart/form-data

So the fact content-type and charset is also added for each parameter does something different to the receiving party. That's the only difference between v106 and v110 (from raw output from Charles).

I've also tried the DisableCharset option, but that does not change the behavior. I've tried with different charset also (utf-8 and ISO-8859-1), but with no luck.

At the end, I don't know if it's a charset or content-type issue, or both, but the only difference between v106 and v110 raw http output is the line "Content-Type: text/plain; charset=utf-8" which is printed for each POST parameter in the form, right after the form boundary line.

I hope this help.

Thanks,
Patrice

@alexeyzimarev
Copy link
Member

That's basically what I described in my previous comment. It's the default behaviour of StringContent.

@alexeyzimarev
Copy link
Member

So even if you set the content type for the parameter to null, the StringContent constructor will override it with DefaultMediaType, which is text/plain, and that's what you see.

@pboisso
Copy link
Author

pboisso commented Aug 10, 2023

Not familiar with the internals, that's the goal of using a library ;) Just reporting that http raw output has changed from v106 to v110 with the same code and did not find a way to update the code to make the output the same. Unfortunately, that has apparently some impact on the receiving end. Reverting back to v106 for now. Thanks for the help.

@alexeyzimarev
Copy link
Member

Well, the point of FOSS is to have collaboration, so the issues can be resolved by the community.

I can confirm that the content type header for individual parameters can be removed after the content object is created. Not sure what the API should look like. My current thought is that it should be a new, separate parameter type like MultipartDataFormParameter. Adding such parameters would automatically ensure the form is set with the correct type and content type, as well as the parameter class would allow to override the parameter content type, including setting it to null.

I want to make clear that although the behaviour of RestSharp has changed on the transport level, it didn't become incorrect. Setting the content disposition header for multipart-data form parameters is the correct behaviour.

@Frankwayne
Copy link

I'm running into this issue as well trying to connect to a java service. While RestSharp is behaving correctly, I can't control external servers.

@Frankwayne
Copy link

MultipartDataFormParameter

Sounds good to me, idk if you will want to handle changing the behavior of StringContent inside of the constructor or with a method that will remove the ContentType.

I could be wrong as I haven't had the time to really review the RFC but if you are adding in the ability to write invalid transport text, then I would support a method to remove the ContentType of the multimedia part.

@Frankwayne
Copy link

So I got a chance to revisit my issue and it turns out that I need to be able to set the Media type like in the String Content type like below.

{ new StringContent(fileName, Encoding.UTF8, MediaTypeNames.Text.Plain), "deployment-name" },

I couldn't find a way to do this quickly in restsharp I tried the following

new RestRequest("/deployment/create", Method.POST)
                {
                        AlwaysMultipartFormData = true,
                }
                .AddParameter("deployment-name", fileName, MediaTypeNames.Text.Plain, ParameterType.RequestBody)

but my java service does not seem to pick it up.

@alexeyzimarev
Copy link
Member

This - Method.POST - kind of tells me you are using the old version of RestSharp.

Also, I am not sure that StringContent actually produces a multipart form.

It would help if you can post an example request that works. You can use requestbin.com to make a sample call and inspect how it looks.

@Frankwayne
Copy link

Well it turns out that there were some issues with original request parameters and not at the transport layer, like I had suspected. I have deleted the code I was using since I migrated back to using another library.

StringContent doesn't produce a multipart form but you can use it in mulitpart form request like so

var multipartContent = new MultipartFormDataContent()

multipartContent.Add(  new StringContent(fileName, Encoding.UTF8, MediaTypeNames.Text.Plain), "whatever"))

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

No branches or pull requests

3 participants