3

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?

EBarr
  • 11,826
  • 7
  • 63
  • 85
Rivka
  • 2,172
  • 10
  • 45
  • 74

1 Answers1

1

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.

Community
  • 1
  • 1
EBarr
  • 11,826
  • 7
  • 63
  • 85
  • Thanks. Actually I'm using Web Forms - I have the Route Template defined as "api/{controller}/{action}/{actionType}" in the global file - it does expect the action. Remember, it works fine without the parameter there so I suspect it's got s/t to do with that. – Rivka May 07 '12 at 17:37
  • Webforms..huh? Does your controller inherit from `ApiController` ? Using firebug/fiddler/whatever ... what is listed in the request header `Accept`? Assuming you're excpecting json back it should be `application/json`. You may need `dataType: json` as part of your ajax call. – EBarr May 07 '12 at 18:27
  • My controller does inherite from apicontroller. In fiddler, the content-type is 'application/json'. I edited my OP to reflect my current ajax call. – Rivka May 07 '12 at 18:58
  • Thank you! That first link you posted to Rick's blog helped me. I used querystring/ParseQueryString() method (with no action parameter) which seemed to work. Appreciate your help. – Rivka May 07 '12 at 22:40