My VS project has the following folder and files:
~\Controllers
\AccountController.cs
\HomeController.cs
...
~\Data
\AccountController.cs
...
~\App_Start
\RouteConfig.cs
\WebApiConfig.cs
WebApiConfig.cs contains:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
~\Data\AcccountController.cs contains:
namespace myApp.Data
{
public class AccountController : ApiController
{
[HttpGet]
public string GetUser(int id)
{
//...
}
...
}
}
When I make a http call to /api/Account/GetUser, the call is routed to the GetUser method shown above. What in all of the above or any configuration file tells the server to take the action from this particular file? What if ~/Controllers/AccountController.cs also contain a method of the same name?
It is called convention over configuration.
Related
I am trying to develop a webapi+angularjs+mvc project .here you can see my apicontroller
public class DefaultController : ApiController
{
testDBEntities a = new testDBEntities();
public IEnumerable<City> Get()
{
return a.Cities;
}
}
Here you can see the webapiconfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
But when i type this : localhost:5411/api/default
i got this error :
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /api/default
Add the line
GlobalConfiguration.Configure(WebApiConfig.Register) in your Global.asax.cs file
And this will register the webapi routes
I have web api 2 controller actions:
[HttpGet]
public Response<IEnumerable<Product>> Get()
{
....(Get all products)
}
[HttpGet]
public Response<Product> Get(int id)
{
....(Get product by id)
}
[HttpGet]
public Response<IEnumerable<Product>> Category(int id)
{
.... (Get products by category)
}
I want to use this controllers with url:
http://localhost/api/product
http://localhost/api/product/1
http://localhost/api/product/category/1
But this url http://localhost/api/product/1 returns error,
Multiple actions were found that match the request
My config settings are like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You might be better off using attribute routing rather than global routing here. If you remove your global routes and define your routes on a per-action basis you should have no problems. For example, your routes could look like:
[Route("api/product")]
[Route("api/product/{id:int}")]
[Route("api/product/category/{id:int}")]
This is the default controller created when you create a new ASP.NET Web APi within Visual Studio:
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
And the WebApi config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Your two Get methods match the same route. I would delete the first Get method and change your second Get method to use an optional id parameter like so:
[HttpGet]
public Response<IEnumerable<Product>> Get(int? id)
{
// Get all products if id is null, else get product by id and return as a list with one element
}
This way, Get will match routes for both "product" and "product/1".
By testing and wasting obscene amount of time I have found out that ASP.NET MVC has a bug which prevents using the string "api" in request URL. I wan to access my method with URL like this
www.mysite.com/api/test
This is not an unexpected wish. In fact it an an obvious Url choice.
Is there a workaround to achieve this?
UPDATE
By request routing definition.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// this executes, checked it in debugger
routes.MapRoute(
name: "Test",
url: "api/test",
defaults: new { controller = "Api", action = "Test" }
);
}
ApiController
public class ApiController : Controller
{
public ActionResult Test()
{
return Content("TEST TEST TEST");
}
{
If you have the WebApi packages installed, you'll find a WebApiConfig.cs class in App_Start. Here's what it looks like:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
So, assuming you don't change the default code in Global.asax.cs, this route gets added to the routing table. Hence, why your /api/whatever route doesn't work.
If you're not using WebApi, I would suggest removing the packages. Otherwise, you can simply change the "root" part of the API route to something else:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
/* changed 'api' to 'restsvc' */
routeTemplate: "restsvc/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I have created a new controller called WebPortalController but when I call it or try to call it via the browser I couldnt access the below method just said resource is not found. Do I need to add a new routing to the RoutesConfig.cs code if so how.?
namespace WebApi.Controllers
{
public class WebPortalController : ApiController
{
// GET api/webportal
private WebPortEnterpriseManagementDa _da = new WebPortEnterpriseManagementDa();
public ManagedType Get(string name)
{
ManagedType items = _da.GetManagedType(name);
return items;
}
// POST api/webportal
public void Post([FromBody]string value)
{
}
// PUT api/webportal/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/webportal/5
public void Delete(int id)
{
}
}
}
Routes file
namespace WebApi
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
The route config you have shown is for MVC routes and is located in the App_Start/RouteConfig file. Check that you have a default API route set in your App_Start/WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then you will need to change the parameter name in your Get method to match the routing parameter:
public ManagedType Get(string id)
{
ManagedType items = _da.GetManagedType(name);
return items;
}
This should allow you to call your Get method through a browser using:
localhost:55304/api/WebPortal/Test
In order to test out your Post/Put/Delete methods you will need to use Fiddler or a browser addin such as Postman
I have a Controller called QuotaController, and i can access it via httprequests, like this:
localhost:12345/quota/
What i want is to put an endpoint somewhere so i can access it like:
localhost:12345/quota/increment
or
localhost:12345/quota/decrement
How can this be done?
You could change your web api route definition to allow passing an action name:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
And then:
public class QuotaController : ApiController
{
public void Increment()
{
...
}
public void Decrement()
{
...
}
}