Route Prefix can be overridden - c#

I have an base controller which perform few post and get on offers, below i gave an sample structure of get
[AxAuthorization(Resource = "Offers")]
[RoutePrefix("api/offer/v2/offers")]
public class OffersV2Controller : ApiController
{
[HttpGet]
[Route("{id}", Name = "OffersGetById")]
public async Task<HttpResponseMessage> GetById([FromUri(Name = "id")]string OfferId)
{
----
-----
}
}
we are calling this get method by api/offer/v2/offers/id , but some other consumer who are using our services, they like to call as api/v2/offers/id, is there any way we can override it ? the above code is kind of code generated by product which we does't want to modify the route prefix.

[Route("api/v2/offer/test")]
[Route("api/offer/v2/test")]
OR
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "route1",
routeTemplate: "test/v2/Values",
defaults: new { controller = "Values", action = "Get" });
config.Routes.MapHttpRoute(
name: "route2",
routeTemplate: "v2/test/Values",
defaults: new { controller = "Values", action = "Get" });
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
in the webapiConfig.cs

Related

Routing error: No HTTP resource was found that matches the request URI

I'm trying to make the API call
http://localhost:56578/v1/reports
to call my GetReports() method.
However I continue to get the error message in the subject.
I'm following the ms docs here via the route prefix:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-prefixes
What am I doing wrong?
ReportV1Controller.cs
[Authorize]
[RoutePrefix("v1/reports")]
....
....
[Route("")]
public IHttpActionResult GetReports()
WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Change from this:
[RoutePrefix("v1/reports")]
to this:
[RoutePrefix("api/v1/reports")]
because of:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
See routeTemplate: "api/{controller}/{action}/{id}", you said prefix for all paths will be api, {controller}/{action}/{id} are placeholders
Conclusion: if you are going to use v1 prefix everywhere, put it instead of api
What you have should work provided that you have enabled attribute routing in the WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes(); //<-- THIS HERE
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Reference Attribute Routing in ASP.NET Web API 2: Enabling Attribute Routing
And assuming
[Authorize]
[RoutePrefix("v1/reports")]
public class ReportV1Controller : ApiController {
//GET v1/reports
[Route("")]
[HttpGet]
public IHttpActionResult GetReports() {
//...
}
}

Multiple Routing in Web API 2

I'm using Web API 2, I want to route using parameters such as (name & id).
When I try this :
config.Routes.MapHttpRoute(
name: "IDApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "NameApi",
routeTemplate: "api/{controller}/{action}/{name}",
defaults: new { name = RouteParameter.Optional }
);
I got the route 'api/customer/getByID/5' worked fine.
But the route 'api/customer/searchByName/fawzy' didn't work.
And if I set the NameAPI route before the IDAPI route the result is the opposite.
Any ideas ?
You can use Attribute [Route("api/customer/searchByName/{name}")] from namespace System.Web.Http.Routing for searchByName action.
I solved this problem by a combination of Pattern & Route Attribute
In the WebAPIConfig file :
config.Routes.MapHttpRoute(
name: "IDApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { id = #"^[0-9]+$" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}",
defaults: null
);
In the Controller :
[HttpGet]
[Route("api/customer/search/{name}")]
public IHttpActionResult Search(string name)
{
}
[HttpGet]
public IHttpActionResult Get(int id)
{
}

WebApi Routing: api/{controller}/{id} and api/{controller}/{action} at the same time

I have default webapi routing configuration:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
);
I want to support following scenarios:
//api/mycontroller
public IQueryable<MyDTO> Get();
//api/mycontroller/{id} where id can be anything except "customaction1" and "customaction2"
public HttpResponseMessage Get(string id);
//api/mycontroller/customaction
[HttpPost]
public void CustomAction1([FromBody] string data);
[HttpPost]
public void CustomAction2([FromBody] string data);
I have tried to apply [Route("api/mycontroller/customaction1")] to the CustomAction1 method, and similar to CustomAction2 but getting:
Multiple actions were found that match the request:
CustomAction1 on type MyProject.WebApiService.MyController
CustomAction2 on type MyProject.WebApiService.MyController
Make sure that you configured attribute routing along with your default configuration
//....
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
);
//....
If you want to do the same with out attribute routing then you will need to configure routes explicitly
//This one constrains id to be an int
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action="Get", id = RouteParameter.Optional },
constraints : new { id = #"\d" }
);
//This one should catch the routes with actions included
config.Routes.MapHttpRoute(
name: "ActionRoutes",
routeTemplate: "api/{controller}/{action}"
);

