Not able to find Web API route? - c#

I’m struggling to figure out why I can’t get to an API end point. I’m building a Web API that will be calling another local API and from everything I see it should be getting to the end point and I’m looking for any ideas.
This is the code in the originating API. I’m using RestSharp to make the call.
string jsonToSend = JsonConvert.SerializeObject(m);
var request = new RestRequest("CheckForDuplicateID", Method.POST);
request.AddParameter("application/json; charset=utf-8", jsonToSend, ParameterType.RequestBody);
request.RequestFormat = DataFormat.Json;
request.AddParameter("CandidateID", m.CandidateID);
request.AddParameter("FirstName", m.FirstName);
request.AddParameter("LastName", m.LastName);
var client = new RestClient("http://localhost:60077/api/IDM/");
var content = client.Execute(request).Content;
This is the end point in the secondary API where I'm trying to get to.
[HttpPost]
public static DuplicateCheck CheckForDuplicateID([FromBody] DuplicateCheck m)
{
....code
}
This is my RouteConfig.cs file. I've tried both routes and neither one works.
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
);
}
When I fire up the secondary API locally it is running on localhost:60077 which I hard coded above. The name of my controller is IDMController and this is the message I get but the URL looks correct to me.
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:60077/api/IDM/CheckForDuplicateID'.","MessageDetail":"No type was found that matches the controller named 'IDM'."}

Actions must be instance members of the ApiController, not static.
[HttpPost]
public DuplicateCheck CheckForDuplicateID([FromBody] DuplicateCheck m) {
....code
}
Since attribute routing is enabled with
config.MapHttpAttributeRoutes();
consider using attribute routing on the API controller to get the desired behavior
[RoutePrefix("api/IDM")]
public class IDMController : ApiController {
//...
//POST api/IDM/CheckForDuplicateID
[HttpPost]
[Route("CheckForDuplicateID")]
public DuplicateCheck CheckForDuplicateID([FromBody] DuplicateCheck m) {
....code
}
}
Reference Attribute Routing in ASP.NET Web API 2

Related

ASP.NET Web API - The requested resource does not support http method 'GET'

I am make POST call into my Web API using Postman. I get the error: "The requested resource does not support http method 'GET'."
I am not making a GET call. If I do call one of my GET methods, it works fine and returns the expected result.
My controller class:
[RoutePrefix("api/login")]
public class LoginController : ApiController
{
ModelContext db = new ModelContext();
[HttpPost]
[Route("validate")]
public HttpResponseMessage Validate([FromBody] LoginViewModel login)
{
try
{
var message = Request.CreateResponse(HttpStatusCode.OK);
return message;
}
catch (Exception ex)
{
var message = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
return message;
}
}
}
I have the Web API running locally and call with this URL:
http://localhost:44303/api/login/validate
This url returns:
<Error>
<Message>
The requested resource does not support http method 'GET'.
</Message>
</Error>
My routing in WebApiConfig.cs
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
While this controller message returns HttpResponseMessage, I have tested by changing the response to "string" and just returning a string value, but I get the same error.
I have read through so many SO posts but none appear to fix my issue. I am at a total loss to explain this behavior. I appreciate any ideas.
EDIT
I have tested GETs in other controllers and they are returning data as expected.
EDIT FOR CONTEXT 6/3/2020
This method in the default ValuesController works:
[Route("api/values")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
These 2 methods in the SAME controller do not work:
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
EDIT #2 6/3/2020
Now all of my api methods are working for the default ValuesController. I do not know why.
My custom POST methods in other controllers such as the Post method above are still not working. Here is my current WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "Api_Get",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional, action = "Get" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
);
config.Routes.MapHttpRoute(
name: "Api_Post",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional, action = "Post" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
);
}
I do not have any middleware or special routing that I know of. Any exception handling would be simple try-catch.
I am trying to use attribute routing vs convention but that seems to be an issue.
You don't need to create a route table by HttpMethods because you have [HttpPost] attribute.
Replace all config.Routes.MapHttpRoute by
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
It's preferable to use Attribute Routing for Web API project. It will reduce the chances of errors because in RouteConfig class there can be any mistake while creating a new custom route. Also, you don’t have to take care of the routing flow i.e, from most specific to most general. All here is the attribute you use the action method.

