I have a web api controller and two GET methods:
public class ImagesController : ApiController {
[HttpGet]
public HttpResponseMessage GetImages() { }
[HttpGet]
public HttpResponseMessage Download([FromUri]int[] ids) { }
}
Why I'm getting multiple actions found error, when trying to reach /api/Images, why both actions are the same?
When you created controller, you have assigned HttpGet to two different methods. Making that you have confused web server when it tries to process your request. Since you are sending GET verb to the controller it self, instead directly to the method, web server can not determinate what method should be invoked.
You can try with /api/Images/GetImages in order to directly hit a method, or remove one of listed.
If you see the Web API feature it work for the selected httm methods like GET,PUT,POST,DELETE.
So if you create two action method with same name it will give error. To avoid this error you have to redefine the DefaultAPI path in route.config file.
Change it to
API/{controller}.....
After changing this acces your API from browser like
Or
Mark as a answer if this resolve your issue.
Related
I am working on a project which have scenario to redirect to httppost method from another controller which have a httpget method. Can you guys suggest me a good approach to achieve it?
Example is given below
ControllerA :
[HttpPost]
[Route("Student/InsertData", Name = "InsertData")]
[RequiredQueryStringKeys("SystemId", "IncidentDt")]
public IHttpActionResult InsertData([FromBody] StudentDetailRequest request)
{
//Code
}
Controller B:
[HttpGet]
[Route("Student/GetDetail")]
[RequiredQueryStringKeys("SystemId", "IncidentDt", "Cd")]
public IHttpActionResult GetDetail()
{
------- Need to call ControllerA POST method here
}
NOTE: My requirement is to reroute Student/GetDetail to Student/InsertData. If User hit Student/GetDetail then it should redirect to Student/InsertData.
If you have problems like this one, then you need to think about refactoring that. For example, you can write some UseCases, and just from your methods call that UseCase scenario. Try to write whole logic out of the controllers, then you will be able to reuse that again, instead of logic inside of methods in controller just try to handle request and call that UseCase what you need.
With this logic, you will also have problems when you want to call that POST method because he required some model, and you don't have it when you first call your GET method.
I've come to some strange behaviour using web api. I'm using attribute routing, and making post on server.
Controller:
[Route("names")]
public ResultDTO SaveData(SomeDTO dto)
{
//somecode
...
}
and i'm calling it
$http.post('/api/mycontroller/names', $scope.model.dto).success(function
(data) { ...
It's working. However, if I rename my method
[Route("names")]
public ResultDTO GetData(SomeDTO dto)
{
//somecode
...
}
it's not working and I get HTTP 405 error The page you are looking for cannot be displayed because an invalid method (HTTP verb) was used to attempt access,
However it's working if I change calling from $http.post to $http.get
Obviously, I won't name my method starting with GetSomeMethod if I'm posting data, but I'm curious, shouldn't defined route
[Route("names")]
work with $http.post, no matter how I actually call method that will handle that post? More specific, why $http.post won't work if I named my method GetSomething, but it will if I change method name to, for example, GotSomething or SaveSomething?
Try to add route attribute
[HttpPost]
and then you can name your action as you wish.
Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with Get..., such as GetContact or GetAllContacts. This convention applies only to GET, POST, PUT, and DELETE methods.
See more here
Use proper verbs for $http.post(***) - [HttpPost] and for $http.get(***) - [HttpGet]
I am building an API. But I receive the following error.
The requested resource does not support http method 'GET'
My request is a HTTP PUT and I'm trying to update my database. I have searched for many days but I can't find an answer. Below is my request code. Please help me. Thanks in advance.
request
Code in Controller
[HttpPut]
public void CGNATObjUpdate(int ID)
{
Library.Instances.Value.CGNATObjUpdate(ID);
}
You need to send PUT request aswell. [HttpPut] Allows your method to be triggered for PutRequests only, but in your example you just put link into browser and this simple GET request. Try to use something like Postman to send correct request.
Another way is to check that your controller alows to trigger action by name, for this you need to configure routing for your controller. Just set
[Route("api/[controller]/[action]")]
public class CGNATUpdateApiController : Controller
{
}
Now you can call Action by name, otherwise you will not be able to call Controller action by it`s name, and you need to call Controller:
/api/CGNATUpdateApi?ID=3
just with correct method (PUT) and it will call first PUT method in controller.
Why this doesn't work? I get error: System.InvalidOperationException: Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.
public class ConfigUpdateController: ApiController
{
[HttpPut]
[Route("api/device/{serial}/config")]
public IHttpActionResult Update(
[FromUri] string serial,
[FromBody] Configuration configuration)
{
}
}
public class ConfigQueryController: ApiController
{
[HttpGet]
[Route("api/device/{serial}/config")]
public IHttpActionResult Get(
[FromUri] string serial)
{
}
}
The reason why i want to have methods for same resource in separate controllers is decoupling queries from commands.
EDIT
To be honest, it's ample code to illustrate my problem, so please don't bother commenting controllers naming ect. It's not important in context of my question.
EDIT 2
I've found here web-api overview thet routing has 3 phases:
Routing has three main phases:
Matching the URI to a route template.
Selecting a controller.
Selecting an action.
So it seems this does not work because controller can't be resolved and method verb (PUT, GET) are not even checked? O_o
Read the error carefully, then look at your attribute routing. You have identical URLs for two different actions.
Program would have no idea which action to execute.
use [FromRoute] instead of [FromUri] annotations
I want to be able to take over the 404 response from web api (iis) when the resource does not exist.
I have done my research and came across only one solution that made this work, but i am not sure how "safe" it is since the "routeTemplate" is just {*url}
This post is kinda to ask for help and explanation.
My App uses MVC and WebAPI... would this template affect MVC as well?
Is there a way to add "api" with {*url} in the template? (to make sure only requests with ".../api/..." get affected)
config.Routes.MapHttpRoute("Error404", "{*url}", new { controller = "Error", action = "Handle404" });
Has anyone come across a cleaner way of doing this and handling 404 in web api?
EDIT 1
The above code DOES affect my MVC routes.
How can i add "api" to "{*url}"?... if tried many different ways and no dice.
Had the exact same issue. After some research and trial and error, I was able to find a working solution.
I went with a RoutePrefix solution and I tried to implement something similar to how the MVC controllers used HandleUnknownAction in a base controller.
With the help from this post: .NET WebAPI Attribute Routing and inheritance to allow for route inheritance, I created a base controller for my web APIs with a HandleUnknownAction method like this:
public abstract class WebApiControllerBase : ApiController {
[Route("{*actionName}")]
[AcceptVerbs("GET", "POST", "PUT", "DELETE")]//Include what ever methods you want to handle
[AllowAnonymous]//So I can use it on authenticated controllers
[ApiExplorerSettings(IgnoreApi = true)]//To hide this method from helpers
public virtual HttpResponseMessage HandleUnknownAction(string actionName) {
var status = HttpStatusCode.NotFound;
//This is custom code to create my response content
//....
var message = status.ToString().FormatCamelCase();
var content = DependencyService
.Get<IResponseEnvelopeFactory>()
.CreateWithOnlyMetadata(status, message);
//....
return Request.CreateResponse(status, content);
}
}
If you don't want to go down the inheritance path, you can always put the method directly into the controller you want to apply the functionality on.
This allows me to use route prefixes that handle custom not found messages that pertain to specific controllers as I have both back-office and public public facing APIs.
If a URL does not apply to an ApiController the default Error controller will handle the not found as usual.