问题
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> IIS Web Core</td>
</tr>
<tr>
<th>Notification</th>
<td> MapRequestHandler</td>
</tr>
<tr class="alt">
<th>Handler</th>
<td> StaticFile</td>
</tr>
<tr>
<th>Error Code</th>
<td> 0x80070002</td>
</tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt">
<th>Requested URL</th>
<td> 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> 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> Anonymous</td>
</tr>
<tr>
<th>Logon User</th>
<td> Anonymous</td>
</tr>
<tr class="alt">
<th>Request Tracing Directory</th>
<td> 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&IIS70Error=404,0,0x80070002,7601">View more information »</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:
...and with the exact same result.
I can only say it again (pardon my "Las Uvas de la Ira"-inspired Spanish): ¡Que demonios!
回答1:
Your problems have nothing to do with POST/GET but only with how to 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
- return "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
- return "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
- return "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 parameters have been reversed, does not matter, this is not possible with "URL-style" of first example
When should you use path segment or query parameters ? Some advices have already been given here : REST API Best practices: Where to put parameters?
回答2:
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;
回答3:
WebApiConfig.Register(GlobalConfiguration.Configuration); should be on top.
回答4:
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" }
);
回答5:
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.
回答6:
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);
}
回答7:
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.
回答8:
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.
回答9:
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.
来源:https://stackoverflow.com/questions/24769379/why-is-it-that-no-http-resource-was-found-that-matches-the-request-uri-here