fletchsod
fletchsod

Reputation: 3719

Using parameter long? in Web API controller cause "no action was found on the controller..." error

The Web API works great but I don't understand why am I getting the "no action was found on the controller that matches the request error" exception error if I changed the parameter from "long parmAccountId" to "long? parmAccountId"? (See the "?" next to long datatype).

Is there a way to make it work? Thanks..

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "MemberApi",
            routeTemplate: "WebApi/Member/{controller}/{action}/{AccountId}/{UserId}",
            defaults: new { AccountId = RouteParameter.Optional, UserId = RouteParameter.Optional }
       );
    }
}

public class DigitalLoanJacketController : ApiController
{
    [ActionName("Upload")]
    [HttpPost]
    public string Post(long? parmAccountId, long? parmUserId, Foo parmFoo)
    {
    }
}

//JQUery...
var jsonRequest = { "Id": 3, "Name": "Scott Fletcher"};

$.ajax({
    type: "POST",
    async: false, /*false, //This need to be synchronous to the client can wait for a webserver response...*/
    url: "https://localhost:44301/WebApi/Member/DigitalLoanJacket/Upload/e/83",
    data: JSON.stringify(jsonRequest),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (parmData, parmTextStatus, parmXmlHttpRequest) {
        alert("AjaxStatus: " + parmTextStatus + "\nReadyState - " + parmXmlHttpRequest.readyState + "\nStatus: " + parmXmlHttpRequest.status + "\nStatusText: " + parmXmlHttpRequest.statusText + "\nResponseText: " + parmXmlHttpRequest.responseText);
    },
    error: function (parmXmlHttpRequest, parmTextStatus, parmErrorThrown) {
        alert("AjaxStatus: " + parmTextStatus + "\nReadyState - " + parmXmlHttpRequest.readyState + "\nStatus: " + parmXmlHttpRequest.status + "\nStatusText: " + parmXmlHttpRequest.statusText + "\nResponseText: " + parmXmlHttpRequest.responseText);
    }
});

Upvotes: 0

Views: 586

Answers (2)

Vikram Babu Nagineni
Vikram Babu Nagineni

Reputation: 3549

The basic problem with your Post methd is, the parmAccountId and parmUserId would never get values from url. Because the accountId, UserId in the route template are different from parmAccountId,parmUserId in the post method. So, model binding will fail here, as it fills parameters by matching names.

Change parameter names in Post method. It would work.

Public string Post(long? accountId, long? userId, Foo parmFoo)
{

}

Model binding fills the method parameters by matching names.

This is the request flow in Web Api.

  1. The routing mechanism fills the placeholders in route template from the url.
  2. Next it matches action in controller, by type of request(Get, Post,Put...) and method parameters.
  3. Next, model binding comes into picture and fills the method parameters by taking values from three places.They are route parameters, query string and request body.

Here model binding fills first two parameters(accountid, userId) in method from route parameters, and last parameter(Foo) from request body. Model binding fails to fill the first two parameters, because names does not match.

Upvotes: 1

ntl
ntl

Reputation: 1299

UPDATED according to comment:

Try to change you action declaration to:

public class DigitalLoanJacketController : ApiController
{
    [ActionName("Upload")]
    [HttpPost]
    public string Post(Foo parmFoo, long? parmAccountId = 0, long? parmUserId = 0)
    {
    }
}

or

public class DigitalLoanJacketController : ApiController
{
    [ActionName("Upload")]
    [HttpPost]
    public string Post(Foo parmFoo, long? parmAccountId = null, long? parmUserId = null)
    {
    }
}

Upvotes: 1

Related Questions