Adding custom method to WebAPI - asp.net-web-api

I am new to the WebAPI and I got stuck in a problem. I am using API controller which contains two Get methods. One is used for GetAll while other retrieves data on the basis of ID. Now what I want to do is to implement another get method which takes string and returns records. I have made that method and call that it does not work as my route was default API route which was like:
config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
When I added a new route to call my custom GetMethod:
config.Routes.MapHttpRoute(name: "Custom", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
I was able to call my custom GetMethod but now I lose the restful method with id parameters. How can I use both methods?

Have you tried using your second route only and call as
api/customer/get/1
api/customer/getall/
api/customer/getmethod/one
In the above, customer is the controller name. You have to replace with yours.
Please check whether you have the routes in the webapiconfig.cs file. Please refer this article for more help.

Better not to change routes.
You can use Action Name to differentiate the calls and can add more functions. Take a look at this answer:
How to add custom methods to ASP.NET WebAPI controller?

Related

How can I have controllers with same name but in different folders in Mvc

I have a controller called CarsController that worked fine, but then I created a subfolder in the controllers folder, named it v1 and added another controller also called CarsController. I cannot call the new controller beacuse I get this error..
Multiple types were found that match the controller named
I thought it would help just adding this...
// V1 Route
config.Routes.MapHttpRoute(
name: "DefaultRouteV1",
routeTemplate: "api/v1/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
But it did not, how can I solve this?

Visual Studio Web API: How to change the routing path

I am working on Web Api. By default, it uses the api/{controller}/{id} as a url. I am able to have it to route api/device/{controller}/{id} but this will affect to all Web API route to that path.
But I only want certain controller to be in api/device/{controller}/{id} and the rest will go to another path.
I saw something like RoutePrefix but it doesn't seem to work...
[RoutePrefix (api/data/abc)] where abc is the controller name.
Add the custom route mapping in WebApiConfig.cs file before default route map:
By adding this before, any requests which matches the custom route will be executed, else the other one.
config.Routes.MapHttpRoute(
name: "CustomRoute",
routeTemplate: "api/device/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
If you want to customize the routing with a per controller approach, then you have to use Attribute Routing instead of the standard convention-based routing.
Decorate your controllers with RoutePrefix attribute, and your actions with Route attribute in this way:
[RoutePrefix("api/device/mydevice")]
public class MyDeviceController : ApiController {
[Route("{id}")]
[HttpGet]
public IHttpActionResult Get(int id) {
//DoWork
//...
}
}
And remember to enable attribute routing on the HttpConfiguration object:
config.MapHttpAttributeRoutes();
You may also remove MapHttpRoute method calls if you do not want to allow access to your actions in the standard convention-based way.
More on attribute routing on the official documentation.

Web Api - Swagger documentation error 500

When I access to the swagger url: http://localhost:28483/swagger/ui/index, it generates this error:
500 : undefined http://localhost:28483/swagger/docs/v1
Any ideas?
UPDATED:
See this detail error in firebug:
Not supported by Swagger 2.0: Multiple operations
with path 'api/BimModel' and method 'GET'. See the config setting - \"ResolveConflictingActions\" for
a potential workaround
Swagger might be considering two actions as one operation (like in the case of this common scenario)...
GET api/Products
GET api/Products/{id}
It seems you can use attribute routing to fix this and use these attributes above your actions so swagger will recognize them separately.
[Route("api/Products")]
[Route("api/Products/{id:guid}")]
Have you tried enable this in you swagger config?
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
In the controller, it got two different GET operations and it is disallowed by Swagger.
I suggest to either have only single GET operation for each controller or modify the router in WebApiConfig
I had the same issue when mixing attribute routing with default routes.
When I removed the default route the problem went away. The downside is, without the default route defined, I had to add attribute routing to all my controllers.
So from my WebApiConfig I removed:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
And added attribute routing to my controller:
[Route("Session")] // Added this attribute
public async Task<IHttpActionResult> Get()
...
[Route("Session/{id}")] // Added this attribute
public async Task<IHttpActionResult> Get(int id)
In reality I use a [RoutePrefix("Session")] on my Controller and use [Route("")] on my methods, but the result should be the same.
I was getting this error due to the parameter names not matching between the Attribute Routing statement and the method signature.
[HttpGet("{id}")]
public IActionResult Get(string deviceNumber){
...
After changing "{id}" to "{deviceNumber}" it fixed the error.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);

Actions and QueryString parameters in Web API

I want to have my generic route determine if a query string was passed in the Url like this
http://localhost/query/DailyLogs/1?dateOfLog='1/13/2013'
Here is my current Route definition:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "query/{controller}/{id}",
defaults: new { id = RouteParameter.Optional}
);
I have read some answers that say to add the dateOfLog value as an optional action on the Route defintion:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "query/{controller}/{id}/{dateOfLog}",
defaults: new { id = RouteParameter.Optional,
dateOfLog = RouteParameter.Optional }
);
This does not seem to work, maybe I am doing something wrong, I am not sure.
This is how I am currently handling the problem, but I would like to use the ModelBinding power of the Routing Engine:
var queryValue = Request.RequestUri.ParseQueryString();
string dateOfLog = queryValue["dateOfLog"];
Please tell me how to create a Route definition that will use ModelBinding correctly and map my custom url to the controller's parameters.
In the controller action, just include DateTime dateOfLog as a method parameter and continue to use the query string as it will get mapped just fine, Web API will use the correct method overload if it finds it.

How to do asp.net webapi routing when it comes to custom models?

I am developing an ASP.Net WebApi application and facing some difficulties with routing. I have following code in my WebApi controller.
public class UserRegistrationServiceWebApiController : ApiController
{
[HttpPost]
public void RegisterUser(RegisterUser registerUser)
{
/*Some code here*/
}
[HttpPost]
public void ConfirmUserPassword(UserPasswordConfirmModel userPasswordData)
{
/*Some code here*/
}
}
In my RouteConfig.cs, I have given the routes like this.
routes.MapHttpRoute(
name: "UserRegistrationApi",
routeTemplate: "api/{controller}/{action}/{firstName}/{lastName}/{email}/{phoneNo}/{company}"
);
routes.MapHttpRoute(
name: "UserPasswordConfirmationApi",
routeTemplate: "api/{controller}/{action}/{userId}/{password}"
);
The attributes here (firstName, lastName etc) are getting filled properly from the client-side and I can see them in server-side when I call these two actions separately. But when both actions are in the controller, it says it cannot identify which action to pick. This is obviously because of the custom objects i am filling in the server-side (RegisterUser model and UserPasswordConfirmModel model). So there is a conflict there.
This is because of the routing problem. Appreciate any kind of help.
Thanks in advance.
Actually I found out the problem is with the conflict of two actions in the same controller. If I use these two actions separately they work fine. I do not know how to handle when we have two actions in the same controller like above.
I looked in to custom parameter binding, but I do not think that is the problem since my actions work fine separately.
Thanks.
A short answer, do not have two actions on the same controller. But if you want to, use specific routes (add a constraint). Also, is there a reason to have the password in the url?
routes.MapHttpRoute(
name: "UserRegistrationApi",
routeTemplate: "api/{controller}/{action}/{firstName}/{lastName}/{email}/{phoneNo}/{company}",
constraints = new { action = "RegisterUser" }
);
routes.MapHttpRoute(
name: "UserPasswordConfirmationApi",
routeTemplate: "api/{controller}/{action}/{userId}/{password}",
constraints = new { action = "ConfirmUserPassword" }
);

Resources