Introduction
This is a solution for automatic binding action parameters of custom types (including files) encoded as multipart/form-data. It works similar to ASP.NET MVC binding. This media type formatter can be used also for sending objects (using HttpClient
) with automatic serialization to multipart/form-data.
This formatter can process:
- custom non enumerable classes (deeply nested classes supported)
- all simple types that can be converted from/to
string
(using TypeConverter
)
- files (
MultipartDataMediaFormatter.Infrastructure.HttpFile
or byte[]
)
- generic arrays
- generic lists
- generic dictionaries
Using the Code
Install formatter from Nuget:
Install-Package MultipartDataMediaFormatter.V2
Add it to WebApi formatters collection:
If WebApi is hosted on IIS (on Application Start):
GlobalConfiguration.Configuration.Formatters.Add
(new FormMultipartEncodedMediaTypeFormatter(new MultipartFormatterSettings()));
If WebApi is self-hosted:
new HttpSelfHostConfiguration(<url>).Formatters.Add
(new FormMultipartEncodedMediaTypeFormatter(new MultipartFormatterSettings()));
Using formatter for sending objects (example from test project):
private ApiResult<T> PostModel<T>(T model, string url)
{
var mediaTypeFormatter = new FormMultipartEncodedMediaTypeFormatter(new MultipartFormatterSettings()
{
SerializeByteArrayAsHttpFile = true,
CultureInfo = CultureInfo.CurrentCulture,
ValidateNonNullableMissedProperty = true
});
using (new WebApiHttpServer(BaseApiAddress, mediaTypeFormatter))
using (var client = CreateHttpClient(BaseApiAddress))
using (HttpResponseMessage response = client.PostAsync(url, model, mediaTypeFormatter).Result)
{
if (response.StatusCode != HttpStatusCode.OK)
{
var err = response.Content.ReadAsStringAsync().Result;
Assert.Fail(err);
}
var resultModel = response.Content.ReadAsAsync<ApiResult<T>>(new[] { mediaTypeFormatter }).Result;
return resultModel;
}
}
You can use MultipartDataMediaFormatter.Infrastructure.FormData
class to access raw http data:
[HttpPost]
public void PostFileBindRawFormData(MultipartDataMediaFormatter.Infrastructure.FormData formData)
{
HttpFile file;
formData.TryGetValue(<key>, out file);
}
Bind custom model example:
public class PersonModel
{
public string FirstName {get; set;}
public string LastName {get; set;}
public DateTime? BirthDate {get; set;}
public HttpFile AvatarImage {get; set;}
public List<HttpFile> Attachments {get; set;}
public List<PersonModel> ConnectedPersons {get; set;}
public PersonModel Creator {get; set;}
public List<string> Attributes {get; set;}
}
[HttpPost]
public void PostPerson(PersonModel model)
{
}
History
Version 2.0.0 (2017-05-27)
Version 1.0.2 (2016-08-12)
- Parsing lists of simple types and files with not indexed naming scheme (keys have same names like "
propName
" or "propName[]
")
- Parsing values "
on
" and "off
" for boolean properties
- Binding
HttpFile
from http request as byte[]
if model has such property
- Added class
MultipartDataMediaFormatter.Infrastructure.MultipartFormatterSettings
to control:
CultureInfo
- Serializing
byte[]
as HttpFile
when sending data
- Validating non nullable value types properties if there are no appropriate keys in http request
Version 1.0.1 (2014-04-03)
- Fixed a bug that caused Exception (No
MediaTypeFormatter
is available to read an object of type <type name>) when posted data use multipart boundary different from used inside formatter code
- Fixed a bug that caused error when binding model with recursive properties
Version 1.0 (2013-11-22)
Notes
For successfully running tests from the test project, you should run Visual Studio with administrator rights because of using Self Hosted WebApi Server System.Web.Http.SelfHost.HttpSelfHostServer
.