Search code examples
asp.net-web-apijquery-post

No 'MediaTypeFormatter' is available to read an object of type 'String'


I'm using the ASP.NET Web API. I have an action in my controller which works fine if there's no parameter. If there is a parameter, like:

public string UploadFile(string actionType)

then my action isn't called and I get the following message, viewed in Fiddler:

No 'MediaTypeFormatter' is available to read an object of type 'String' with the media type 'multipart/form-data'

The route in my global.asx is as follows:

"api/{controller}/{action}/{actionType}"

I'm using Jquery Post to call the action:

    function upload() {

        var actiontype = $("input:radio[name=actiontype]").val();
        var formData = new FormData($('form')[0]); 

        $.ajax({
            url: 'api/uploads/uploadfile/' + actiontype,
            type: 'POST',
            success: function (data) {
                $("#mydiv").append(data);
            },
            error: function (data) {
                $("#mydiv").append(data);
            },
            data: formData,
            cache: false,
            contentType: false, 
            processData: false
        });
    }; 

Here's my action method:

    public string UploadFile(string actionType)
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            //Save file
            MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));
            Request.Content.ReadAsMultipartAsync(provider);
        }

        return string.Format("Action {0} Complete!", actionType);
    }

Is this a known problem, with a workaround? How can I have a simple action with parameter?


Solution

  • Assuming you're using the default routes, it looks like you're posting to an incorrect path. This is a common confusion that MVC developers seem to encounter (i know i did). MVC uses a default path like: /Controller/Action.

    In web API's default routing setup, however, the action name is skipped (/api/Controller) then the method is found through the intersection of the HTTP verb name (post), the method name (Post___) and parameter if necessary.

    Assuming you have an API controller named Uploads, you should have an action named PostUploadFile.

       $.ajax({
            url: 'api/uploads/',
            type: 'POST',
    

    Some things to notice...

    • I started the name of your action with the text "Post..." this matters, the remainder of the name does not
    • Your post url was shorted to the name of the controller.
    • I went more in depth explaining the mapping here.

    EDIT

    Apparently your experiencing an odity of WebAPI. The way around this is to stuff your "actionType" parameter into a simple object, so model binding can take over.

    Rick Strahl explains this and some other binding oddities here. There is also another SO question addressing similar issues.