5

I have the following code, but the request ends (Foo() / Bar()) always in No action was found on the controller 'Device' that matches the request.

I've a custom route in my WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new {id = RouteParameter.Optional}
    );

My ASP.NET WebAPI controller:

[HttpPost]
public void UpdateToken(string newToken)
{
    _deviceHandler.UpdateToken(newToken);
}

To query my ASP.NET WebAPI I'm using RestSharp.

private static void Send(string resource, Method method, object payload)
{
    var client = new RestClient(baseUrl);
    var request = new RestRequest(resource, method);
    request.XmlSerializer = new JsonSerializer();
    request.RequestFormat = DataFormat.Json;
    request.AddBody(payload);

    var response = client.Execute(request);
    // ... handling response (exceptions, errors, ...)
}

public void Foo()
{
    var newToken = "1234567890";
    Send("/api/device/updatetoken", RestSharp.Method.POST, newToken );
}

public void Bar()
{
    var newToken = new { newToken = "1234567890" };
    Send("/api/device/updatetoken", RestSharp.Method.POST, newToken );
}

The only way to avoid this error is creating a wrapper class with a property (get;set;) in it which has the name of the controller argument (newToken).

I have a lot of requests which sends one or two custom strings (undefined length) as post (get is limited in length). But to create for each scenario a wrapper implementation is real overhead! I'm looking for another way to go.

PS: I hope I haven't made any mistakes by simplifying the scenario =)

1 Answer 1

12

Primitives are by default bound from the URI. If you want a primitive to come from the body, you should use the [FromBody] attribute like this:

[HttpPost]
public void UpdateToken([FromBody] string newToken)
{
    _deviceHandler.UpdateToken(newToken);
}

The string will then be deserialized using the appropriate formatter. If it's JSON, the request body should look like this:

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

3 Comments

Thank you, just the missing [FromBody]-Attribute was the fault.
This just saved my night. I was banging my head wondering why this one particular route was getting a 404. It takes an int where the rest of my routes take a reference type. Adding the [FromBody] attribute did the trick.
1 for saving my half day of my life, half already wasted on it thanks

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.