Why is it that "No HTTP resource was found that matches the request URI" here?

C#ControllerPostmanRequest UriHttp Post-Vars

C# Problem Overview


I have code in my controller like so:

[Route("api/deliveryitems/InsertIntoPPTData/{stringifiedRecord}")]

...and I'm calling it via Postman like so:

    http://localhost:21609/api/deliveryitems/InsertIntoPPTData?
stringifiedRecord=serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2

...but get:

{
Message: "No HTTP resource was found that matches the request URI     
'http://localhost:21609/api/deliveryitems/InsertIntoPPTData?   stringifiedRecord=serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2'."
MessageDetail: "No type was found that matches the controller named 'deliveryitems'."
}

Other REST methods that are created and called in the same way are found just fine - why not this one? The only thing it does not have in common with the others is that it is a HttpPost, whereas the others are HttpGet. Does that make that much of a difference? I am selecting "Post" from the dropdown in Postman when trying to call this REST method.

UPDATE

Yes, it apparently has nothing to do with it being a Post and passing args in the URI, because I'm getting the same thing now with an HttpGet method:

{
Message: "No HTTP resource was found that matches the request URI     
'http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12'."
MessageDetail: "No action was found on the controller 'Department' that matches the request."
}

I'm calling it from postman like so:

http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12

...and it does indeed appear in my controller:

[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
    return CCRService.GetNDepartmentsFromID(FirstId, CountToFetch);
}

UPDATE 2

I thought I was about to solve it when I changed this code:

String.Format("api/department/getndeptsfromid/{0}/{1}", FirstId, CountToFetch)

...to this:

String.Format("api/department/getndeptsfromid?firstId={0}&countToFetch={1}", FirstId, CountToFetch)

...but I still get the same err msg...

UPDATE 3

I find that this also is not working:

http://localhost:21609/api/delivery/invnumbyid?ID=33

