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

Adds support for setting multipart content in RequestInformation #615

Closed
wants to merge 1 commit into from

Conversation

andrueastman
Copy link
Member

@andrueastman andrueastman commented Sep 13, 2021

This PR closes #360

It adds the support of setting MultipartContent in the RequestInformation class through the newly added SetContentFromHttpContentAsync method.

This will also therefore enable a user to set the content of a RequestInformation instance from any derived instance of HttpContent.

Example usage

// create requestInfo
var testRequest = new RequestInformation
{
    HttpMethod = HttpMethod.POST,
    URI = new Uri("http://localhost")
};
// Create an instance of MultipartContent
var content = new MultipartContent("mixed", "customBoundary")
{
    new StringContent("value1"), // string content
    JsonContent.Create(new { name = "Peter Pan"} ) // instance of JsonContent
};

// set the content (headers will also be copied across)
await testRequest.SetContentFromHttpContentAsync(content);

Tests have been added to validate this as well.

@andrueastman andrueastman self-assigned this Sep 13, 2021
@andrueastman andrueastman marked this pull request as ready for review September 13, 2021 08:50
@andrueastman andrueastman added the Csharp Pull requests that update .net code label Sep 13, 2021
@andrueastman andrueastman added this to the Beta milestone Sep 13, 2021
/// </summary>
/// <param name="httpContent">The <see cref="HttpContent"/> instance to set as a content of the request.</param>
/// <param name="cancellationToken">The (optional) <see cref="CancellationToken"/> to use.</param>
public async Task SetContentFromHttpContentAsync(HttpContent httpContent, CancellationToken cancellationToken = default)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a dependency on system.net.http in the abstractions breaks of promise of not having implementations details creep up in the abstractions.
If that'd be kind of ok in dotnet because there's a strong consensus on the http client, it wouldn't work for other languages.
We need to find an alternative, would having the content property be a list of streams, and if it contains a single entry, we keep the current behavior, however if we have multiple entries, we build a multipart request work?

Copy link
Member Author

@andrueastman andrueastman Sep 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@baywet I see your point. That would possibly work. I'm afraid though that we might end up creating extra steps for the user to setup the RequestInformation object.
The other alternative would be to move this to the HttpClient library as an extenstion of the RequestInformation class. That way, it wouldn't really creep into the Abstractions and avoid the system.net.http depedency and still leverage the MultipartContent without having to end up creating extra steps for the user to set the RequestInformation content

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check out the latest update and let me know what you think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a design perspective we can't rely on an extension method. This only works in dotnet and partially works in the TypeScript/Go eco-systems. And I'd like to avoid having language specific implementations for things like this that are so central to the architecture of the SDKs.
Unless you have a better suggestion, let's go with a List of content approach, if people complain about the complexity, we can always try to add facilitating methods in core, which could be in that case an extension method for dotnet/go.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries. Marking this PR as draft for now as I work this out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the extra info @baywet,

For the generated code, the current Sdk does not generate the overload accepting the stream (see here). The file you linked to is actually an extension class that has been handwritten as the OneNote Api is abit "weird" as the posting the stream does not happen to its "content" property as its csdl describes it.

This would also explain why running Kiota also generates the post method with the OnenotePage object rather than a binary object (see here) as well.

If it makes sense, I can close this for now and we can dig further into this after #220. (If need be, one could always send the multipart request with either of the snippets we provided above)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so from a service perspective we have 2 main overloads if I understand things right:

  • Json body -> the page only contains text
  • multipart -> the page contains text and rich content
    But today we're only generating for the json body case, is that correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure but I think there is a possibility Json body route might not possibly work and we can't really know since we can't really infer this from the metadata. The docs say we should just post the rich content and has no mention of the json route and it will return the json representation as a response.
I believe the extensions exist to allow the user to post a MultipartContent or Stream but unless the metadata somehow says so, we can't avoid generating the json route.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so at this point it would be a metadata issue. Is there any other instance of multipart requests in the API this far?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After searching through the docs' repo and the SDK repo, I could only find the OneNote api we discussed.

https://docs.microsoft.com/en-us/graph/api/section-post-pages?view=graph-rest-1.0

@andrueastman andrueastman force-pushed the andrueastman/MultipartContent branch from cd4bfd9 to e6ba431 Compare September 14, 2021 06:04
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@andrueastman andrueastman requested a review from baywet September 14, 2021 06:06
@andrueastman andrueastman marked this pull request as draft September 15, 2021 08:55
@baywet baywet deleted the andrueastman/MultipartContent branch March 22, 2022 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Csharp Pull requests that update .net code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Move middleware and other generic components from graph core to the http core library
2 participants