14

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, IEnumerable1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable1 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?

3 Answers 3

0

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).

Sign up to request clarification or add additional context in comments.

Comments

0

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'

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.