5.17Setting Multipart Form Content (Complex Forms / File Upload)

Updated on Aug 20, 2026~12 min read

Sets the request content type to multipart/form-data and sends multipart form content.

HTTP declarative requests set multipart form content via the MultipartAttribute attribute. The corresponding HTTP declarative extractor is implemented as the MultipartDeclarativeExtractor type, which is responsible for parsing the MultipartAttribute and MultipartFormAttribute attributes and building the multipart form content configuration required by the HttpRequestBuilder instance.

cs
public interface IHttpService : IHttpDeclarative{    // Adds common form item content    [Post("https://furion.net/")]    Task<string> PostStringAsync(        [Multipart] int id,        [Multipart] string name,        [Multipart] object obj,        [Multipart] Stream stream,        [Multipart("bytes")] byte[] byteArray,  // custom form name; the file name can also be specified via the FileName property        [Multipart] StringContent content        [Multipart] MultipartFile file);    // Adds file content    [Post("https://furion.net/")]    Task<string> PostStringAsync(        [Multipart(AsFileFrom = FileSourceType.None)] string none, // does nothing        [Multipart("files", AsFileFrom = FileSourceType.Path, ContentType = "image/jpeg")] string filePath,  // adds from a local file path; if Content-Type is not provided, it is resolved automatically from the file extension        [Multipart("files", AsFileFrom = FileSourceType.Base64String)] string base64String,  // adds from a Base64 string file; if Content-Type is not provided, it is resolved automatically from the file extension        [Multipart("files", AsFileFrom = FileSourceType.Remote)] string remote); // adds from an internet file address; if Content-Type is not provided, it is resolved automatically from the file extension    // Adds object content; when AsFormItem is false, the object's properties are parsed and iterated, and its properties are set as independent form items    [Post("https://furion.net/")]    Task<string> PostStringAsync([Multipart(AsFormItem = false)] object obj); // [MultipartObject] is recommended    // Sets the boundary of the multipart form content    [MultipartForm("--------------------")]    [Post("https://furion.net/")]    Task<string> PostStringAsync([Multipart] int id);    // Sets the form name naming policy (converter)    [Post("https://furion.net/")]    [MultipartForm(NamingPolicy = FormNamingPolicy.CamelCase)]    Task<string> PostStringAsync([MultipartObject] object obj);    // Frozen parameter types will be ignored    [Post("https://furion.net/")]    Task<string> PostStringAsync([Multipart] CancellationToken cancellationToken);}

Complex Forms Containing Files (or Binary Data)

When handling complex forms that contain basic data along with files (or binary data), you can use the [MultipartObject] attribute to mark the corresponding complex type. For file fields, it is recommended to declare the file field using the MultipartFile type. An example interface definition is as follows:

cs
public interface IHttpService : IHttpDeclarative{    [Post("https://furion.net/")]    Task<string> PostStringAsync([MultipartObject] FormClass data);}

The corresponding model class is defined as follows:

cs
public class FormClass  // Supports defining aliases via the [AliasAs] attribute{    public int Id { get; set; }    public string Name { get; set; }    public MultipartFile File { get; set; }    // public IFormFile File { get; set; }  // Note: needs to be configured according to the following steps}

Note: If you use IFormFile instead of MultipartFile, make sure that FormFileContentProcessor has been registered. You can complete the registration by calling .AddHttpContentProcessors(() => [new FormFileContentProcessor()]) globally:

In the Startup.cs or Program.cs file, configure and register the HttpRemote service to enable the IFormFile content processor feature:

cs
services.AddHttpRemote(builder =>{    builder.AddHttpContentProcessors(() => [ new FormFileContentProcessor() ]);});

In this way, the framework automatically submits the primitive-type properties of the object as ordinary form items, and correctly encodes and transmits MultipartFile-typed properties as file upload content.

Parameters marked with MultipartAttribute are set through the underlying httpRequestBuilder.SetMultipartContent method, and support parameters of any non-frozen type. The following code example shows how to achieve the same configuration effect using HttpRequestBuilder:

cs
// Add common form item contentHttpRequestBuilder.Post("https://furion.net")    .SetMultipartContent(multipart =>    {        multipart.AddFormItem(1, "id");        multipart.AddFormItem("Furion", "name");        multipart.AddFormItem(new { id = 1, name = "Furion" }, "obj");        multipart.AddStream(stream, "stream");        multipart.AddByteArray(bytes, "bytes");        multipart.Add(stringContent, "content");        multipart.AddFile(Multipart.CreateFromPath("path"));    });// Add file contentHttpRequestBuilder.Post("https://furion.net")    .SetMultipartContent(multipart =>    {        multipart.AddFileAsStream(@"C:\Workspaces\httptest.jpg", "files", contentType: "image/jpeg");        multipart.AddFileFromBase64String("77u/5rWL6K+V5paH5Lu25YaF5a65", "files");        multipart.AddFileFromRemote("https://furion.net/img/furionlogo.png", "files");    });// Add object content. When AsFormItem is false, the object is parsed and traversed, and its properties are set as independent form itemsHttpRequestBuilder.Post("https://furion.net")    .SetMultipartContent(multipart =>    {        multipart.AddObject(new { id = 1, name = "furion" });   // When AsFormItem is false, it is equivalent to not setting a form name    });// Set the boundary of the multipart form contentHttpRequestBuilder.Post("https://furion.net")    .SetMultipartContent(multipart =>    {        multipart.SetBoundary("--------------------");        multipart.AddFormItem(1, "id");    });// Add complex form contentHttpRequestBuilder.Post("https://furion.net")    .SetMultipartContent(multipart =>    {        multipart.AddObject(new FormClass { Id = 1, Name = "furion", File = MultipartFile.CreateFromPath("file path") });    });

Comparing the two approaches for sending multipart form content above, the HTTP declarative request approach has a more organized code structure and is easier to organize, maintain, and reuse.

MultipartAttribute includes the following constructors and properties:

  • Constructors:

    • new(): applies to a parameter, using the parameter as the multipart form item content.
    • new(name): applies to a parameter, using the parameter as the multipart form item content, and supports setting the form name.
  • Properties:

    • Name: the form name (string type).
    • FileName: the name of the file (string type).
    • ContentType: the content type (string type).
    • ContentEncoding: the content encoding (string type).
    • AsFileFrom: indicates the source for treating a string as a multipart form file (FileSourceType type). It is used to set the multipart form file content and only takes effect when the parameter is of string type. The FileSourceType enumeration includes the following options:
      • None (default): not used as the source of the file.
      • Path: used as a local file path.
      • Base64String: used as a Base64 string file.
      • Remote: used as an internet file address.
    • AsFormItem: indicates whether it is treated as one item of the form (bool type). The default value is true (treated as an item), and it only takes effect when the parameter is of object type. When false (not treated as an item), the object is parsed and traversed, and its properties are set as independent form items.

MultipartFormAttribute includes the following constructors and properties:

  • Constructors:

    • new(): applies to a method, configuring the multipart form content properties.
    • new(boundary): applies to a method, configuring the multipart form content properties, and supports setting the boundary of the multipart form content.
  • Properties:

    • Boundary: the boundary of the multipart form content (string type). The default value is: $"----{DateTime.Now.Ticks:x}".
    • OmitContentType: whether to remove the default multipart content Content-Type (bool type). The default value is true.
    • NamingPolicy: the form name naming policy (converter) (FormNamingPolicy type). The default value is FormNamingPolicy.None.