Routes and the dreaded 405

I've got a simple web API that registers on one route. At the moment I've got two because only one of them does what I need.
My application only has one controller and one Post method in that Controller. I've registered a single Route which always returns a 405 (method not allowed)
The two routes are configured in the RouteConfig.cs:
routes.MapHttpRoute(
name: "app-events",
routeTemplate: "events",
defaults: new { controller = "Events" },
handler: new GZipToJsonHandler(GlobalConfiguration.Configuration),
constraints: null
);
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
The Controller method is essentially this...
public class EventsController : ApiController
{
public EventsController()
{
_sender = new EventHubSender();
}
public async Task<HttpResponseMessage> Post(HttpRequestMessage requestMessage)
{
// doing fun stuff here…
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
If I only configure the first route and post a request to http://devbox/events I will get a 405. However, if I add the second, default, route, and post to http://devbox/api/events I get back my expected 201.
With both routes configured at the same time, the same pattern, the route explicitly bound to the Controller receives a post request and fails with a 405, but the other URL will work.
I've spent a long time looking around before conceding to ask the question. Most things I read have a lot to do with Webdav and I think I've followed every one of them to fix the issue. I am not very experienced with this stack, so nothing is very obvious to me.
You mentioned RouteConfig File. This is used for configuring the MVC routes not Web API routes.
So it would appear you are configuring the wrong file which would explain why the api/... path works as it is probably mapping to the default configuration in WebApiConfig.Register, which would look like
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
You would need to update that file with the other desired route
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "app-events",
routeTemplate: "events",
defaults: new { controller = "Events" },
handler: new GZipToJsonHandler(GlobalConfiguration.Configuration),
constraints: null
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Web API routes are usually registered before MVC routes which explains why it was not working with your original configuration.
You should also adorn the action with the respective Http{Verb} attribute.
In this case HttpPost so that the route table knows how to handle POST requests that match the route template.
[HttpPost]
public async Task<IHttpActionResult> Post() {
var requestMessage = this.Request;
// async doing fun stuff here….
return OK();
}

Unable to connect to ASP.NET web api when I add additional parameters

I am trying understand Web Api 2 (MVC project in Visual Studio).
The method is
[HttpPost]
public string Post(int id, string e, bool o)
///code removed
Using Postman, I can query using Post and the path http://localhost:62093/api/Demo/5. This works and returns the expected value.
Now I want to add more parameters and this is where it goes wrong!
I have updated my method to
[HttpPost]
public string Post(int id, string e, bool o)
Now when I attempt to query this using (again) Post and the path http://localhost:62093/api/Demo/5 I see
"Message": "The requested resource does not support http method 'POST'."
I then try to change the URL, so when I use Post and the new path http://localhost:62093/api/Demo/5/a/false I see an HTML file response of
The resource cannot be found
This has been mentioned before on Stackoverflow and from what I've understood is about the URL being 'incorrect'
Thinking this could be an issue with routes I updated mine to
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{s}/{o}",
defaults: new { id = RouteParameter.Optional, s = RouteParameter.Optional, o = RouteParameter.Optional }
);
But the same issue persists. I'm not sure what I've done wrong.
This is a routing issue. you have not configured your routes correctly.
First let us update the WebApiConfig.cs file
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Now with that configured I would suggest using Attribute routing
public class DemoController : ApiController {
[HttpPost]
[Route("api/Demo/{id:int}/{e}/{o:bool}")] //Matches POST api/Demo/5/a/false
public IHttpActionResult Post(int id, string e, bool o) {
return Ok();
}
}
I would finally suggest reading up on Attribute Routing in ASP.NET Web API 2 to get a better understanding on how to properly route to your API controllers

Api Controller Method not calls

I have MVC project, I have added one API controller.in this API controller I have created methods in it.but when I am trying to call this API from postman or localhost with "http://localhost:10133/api/BedfordBrownstoneApi/GetAgentId?username=dgsdgsdgsd&password=sdgsdgs" Url its gives following response.
{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:10133/api/BedfordBrownstoneApi/GetAgentId?username=dgsdgsdgsd&password=sdgsdgs'.",
"MessageDetail": "No type was found that matches the controller named 'BedfordBrownstoneApi'."
}
My API controller is like following.
public class BedfordBrownstoneApi : ApiController
{
// GET api/<controller>
public int GetAgentId(string username,string password)
{
DataContext db = new DataContext();
var data = db.Set<AgentLogin>().Where(a => a.UserName==username && a.Password==password).SingleOrDefault();
return data.AgentId;
}
}
}
My WebApiConfig class is like following.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "GetAgentId" }
);
}
}
Check Below Question that that similar problem as yours.
Check Accepted Answer of 'Benoit74B'. It clearly explains problem in details. Actual problem is regarding parameters you are passing -
"No HTTP resource was found that matches the request URI" here?
Remove "API" from controller name BedfordBrownstoneApi.
Change it from
http://localhost:10133/api/BedfordBrownstoneApi/GetAgentId?username=dgsdgsdgsd&password=sdgsdgs
to
http://localhost:10133/api/BedfordBrownstone/GetAgentId?username=dgsdgsdgsd&password=sdgsdgs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "GetAgentId",id = RouteParameter.Optional }
);
add Id parameter in your routeTemplete in webapiconfig.
Have you enabled attribute routing in api config? config.MapHttpAttributeRoutes();
With your current route, you should hit it via query string "http://localhost:10133/api/BedfordBrownstoneApi/GetAgentId?username=dgsdgsdgsd&password=sdgsdgs" and decorate the parameters with [FromUri]
[HttpGet]
[Route("api/BedfordBrownstoneApi/GetAgentId/")]
public int GetAgentId(string username,string password)
{
//api stuff
}
or to hit the api via route parameters - http://localhost:10133/api/BedfordBrownstoneApi/GetAgentId/yourusername/yourpassword
[HttpGet]
[Route("api/BedfordBrownstoneApi/GetAgentId/{username}/{password}")]
public int GetAgentId(string username,string password)
{
//api stuff
}
Hope this helps you. Thanks!!
There are two issues.
Controller name - Change the name, add Controller in the name (BedfordBrownstoneApiController).
You missed calling 'config.MapHttpAttributeRoutes()' in Register function.
Please update your 'Register' function in 'WebApiConfig' as below.
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "GetAgentId" }
);
}
I have just change my code to following and now its work.
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "BedfordBrownstoneApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "GetAgentId" }
);
}

Attribute routing to two similar actions on the same controller

I have a controller with the two following actions:
[Route("api/organization/{orgId}/person/{ver}/getmanagers", Name = "GetManagers")]
public HttpResponseMessage GetManagers(Guid orgId, int ver)
{ .... }
[Route("api/organization/{orgId}/person/{ver}/getpersons", Name = "GetPersons")]
public HttpResponseMessage GetPersons(Guid orgId, int ver)
{ .... }
When i make a get request to the following url:
...api/organization/2473ce5e-42e6-449f-9528-a29000921ded/person/1/getpersons
I get this error:
Multiple actions were found that match the request.
Both GetManagers and GetPersons match. Why is this? Why does the "/getpersons" at the end of my url not matter? What can i do to make them separately identifiable?
In Web API the request are mapped to the actions based on HTTP verbs.Change the Default route in WebApiConfig.cs and ensure that you have
//Required for Attribute based routing
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional }
);
hope this helps.

Categories

Resources