WebApi routing not passing value - asp.net

I am trying to pass a value to a controller / action in Web Api but it's not finding it.
My Route Mapping:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
My ApiController:
[HttpGet]
public string MyThing()
{
return "thing";
}
[HttpGet]
public string MyStuff(int myid)
{
return "something " + myid;
}
My REST call via RestSharp:
var request = new RestRequest { Resource = "api/values/MyStuff/555", Method = Method.GET };
If I call MyThing() it works though. It seems that the problem is in passing the id value.

Modify the parameter name from "myid" to "id"
[HttpGet]
public string MyStuff(int **id**)

Solved.
I found I had to add the parameter as an Query String, not a /path value.
api/values/MyStuff?myid=555
instead of
api/values/MyStuff/555

Related

No Type was found that matches Controller non-MVC ASP.net Web API

Currently I am creating a web application using a non-mvc web API in .NET. We are also using AngularJS to call the API with.
Here is the Router:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Here is the controller:
public class signOnController : ApiController
{
public IHttpActionResult GetSingleSignOn()
{
singleSignOn sign = new singleSignOn();
var check = sign.executeStoredProcedure();
if (check == 0)
{
return Ok("http://localhost:64325/EmployeeIndex.html#/form/begin");
}
else if (check == 1)
{
return Ok("http://localhost:64325/ManagerIndex.html#/form/begin");
}
else
{
return Unauthorized();
}
}
}
Here is the angularJS:
formApp.service('ApiCall', ['$http', function ($http) {
var result;
this.GetApiCall = function (controllerName, methodName) {
result = $http.get('api/' + controllerName + '/' + methodName).success(function (data, status) {
result = data;
}).error(function () {
alert("API Get call error");
});
return result;
};
I keep getting this error when I try to run it:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:51463/api/signOnController/GetSingleSignOn'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'signOnController'.
</MessageDetail>
</Error>
Anyone know what I'm doing wrong with it?
You shouldn't be mentioning Controller inside route name. It should be
http://localhost:51463/api/signOn/GetSingleSignOn
Though you can use Route Attribute to define Routing to make route more verbose.
[Route("SingleSignOn")]
public IHttpActionResult GetSingleSignOn() {
....
}
Then URL will be like http://localhost:51463/api/signOn/SingleSignOn
Firstly, the route should be http://localhost:51463/api/signOn/GetSingleSignOn. controller name is just for identifying it is a controller.in routes you must use this without the word Controller. but when creating a controller make sure you include the word
secondly, i think what you exactly want to achieve is a route like in MVC. change your router to include action.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
the default asp webapi routes are for pure REST API implementation which is not suitable for most cases.

can we pass null in the url parameter?

I have a Asp.Net webApi controller as below:
[RoutePrefix("business/api/v1")]
public class BusinessController : ApiController
{
[Route("GetDetails/{id}")]
public HttpResponseMessage Get(string id)
{
// get business details code.
}
}
Is there anyway that client can hit this api with id null??
It depends on your configuration of Web API routes in App_Start/WebApiConfig.cs.
If route is something like:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "business/api/v1/GetDetails/{id}",
defaults: new { id = RouteParameter.Optional }
);
then user can reach resource use http://localhost.business/api/v1/GetDetails or http://localhost.business/api/v1/GetDetails/1.
When you remove defaults: new { id = RouteParameter.Optional } then user have to pass an id otherwise, it will return 404
Please try:
[RoutePrefix("business/api/v1")]
public class BusinessController : ApiController
{
[Route("GetDetails/{id:int?}")]
public HttpResponseMessage Get(int id)
{
// get business details code.
}
}

how to pass parameter name "action" in asp.net web api

Can not send parameter name "action" by url in asp.net web api 2.0.
Example:
http://host:port/controller_name?action=2&...
if you do so:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{action}",
defaults: new
{
action=RouteParameter.Optional
}
);
method in controller:
public HttpResponseMessage Get(int action)
{
return ResponseXml();
}
gives an error message:
in the dictionary path name of the parameter "action" is contained in
the URL-address more than once
How to pass parameter name "action" as a parameter, rather than the action method ?
thanks
Since the name action is included in the querystring part(?action=2), no need to change the route map. The framework will bind the value to the action paramter in the action method. Remove the extra {action} in routeTemplate. And since your url format doesn't contain {action} host:port/controller_name?action=2&login=, remove {action} from routemap.
So, your route map will be
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new
{
id=RouteParameter.Optional
}
);
You could try using Attribute Routing and include it in the route template.
//GET [controller_route]/2
[HttpGet]
[Route("{action:int}")]
public HttpResponseMessage Get(int action)
{
return ResponseXml();
}
which will let you use the following url
http://host:port/controller_name/2
where action parameter will be mapped to 2.
Remember to enable the attribute routing during configuration.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