...and so there is a definite pattern. EVERY REST API call I make that contains args/params fails in this same way; all of the others (http://localhost:21609/api/deliveries/Count, http://localhost:21609/api/deliveryitems/count, http://localhost:21609/api/department/getall) work just fine. IOW, if there are no args in the URI, the method is discovered. If there are args, it is not.

So apparently there's either something wrong with how I'm passing the args/vals in the URI (appending "?=" in the case of a single arg and, in the case of two args "?=&=") and/or there's something wrong with how I set up the routing. Specifically, this style works:

[Route("api/Deliveries/Count")]

...whereas this style does not:

[Route("api/delivery/invnumbyid/{ID}")]

I will bountify this question ASAP - 50 points to the untangler of this Gordiesque knot, and 100 if it's answered today (prior to the setting up of the bounty).

UPDATE 4

I changed the routing to include the data type of the arg so that this:

[Route("api/delivery/invnumbyid/{ID}")]

-became this:

[Route("api/delivery/invnumbyid/{ID:int}")]"

But it still failed, growling:

{
Message: "No HTTP resource was found that matches the request URI 
'http://localhost:21609/api/delivery/invnumbyid?ID=45'."
MessageDetail: "No action was found on the controller 'Delivery' that matches the request."
}

Then, "on a lark," I tried entering this into Postman:

http://localhost:21609/api/delivery/invnumbyid/45

...and it worked! (I had been thinking it needed to be "http://localhost:21609/api/delivery/invnumbyid?ID=45")

But a similar attempt in Postman:

http://localhost:21609/api/department/getndeptsfromid/2/12/

...continues to fail with "No value given for one or more required parameters." even though this is hit:

[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
    return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}

...and the args to GetNDepartmentsFromID() has the expected vals (2 and 12)

Even worse/weirder is the result I get with "http://localhost:21609/api/deliveryitems/InsertIntoPPTData/serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2" now:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
    xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>IIS 8.0 Detailed Error - 404.0 - Not Found</title>
        <style type="text/css">
            <!-- 
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;} 
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;} 
.config_source code{font-size:.8em;color:#000000;} 
pre{margin:0;font-size:1.4em;word-wrap:break-word;} 
ul,ol{margin:10px 0 10px 5px;} 
ul.first,ol.first{margin-top:5px;} 
fieldset{padding:0 15px 10px 15px;word-break:break-all;} 
.summary-container fieldset{padding-bottom:5px;margin-top:4px;} 
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;} 
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px; 
font-weight:bold;font-size:1em;} 
a:link,a:visited{color:#007EFF;font-weight:bold;} 
a:hover{text-decoration:none;} 
h1{font-size:2.4em;margin:0;color:#FFF;} 
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;} 
h4{font-size:1.2em;margin:10px 0 5px 0; 
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif; 
 color:#FFF;background-color:#5C87B2; 
}#content{margin:0 0 0 2%;position:relative;} 
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;} 
.content-container p{margin:0 0 10px 0; 
}#details-left{width:35%;float:left;margin-right:2%; 
}#details-right{width:63%;float:left;overflow:hidden; 
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF; 
 background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal; 
 font-size:1em;color:#FFF;text-align:right; 
}#server_version p{margin:5px 0;} 
table{margin:4px 0 4px 0;width:100%;border:none;} 
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;} 
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;} 
thead th{background-color:#ebebeb;width:25%; 
}#details-right th{width:20%;} 
table tr.alt td,table tr.alt th{} 
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;} 
.clear{clear:both;} 
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;} 
-->
        </style>
    </head>
    <body>
        <div id="content">
            <div class="content-container">
                <h3>HTTP Error 404.0 - Not Found</h3>
                <h4>The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.</h4>
            </div>
            <div class="content-container">
                <fieldset>
                    <h4>Most likely causes:</h4>
                    <ul>
                        <li>The directory or file specified does not exist on the Web server.</li>
                        <li>The URL contains a typographical error.</li>
                        <li>A custom filter or module, such as URLScan, restricts access to the file.</li>
                    </ul>
                </fieldset>
            </div>
            <div class="content-container">
                <fieldset>
                    <h4>Things you can try:</h4>
                    <ul>
                        <li>Create the content on the Web server.</li>
                        <li>Review the browser URL.</li>
                        <li>Check the failed request tracing log and see which module is calling SetStatus. For more information, click 
                            <a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>. 
                        </li>
                    </ul>
                </fieldset>
            </div>
            <div class="content-container">
                <fieldset>
                    <h4>Detailed Error Information:</h4>
                    <div id="details-left">
                        <table border="0" cellpadding="0" cellspacing="0">
                            <tr class="alt">
                                <th>Module</th>
                                <td>&nbsp;&nbsp;&nbsp;IIS Web Core</td>
                            </tr>
                            <tr>
                                <th>Notification</th>
                                <td>&nbsp;&nbsp;&nbsp;MapRequestHandler</td>
                            </tr>
                            <tr class="alt">
                                <th>Handler</th>
                                <td>&nbsp;&nbsp;&nbsp;StaticFile</td>
                            </tr>
                            <tr>
                                <th>Error Code</th>
                                <td>&nbsp;&nbsp;&nbsp;0x80070002</td>
                            </tr>
                        </table>
                    </div>
                    <div id="details-right">
                        <table border="0" cellpadding="0" cellspacing="0">
                            <tr class="alt">
                                <th>Requested URL</th>
                                <td>&nbsp;&nbsp;&nbsp;http://localhost:21609/api/deliveryitems/InsertIntoPPTData/serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2</td>
                            </tr>
                            <tr>
                                <th>Physical Path</th>
                                <td>&nbsp;&nbsp;&nbsp;C:\project\git\CStore\HHS.API\api\deliveryitems\InsertIntoPPTData\serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2</td>
                            </tr>
                            <tr class="alt">
                                <th>Logon Method</th>
                                <td>&nbsp;&nbsp;&nbsp;Anonymous</td>
                            </tr>
                            <tr>
                                <th>Logon User</th>
                                <td>&nbsp;&nbsp;&nbsp;Anonymous</td>
                            </tr>
                            <tr class="alt">
                                <th>Request Tracing Directory</th>
                                <td>&nbsp;&nbsp;&nbsp;C:\Users\clay\Documents\IISExpress\TraceLogFiles\HHS.API</td>
                            </tr>
                        </table>
                        <div class="clear"></div>
                    </div>
                </fieldset>
            </div>
            <div class="content-container">
                <fieldset>
                    <h4>More Information:</h4> 
  This error means that the file or directory does not exist on the server. Create the file or directory and try the request again. 
  
                    <p>
                        <a href="http://go.microsoft.com/fwlink/?LinkID=62293&amp;IIS70Error=404,0,0x80070002,7601">View more information &raquo;</a>
                    </p>
                </fieldset>
            </div>
        </div>
    </body>