Correctly crafting routes for asp.net web api

I am struggling to correctly design a DELETE http request in my ASP Web application.
I have the following route defined:
public const string ControllerOnly = "ApiControllerOnly";
public const string ControllerAndId = "ApiControllerAndIntegerId";
private const string ControllerAction = "ApiControllerAction";
public static void Register(HttpConfiguration config)
{
var routes = config.Routes;
// api/projects
routes.MapHttpRoute(
name: ControllerOnly,
routeTemplate: "api/{controller}"
);
//api/projects/1
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits
);
routes.MapHttpRoute(
name: ControllerAction,
routeTemplate: "api/{controller}/{action}"
);
}
I am expecting it to hit the following action:
public HttpResponseMessage Delete(int i)
{
//content remove for brevity
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
In fiddler I try to test using the following: DELETE http://localhost:port/api/controller/1
but that method never gets hit. Instead, the following method is hit:
public HttpResponseMessage Delete()
{
//content remove for brevity
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
I have a basic understanding of routing but shouldn't that only route I defined ensured that the previous test is successful?
Note that I have no problem with GET and POST verbs
Any help appreciated
I guess you need to add the action part in your route as below :-
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits);
Add/Register other route-path before default route. It takes always first prior one. So, in your case you need to register one more path in WebApiConfig as below.
routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{Id}",
defaults: new { Id = RouteParameter.Optional
});
Note : You must register this route before your default route.
i.e, It should be as below.
public static void Register(HttpConfiguration config)
{
routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{Id}",
defaults: new { Id = RouteParameter.Optional
});
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits
);
}

Need to pass the URL with arguments in webapi

I have the below URLs to pass the different API.
/shared/rendererjob -- I done
/shared/rendererjob/{jobId} -- I done
/shared/rendererjob/{jobId} -- done
/shared/rendererjob/{jobId}/status -- done
/shared/renderer/documentconverter/document -- I done
/shared/renderer/documentconverter/storage -- I done
/shared/renderer/documentconverter/callback -- I done
/shared/rendererhealth?q={level} -- **I dont know how to do this one**
How to write the webconfig.cs for this -- /shared/rendererhealth?q={level}
My config code is below.
config.Routes.MapHttpRoute(
name: "RendererApi",
routeTemplate: "shared/{controller}/{renderGUID}",
defaults: new { action = "rendererJob", renderGUID =
RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "RendererAPiStatus",
routeTemplate: "shared/{controller}/{jobid}/status",
defaults: new { action = "getJobStatus", jobid = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DocumentConverterApi",
routeTemplate: "shared/renderer/{controller}/{action}"
);
The above code is working for what I have done.
Please let me know how to config the controler with arguments.
**How to achieve this path --
http://localhost:12345/shared/rendererhealth?q={level}**
As your routes appear to be very controller dependent, the first thing I would do is change your existing routing as follows:
config.Routes.MapHttpRoute(
name: "RendererApi",
routeTemplate: "shared/rendererjob/{renderGUID}",
defaults: new { action = "rendererJob",
renderGUID = RouteParameter.Optional,
controller="rendererJob" }
);
config.Routes.MapHttpRoute(
name: "RendererAPiStatus",
routeTemplate: "shared/rendererjob/{jobid}/status",
defaults: new { action = "getJobStatus",
controller="rendererjob" }
);
config.Routes.MapHttpRoute(
name: "DocumentConverterApi",
routeTemplate: "shared/renderer/documentconverter/{action}",
defaults: new { controller="documentconverter" }
);
Note you cannot have an optional parameter in the middle of a route so I have changed your RendererAPiStatus route so that jobid is mandatory.
Next add a new route at the end for your new resource:
config.Routes.MapHttpRoute(
name: "RendererHealthApi",
routeTemplate: "shared/rendererhealth",
defaults: new { controller="rendererhealth" }
);
You can then add your new controller method:
public class RendererHealthController : ApiController
{
public string Get(int q)
{
return "hello";
}
}
Note the above assumes you are using a GET request and {level} is an integer.

Categories