the request is invalid?

Bit of a asp.net mvc noob , I am trying to pass in a string as an argument for my Web API controller:
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";
}
public string Get(string arg)
{
return "othervalue";
}
}
I tried to add another route:
routes.MapRoute(
name: "Default2",
url: "{controller}/{action}/{arg}",
defaults: new { controller = "Home", action = "Index", arg = UrlParameter.Optional }
);
So I want to keep both Get methods and use the Get with the arg parameter so I can pass in a string. So when I try to hit this url 'api/values/jjhjh' in my browser I get this error:
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.String Get(Int32)' in 'stackOverflowWebApi.Controllers.ValuesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
The additional route you added was an MVC route, not a WebAPI route. WebAPI routes are not located in RouteConfig.cs by default, they are in WebApiConfig.cs. They look more like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
The error you posted comes from not passing in any data at all. Give this a try instead:
public string Get(string id = null)
{
return "othervalue";
}
Note that the parameter name is id, not arg, to make it match the optional route parameter. Also, defaulting it to null tells the binder that its okay to invoke this method when no data is passed.

Web API Routing - api/{controller}/{action}/{id} "dysfunctions" api/{controller}/{id}

I have the default Route in Global.asax:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
I wanted to be able to target a specific function, so I created another route:
RouteTable.Routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
So, in my controller, I have:
public string Get(int id)
{
return "object of id id";
}
[HttpGet]
public IEnumerable<string> ByCategoryId(int id)
{
return new string[] { "byCategory1", "byCategory2" };
}
Calling .../api/records/bycategoryid/5 will give me what I want.
However, calling .../api/records/1 will give me the error
Multiple actions were found that match the request: ...
I understand why that is - the routes just define what URLs are valid, but when it comes to function matching, both Get(int id) and ByCategoryId(int id) match api/{controller}/{id}, which is what confuses the framework.
What do I need to do to get the default API route to work again, and keep the one with {action}? I thought of creating a different controller named RecordByCategoryIdController to match the default API route, for which I would request .../api/recordbycategoryid/5. However, I find that to be a "dirty" (thus unsatisfactory) solution. I've looked for answers on this and no tutorial out there on using a route with {action} even mentions this issue.
The route engine uses the same sequence as you add rules into it. Once it gets the first matched rule, it will stop checking other rules and take this to search for controller and action.
So, you should:
Put your specific rules ahead of your general rules(like default), which means use RouteTable.Routes.MapHttpRoute to map "WithActionApi" first, then "DefaultApi".
Remove the defaults: new { id = System.Web.Http.RouteParameter.Optional } parameter of your "WithActionApi" rule because once id is optional, url like "/api/{part1}/{part2}" will never goes into "DefaultApi".
Add an named action to your "DefaultApi" to tell the route engine which action to enter. Otherwise once you have more than one actions in your controller, the engine won't know which one to use and throws "Multiple actions were found that match the request: ...". Then to make it matches your Get method, use an ActionNameAttribute.
So your route should like this:
// Map this rule first
RouteTable.Routes.MapRoute(
"WithActionApi",
"api/{controller}/{action}/{id}"
);
RouteTable.Routes.MapRoute(
"DefaultApi",
"api/{controller}/{id}",
new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional }
);
And your controller:
[ActionName("DefaultAction")] //Map Action and you can name your method with any text
public string Get(int id)
{
return "object of id id";
}
[HttpGet]
public IEnumerable<string> ByCategoryId(int id)
{
return new string[] { "byCategory1", "byCategory2" };
}
You can solve your problem with help of Attribute routing
Controller
[Route("api/category/{categoryId}")]
public IEnumerable<Order> GetCategoryId(int categoryId) { ... }
URI in jquery
api/category/1
Route Configuration
using System.Web.Http;
namespace WebApplication
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
// Other Web API configuration not shown.
}
}
}
and your default routing is working as default convention-based routing
Controller
public string Get(int id)
{
return "object of id id";
}
URI in Jquery
/api/records/1
Route Configuration
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Review article for more information Attribute routing and onvention-based routing here & this
Try this.
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var json = config.Formatters.JsonFormatter;
json.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
config.Formatters.Remove(config.Formatters.XmlFormatter);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional , Action =RouteParameter.Optional }
);
}
}
The possible reason can also be that you have not inherited Controller from ApiController.
Happened with me took a while to understand the same.
To differentiate the routes, try adding a constraint that id must be numeric:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
constraints: new { id = #"\d+" }, // Only matches if "id" is one or more digits.
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);

Resources