</html> 

¡Que demonios!

I sadly smilingly remember that there is always one more gargoyle hiding behind the rustling curtain (where Robinson Jeffers and Edgar Allen Poe are seemingly wrestling). Palely loitering...

UPDATE 5

Okay, here it is stated differently:

From Postman, if I use this URL:

http://localhost:21609/api/department/getndeptsfromid/2/12/

I make it into this method:

[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
    return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}

...where the value of FirstId is 2, and the value of CountToFetch is 12 (as I would expect them to be). But then, Postman sends back my package with the notation, "500 No value given for one or more required parameters."

¡Que demonios! Both parameters were obviously passed!

If I use a URI that would seem more correct:

http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12

I get:

{
Message: "No HTTP resource was found that matches the request URI   
'http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12'."
MessageDetail: "No action was found on the controller 'Department' that matches the request."
}

Yet this is the route that I've provided:

[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]

...and so I would say that I did, in fact, provide a matching action on the controller.And, BTW, if I just enter this as the URI into Postman:

http://localhost:21609/api/department/getndeptsfromid

...and then use Postman's "URL Parameter Key / Value" interface to add those, it generates the exact same URL as above, as can be seen here:

enter image description here

...and with the exact same result.

I can only say it again (pardon my "Las Uvas de la Ira"-inspired Spanish): ¡Que demonios!

C# Solutions


Solution 1 - C#

Your problems have nothing to do with POST/GET but only with how you specify parameters in RouteAttribute. To ensure this, I added support for both verbs in my samples.

Let's go back to two very simple working examples.

[Route("api/deliveryitems/{anyString}")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsOne(string anyString)
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, anyString);
}

And

[Route("api/deliveryitems")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsTwo(string anyString = "default")
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, anyString);
}

The first sample says that the "anyString" is a path segment parameter (part of the URL).

First sample example URL is:

  • localhost:xxx/api/deliveryItems/dkjd;dslkf;dfk;kkklm;oeop
    • returns "dkjd;dslkf;dfk;kkklm;oeop"

The second sample says that the "anyString" is a query string parameter (optional here since a default value has been provided, but you can make it non-optional by simply removing the default value).

Second sample examples URL are:

  • localhost:xxx/api/deliveryItems?anyString=dkjd;dslkf;dfk;kkklm;oeop
    • returns "dkjd;dslkf;dfk;kkklm;oeop"
  • localhost:xxx/api/deliveryItems
    • returns "default"

Of course, you can make it even more complex, like with this third sample:

[Route("api/deliveryitems")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsThree(string anyString, string anotherString = "anotherDefault")
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, anyString + "||" + anotherString);
}

Third sample examples URL are:

  • localhost:xxx/api/deliveryItems?anyString=dkjd;dslkf;dfk;kkklm;oeop
    • returns "dkjd;dslkf;dfk;kkklm;oeop||anotherDefault"
  • localhost:xxx/api/deliveryItems
    • returns "No HTTP resource was found that matches the request URI ..." (parameter anyString is mandatory)
  • localhost:xxx/api/deliveryItems?anotherString=bluberb&anyString=dkjd;dslkf;dfk;kkklm;oeop
    • returns "dkjd;dslkf;dfk;kkklm;oeop||bluberb"
    • note that the parameters have been reversed, which does not matter, this is not possible with "URL-style" of first example

