I'm trying to use the web api in c# so far its been working pretty well but i just have a route that doesn't want to work and i searched a bit around for people with similar problems but their solution didn't seem to work.
I'm trying to have a specific route and capturing an email address in the string, here is my Controller:
[Authorize]
[RoutePrefix("api/contact")]
public class ContactController : ApiController
{
[Route("list/{id:int}")]
[HttpGet]
public ContactList GetList(int id)
{
BasicAuthenticationIdentity identity = (BasicAuthenticationIdentity)this.User.Identity;
ContactModel contactModel = new ContactModel(identity.accountId);
return (contactModel.GetList(id));
}
[Route("list/{id:int}")]
[HttpPost]
public void PostList(int id)
{
BasicAuthenticationIdentity identity = (BasicAuthenticationIdentity)this.User.Identity;
// To be implemented
}
[Route("attribute/{contactKey}")]
[HttpGet]
public IEnumerable<ContactData> GetContactAttributeKey(string contactKey)
{
BasicAuthenticationIdentity identity = (BasicAuthenticationIdentity)this.User.Identity;
ContactModel contactModel = new ContactModel(identity.accountId);
return (contactModel.GetContactAttribute(contactKey));
}
}
The list route works well but when i try something like
http://localhost/api/contact/attribute/test#test.com i keep getting HTTP Error 404.0 - Not Found because it seems it can't find the route.
Is there something wrong in this?
I also have this in the webconfig
// Itinéraires de l'API Web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
I tried to see if other routes could be set that are the same but there is no other, i just have an account and segment route other than that, if anyone got some suggestion i'm open to everything right now :/
You should use %40 instead of # symbol and %2E instead of ..
http://localhost/api/contact/attribute/test%40test%2Ecom
This is called URL encoding, some characters are not valid in URL.
Okay its a comibnation of the answer of dotctor (using the url encode) and also there is a need to enable this in your web.config
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
Related
I have looked all over for some kind of soultion for this and it seems I have it setup correctly and followed all corrections in other questions.
When calling "http://localhost/en/api/cart/get" I get:
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost/en/api/cart/get'.","MessageDetail":"No type was found that matches the controller named 'cart'."}
...when trying to access a ApiController setup in an EPiServer CMS/Commerce 7.5+ solution.
The Controller looks like this:
public class CartController : ApiController
{
[HttpGet]
public string Get()
{
return "OK";
}
}
In Global.asax.cs i have this:
protected void Application_Start()
{
RegisterApis(GlobalConfiguration.Configuration);
And the RegisterAPis looks like this:
public static void RegisterApis(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
"Api", // Route name
"api/{controller}/{action}/{id}", // URL with parameters
new { id = RouteParameter.Optional } // Parameter defaults
);
config.Routes.MapHttpRoute(
"LanguageAwareApi", // Route name
"{language}/api/{controller}/{action}/{id}", // URL with parameters
new { id = RouteParameter.Optional } // Parameter defaults
);
// We only support JSON
var appXmlType = GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
On the same machine I have the EPiServer Commerce starterkit running i IIS and the code for registering the api controllers is the same. That site runs fine and the api calls can be made correctly but on my site all I get is 404.
So I am probably missing some configuration but I can't for my life figure out what it is. The weird part is that on my site I'm running the EPiServer ServiceApi which creates the /episerverapi Web Api mapping and that works just fine.
Anyone got any clues on why I can't get my APiControllers to work?
In Web API the http verb help the framework to find the right action to be executed and return a result. For sample, in a case of a get method, you just call the controller by get http verb:
http://localhost/en/api/cart
It will bind a Get action method in the Cart controller class. It is valid for a Post, Put, Delete methods too. Keep the default route of asp.net web api
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Try calling just
http://localhost/en/api/cart
In WebAPI if the name of the method matches a HTTP verb then it calls that method when that verb is used on that controller.
I am creating a WebApi2 service, and one of the methods I want to implement represents an HTTP GET from an object within an internal tree structure - so the request would be along the lines of:
GET /values/path/path/to/object/in/tree
So I would want my method to receive "path/to/object/in/tree".
However, I just get a 404 when I run this, and it's interesting that I get a 404 that is different looking to the standard IIS 404. It's titled 'Server Error in '/' Application.', whereas the one for a completely invalid resource is titled 'HTTP Error 404.0 - Not Found'.
I am playing around with the default template to try and see if I can get this to work, hence the similarity.
I have this for my RouteConfig
public static void RegisterRoutes(RouteCollection routes)
{
var route = routes.MapRoute(
name: "CatchAllRoute",
url: "values/path/{*pathValue}",
defaults: new { controller = "Values", action = "GetPath" });
}
And this is my ValuesController:
[System.Web.Mvc.AuthorizeAttribute]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
[Route("test/{value}")]
[HttpGet]
public string Test(string value)
{
return value;
}
[HttpGet]
public string GetPath(string pathValue)
{
return pathValue;
}
}
Interestingly, if I derive from Controller rather than ApiController it works OK, but then the normal attribute routing doesn't work.
I tried following the methodology in this post (http://www.tugberkugurlu.com/archive/asp-net-web-api-catch-all-route-parameter-binding) but I couldn't get it to work.
I'm sure I'm missing something stupidly easy, but having spent a few hours on it I thought it prudent to ask what I'm doing wrong.
Thanks
M
Web api routing is not the same as routing MVC. instead of
route.MapRoute
try
public static void Register(HttpConfiguration config) {
config.MapHttpAttributeRoutes
config.Routes.MapHttpRoute(
name: "CatchAll", routeTemplate: "values/path/{*pathvalue}",
defaults: new {id = RouteParameter.Optional });
}
The reason it works from controller is that MapRoute is the correct format for routing an MVC controller, while MapHttpRoute is designed for API controllers.
I installed ASP.NET 4 Web API Help Page package via nuget to my Web Api project. For some reason it does not display all the api endpoints. I have the documentation set to use XML. Not sure why this is happening, any help is appreciated.
Here is an example controller
public class ProductController : BaseController
{
// GET api/Product/Get/5/43324
[AcceptVerbs("GET")]
public ApiProduct Get(int id, [FromUri]int productId)
{
//// logic
}
}
routes
config.Routes.MapHttpRoute(
name: "api-info",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional }
);
Thanks
I figured out the issue, the problem here is, In Web API there is no action and methods are mapped to the verb and arguments directly, Updating my route to this fixed the problem and all the routes show up.
config.Routes.MapHttpRoute(
name: "apsi-info",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
If the above solution doesn't solve your problem - take a look and make sure you aren't defining BOTH the AcceptVerbs attribute and its shortcut:
public class ProductController : BaseController
{
// GET api/Product/Get/5/43324
[AcceptVerbs("GET")]
[HttpGet]
public ApiProduct Get(int id, [FromUri]int productId)
{
//// logic
}
}
Remove one of them and it should work.
Another reason why a HTTP method might not be available, either as an endpoint or not showing up in the autogenerated help:
The function might be private and not public.
Will show up:
[HttpGet]
[Route("api/projects")]
public IHttpActionResult GetCount()
{
return Ok(db.Projects.Count());
}
Won't show up:
[HttpGet]
[Route("api/projects")]
private IHttpActionResult GetCount()
{
return Ok(db.Projects.Count());
}
My answer might be helpful for someone with different problem statement, As I faced similar sort of issue and wasted few hours.
[PUT("Update/booking/{id}")]
public bool Put(id bookingId, [FromBody] BookingEntity bookingEntity)
This api endpoint won't appear in API help page.
If you observe parameter name is different in route that is {id} and method parameters "bookingId". Both should be same as specified in below code.
[PUT("Update/booking/{id}")]
public bool Put(id id, [FromBody] BookingEntity bookingEntity)
My route is correctly configured, and my methods have the decorated tag. I still get "The requested resource does not support HTTP method 'GET'" message?
[System.Web.Mvc.AcceptVerbs("GET", "POST")]
[System.Web.Mvc.HttpGet]
public string Auth(string username, string password)
{
// Décoder les paramètres reçue.
string decodedUsername = username.DecodeFromBase64();
string decodedPassword = password.DecodeFromBase64();
return "value";
}
Here are my routes:
config.Routes.MapHttpRoute(
name: "AuthentificateRoute",
routeTemplate: "api/game/authentificate;{username};{password}",
defaults: new { controller = "Game",
action = "Auth",
username = RouteParameter.Optional,
password = RouteParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "Home", id = RouteParameter.Optional }
);
Please use the attributes from the System.Web.Http namespace on your WebAPI actions:
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpGet]
public string Auth(string username, string password)
{...}
The reason why it doesn't work is because you were using the attributes that are from the MVC namespace System.Web.Mvc. The classes in the System.Web.Http namespace are for WebAPI.
In my case, the route signature was different from the method parameter. I had id, but I was accepting documentId as parameter, that caused the problem.
[Route("Documents/{id}")] <--- caused the webapi error
[Route("Documents/{documentId}")] <-- solved
public Document Get(string documentId)
{
..
}
Resolved this issue by using http(s) when accessing the endpoint. The route I was accessing was not available over http. So I would say verify the protocols for which the route is available.
just use this attribute
[System.Web.Http.HttpGet]
not need this line of code:
[System.Web.Http.AcceptVerbs("GET", "POST")]
I was experiencing the same issue.. I already had 4 controllers going and working just fine but when I added this one it returned "The requested resource does not support HTTP method 'GET'".
I tried everything here and in a couple other relevant articles but was indifferent to the solution since, as Dan B. mentioned in response to the answer, I already had others working fine.
I walked away for a while, came back, and immediately realized that when I added the Controller it was nested under the "Controller" class and not "ApiController" class that my other Controllers were under. I'm assuming I chose the wrong scaffolding option to build the .cs file in Visual Studio. So I included the System.Web.Http namespace, changed the parent class, and everything works without the additional attributes or routing.
Using the new Api Controller in MVC4, and I've found a problem. If I have the following methods:
public IEnumberable<string> GetAll()
public IEnumberable<string> GetSpecific(int i)
This will work. However, if I want to retrieve some different data of a different type, it defaults to the GetAll method, even though the $.getJSON is set to the GetAllIntegers method:
public IEnumberable<int> GetAllIntergers()
(bad naming conventions)
Is it possible for me to be able to do this?
Can I only have a single GetAll method in the Web API controller?
I think it's easier to visualise what I'm trying to achieve. Here is a snippet of code to show what I'd like to be able to do, in a single ApiController:
public IEnumerable<string> GetClients()
{ // Get data
}
public IEnumerable<string> GetClient(int id)
{ // Get data
}
public IEnumerable<string> GetStaffMember(int id)
{ // Get data
}
public IEnumerable<string> GetStaffMembers()
{ // Get data
}
This is all in the routing. The default Web API route looks like this:
config.Routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
With the default routing template, Web API uses the HTTP method to select the action. In result it will map a GET request with no parameters to first GetAll it can find. To work around this you need to define a route where the action name is included:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
After that you can star making requests with following URL's:
api/yourapicontroller/GetClients
api/yourapicontroller/GetStaffMembers
This way you can have multiple GetAll in Controller.
One more important thing here is that with this style of routing, you must use attributes to specify the allowed HTTP methods (like [HttpGet]).
There is also an option of mixing the default Web API verb based routing with traditional approach, it is very well described here:
Web API: Mixing Traditional & Verb-Based Routing
In case someone else faces this problem. Here's how I solved this. Use the [Route] attribute on your controller to route to a specific url.
[Route("api/getClient")]
public ClientViewModel GetClient(int id)
[Route("api/getAllClients")]
public IEnumerable<ClientViewModel> GetClients()