Reputation: 687
Basically I'm trying to upload an image along with an enum using Web API 2.
Here's the controller signature:
[HttpPost]
public UploadResponseVm Upload([FromBody]ResImageType type)
{
The thing is, whenever I try to post a multipart form (with a file and a type) I get a 415 error:
{"Message":"The request entity's media type 'multipart/form-data' is not supported for this resource.","ExceptionMessage":"No MediaTypeFormatter is available to read an object of type 'ResImageType' from content with media type 'multipart/form-data'.","ExceptionType":"System.Net.Http.UnsupportedMediaTypeException","StackTrace":" at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable
1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable
1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"}
I have even added the following to my startup.cs class:
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
How can I upload a model along with a file using a web api controller?
Upvotes: 14
Views: 7814
Reputation: 582
The following example will solve the issue if you have the following code changes.
Put [FromForm]
with parameters
public async Task<ActionResult<Guid>> Create([FromForm] CreateEmployeeCommand command)
and in model
public class CreateEmployeeCommand
{
public IFormFile FormFile { get; set; }
public string AnyData { get; set; }
}
Use JS FormData
object to POST
data to the controller
Upvotes: 0
Reputation: 741
You can simply add media and enum at the same time by adding content type in header request.
Content-Type:application/x-www-form-urlencoded
Then try to access file and enum
[HttpPost]
public UploadResponseVm Upload()
{
//Get enum type
var enumkey = HttpContext.Current.Request.Form.AllKeys.FirstOrDefault(x => x == "enumkey");
var enumType = Convert.ToInt32(HttpContext.Current.Request.Form[enumkey]).ToEnum<ResImageType>();
//Access files
var postedFileLst = HttpContext.Current.Request.Files.GetMultiple("fileKey").ToList();
}
Use Extension Method to convert to enum
public static T ToEnum<T>(this int param)
{
var info = typeof(T);
if (info.IsEnum)
{
T result = (T)Enum.Parse(typeof(T), param.ToString(), true);
return result;
}
return default(T);
}
Also verify using curl
curl --location --request POST '{{hostname}}/api/media/addmedia' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'BookLogos=@/path/to/file' \
--form 'enumkey=1'
Upvotes: 0
Reputation: 444
There is no formatter that could handle/relate to your ResImageType
object. I have once solved a similar problem without a formatter by using a parameter-less method and have processed the data inside the method. For example:
public async Task<HttpResponseMessage> PostFormData()
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
string upDir= "PathOfDirectory";
MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider(upDir);
MultipartFileStreamProvider multipartFileStreamProvider = await Request.Content.ReadAsMultipartAsync(streamProvider);
// Loop through files.
foreach (MultipartFileData file in streamProvider.FileData)
{
// Save filepaths to DB or do something else
}
return Request.CreateResponse(HttpStatusCode.OK);
}
Similar solution from MS Docs
Another possibility is to create a DTO-like class that is used to transfer the object and use a formatter, for example MultipartDataMediaFormatter seems legit (haven't tried).
Upvotes: 0