0
votes

I have two methods named Post* in my Web API server:

Controller

public void PostNoBills(int accountid, string name)
{
    duckbillsRepository.Post(accountid, name);
}

public void Post(NoBills noBills)
{
    duckbillsRepository.Post(noBills); 
}

Repository:

public void PostNoBills(int accountid, string name)
{
    int maxId = noBills.Max(d => d.Id);
    NoBills duckbill = new NoBills();
    duckbill.Id = maxId + 1;
    duckbill.AccountId = accountid;
    duckbill.Name = name;
    NoBills.Add(duckbill);
}

public void Post(NoBills noBills)
{
    int maxId = NoBills.Max(d => d.Id);
    NoBills.Id = maxId + 1;
    NoBills.Add(noBills);
}

So when I call a Post method from the client, passing an int and a string:

string uri = String.Format("http://platypi:28642/api/NoBills/{0}/{1}", onAccountOfWally, moniker);
var request = System.Net.WebRequest.Create(uri);
request.Method = "POST";
string postData = String.Format("{0}/{1}", onAccountOfWally, moniker);
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/json";
request.ContentLength = byteArray.Length;
using (var requestStream = request.GetRequestStream())
{
    requestStream.Write(byteArray, 0, byteArray.Length);
}

using (var response = request.GetResponse())

...I expect the method with the "int accountid, string name" arguments to be the one that gets called, but it's not - the other one (the one accepting "NoBills noBills" as its argument) is. Why?

(BTW, I'm not at all sure the client code above is "right")

UPDATE

In acquiescence to the invitation/demand of Kian Challa, here is WebApiConfig:

public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

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

    config.Routes.MapHttpRoute(
        name: "DefaultApiWithParameters",
        routeTemplate: "api/{controller}/{ID}/{CountToFetch}"
        //defaults: new { ID = RouteParameter.Optional, CountToFetch = RouteParameter.Optional }
    );

    config.Routes.MapHttpRoute(
        name: "DefaultApiWith3Parameters",
        routeTemplate: "api/{controller}/{ID}/{packSize}/{CountToFetch}"
        //defaults: new { ID = RouteParameter.Optional, packSize = RouteParameter.Optional, CountToFetch = RouteParameter.Optional }
    );

As a bonus, here is RouteConfig.cs:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}   

...and the perhaps pertinent piece of Global.asax.cs:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

UPDATE 2

In reply to Kian Challa's comment below containing "on the action public void PostNoBills(int accountid, string name)"

Okay, so that is (if you're talking about the Controller code):

public void PostNoBills(int accountid, string name)
{
    duckbillsRepository.Post(accountid, name);
}

How should it be changed with:

[Route("api/nobills/{accountid}/{name}")]

? You imply that I need add nothing to WebApiConfig ("...instead of creating a new route in WebApiConfig.cs...") so...precisely what do I need to add, and where do I need to add it?

1
action selection depends on current request's route values and available actions and their parameters...so could you share how your routes look like?Kiran Challa
Do you mean what's in WebApiConfig? What I find odd is that it does select one of the methods, but the "wrong" one.B. Clay Shannon
if all your webapi routes are defined in WebApiConfig, then yes..Kiran Challa
Okay, I updated my post with the contents of WebApiConfig.B. Clay Shannon

1 Answers

1
votes

Your action's FromUri parameters can be bound to route data or query string values with names accountid and name in this case...since none of your routes have these route variable names Web API is unable to provide any route data with names like accountid and name and hence your expected action isn't getting called...to resolve this issue, instead of creating a new route in WebApiConfig.cs, why not use attribute routing as you seem to be already calling that...Example: [Route("api/nobills/{accountid}/{name}")]