When should you use path segment or query parameters? Some advice has already been given here: https://stackoverflow.com/questions/4024271/rest-api-best-practices-where-to-put-parameters

Solution 2 - C#

Try this mate, you can chuck it in the body like so...

    [HttpPost]
    [Route("~/API/ChangeTheNameIfNeeded")]
    public bool SampleCall([FromBody]JObject data)
    {
        var firstName = data["firstName"].ToString();
        var lastName= data["lastName"].ToString();
        var email = data["email"].ToString();
        var obj= data["toLastName"].ToObject<SomeObject>();

        return _someService.DoYourBiz(firstName, lastName, email, obj);
    }

Solution 3 - C#

Have you tried using the [FromUri] attribute when sending parameters over the query string.

Here is an example:

[HttpGet]
[Route("api/department/getndeptsfromid")]
public List<Department> GetNDepartmentsFromID([FromUri]int FirstId, [FromUri] int CountToFetch)
{
    return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}

Include this package at the top also, using System.Web.Http;

Solution 4 - C#

I got the similiar issue, and resolved it by the following. The issue looks not related to the Route definition but definition of the parameters, just need to give it a default value.

----Code with issue: Message: "No HTTP resource was found that matches the request URI

    [HttpGet]
    [Route("students/list")]
    public StudentListResponse GetStudents(int? ClassId, int? GradeId)
    {
       ...
    }

----Code without issue.

    [HttpGet]
    [Route("students/list")]
    public StudentListResponse GetStudents(int? ClassId=null, int? GradeId=null)
    {
       ...
    }

Solution 5 - C#

WebApiConfig.Register(GlobalConfiguration.Configuration); should be on top.

Solution 6 - C#

I had that problem, if you are calling your REST Methods from another Assembly you must be sure that all your references have the same version as your main project references, otherwise will never find your controllers.

Regards.

Solution 7 - C#

You need to map the unique route to specify your parameters as query elements. In RouteConfig.cs (or WebApiConfig.cs) add:

config.Routes.MapHttpRoute(
            name: "MyPagedQuery",
            routeTemplate:     "api/{controller}/{action}/{firstId}/{countToFetch}",
            defaults: new { action = "GetNDepartmentsFromID" }
        );

Solution 8 - C#

Just make sure that the controller name is the same as yours DeliveryController if you renamed it (it will not change automatically!). if you rename the project name too you should delete the reference to this project from the Bin folder. Don't forget to specify the method get or post.

Solution 9 - C#

If it is a GET service, then you need to use it with a GET method, not a POST method. Your problem is a type mismatch. A different example of type mismatch (to put severity into perspective) is trying to assign a string to an integer variable.

Solution 10 - C#

Please check the class you inherited. Whether it is simply Controller or APIController.

By mistake we might create a controller from MVC 5 controller. It should be from Web API Controller.

Solution 11 - C#

Make sure:

  1. the controller name is correctly spelled
  2. has the correct POST/GET directives
  3. you are not missing any parameters in the URL

The last one was what caused me trouble.

Solution 12 - C#

For .net web api, take care, your controller have to Inherit from ApiController, otherwise, you will get this error.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionB. Clay Shannon-B. Crow RavenView Question on Stackoverflow
Solution 1 - C#Benoit74BView Answer on Stackoverflow
Solution 2 - C#Egli BecerraView Answer on Stackoverflow
Solution 3 - C#Kunal MukherjeeView Answer on Stackoverflow
Solution 4 - C#Tom AtGmailView Answer on Stackoverflow
Solution 5 - C#user5430808View Answer on Stackoverflow
Solution 6 - C#Carlos RangelView Answer on Stackoverflow
Solution 7 - C#ComeInView Answer on Stackoverflow
Solution 8 - C#KBTView Answer on Stackoverflow
Solution 9 - C#DarkNinja955View Answer on Stackoverflow
Solution 10 - C#ThriveniView Answer on Stackoverflow
Solution 11 - C#live-loveView Answer on Stackoverflow
Solution 12 - C#dezoxView Answer on Stackoverflow