How can I call different GET methods in the same controller using different parameters?

I have a controller that contains two different Get methods. One takes an int value and the other takes a String value, as shown below:

 public class AccountController : ApiController { public String GetInfoByString(String sUserInput) { return "GetInfoByString received: " + sUserInput; } public String GetInfoByInt(int iUserInput) { return "GetInfoByInt received: " + iUserInput; } } 

My RouteConfig.cs is intact and looks like this:

 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 } ); } 

My WebApiConfig.cs is also untouched and looks like this:

 public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } 

I would like to get into the web interface using one link:

 // Hit GetInfoByInt http://localhost:XXXX/api/account/1 // Hit GetInfoByString http://localhost:XXXX/api/account/abc 

I can hit the first case just fine, but whenever I try to get into the second case, I get the following error:

 <Error> <Message>The request is invalid.</Message> <MessageDetail> The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method 'TestProject.String GetInfoByInt(Int64)' in 'TestProject.Controllers.AccountController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. </MessageDetail> </Error> 

Is it possible to use the Get method depending on whether the user provided String or int ? I assume that changes should be made to RouteConfig or WebApiConfig, but I'm not too sure how to approach this. Maybe this is just an easy solution?

Also, if that matters, I would like to be able to use GetInfoByString with a String that contains both letters and numbers, such as 'ABC123' or '123ABC' . GetInfoByInt may be something like '123'

I would really like to stick to one controller, and not split it into multiple controllers, if possible.

Thanks in advance for your help.

+4
source share
4 answers

Here is one way to do things if you want to separate these two actions:

 config.Routes.MapHttpRoute("GetAccountInfoByInt", "api/account/{iUserInput}", new { controller = "account", action = "GetInfoByInt" }, new { iUserInput = @"\d+" }); config.Routes.MapHttpRoute("GetAccountInfoByString", "api/account/{sUserInput}", new { controller = "account", action = "GetInfoByString" }); 

Please note that we plan to make this easier in the future by introducing attribute routing in the next version of the web API:

https://aspnetwebstack.codeplex.com/wikipage?title=Attribute%20routing%20in%20Web%20API

It should already be available if you want to use our nightly builds. Then all you have to do is add a couple of attributes:

 [HttpGet("api/account/{sUserInput}")] public String GetInfoByString(String sUserInput) [HttpGet("api/account/{iUserInput:int}")] public String GetInfoByInt(int iUserInput) 
+4
source

One way to overcome this limitation would be to use parameters with a zero value, for example.

 public ActionResult GetInfo(string sUserInput, int? iUserInput) 

... and discarding your logic with a non-zero value.

0
source

The following code works for me, pay attention to the ActionName and HttpGet attributes , also not included in the configuration, which must be defined for the action parameter for api.

 public class AccountController : ApiController { [HttpGet] [ActionName("GetInfoByString")] public String GetInfoByString(String sUserInput) { return "GetInfoByString received: " + sUserInput; } [HttpGet] [ActionName("GetInfoByInt")] public String GetInfoByInt(int iUserInput) { return "GetInfoByInt received: " + iUserInput; } } 

Do the same in Config for Api

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapHttpRoute("DrawWebService", "api/{controller}/{action}/{value}", new { value = System.Web.Http.RouteParameter.Optional }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } 
0
source

A workaround is to use parameters with a null value or attempt to parse a string to an integer and then qualify.

 public ActionResult GetInfo(string sUserInput) { var result = sUserInput.IsInt ? GetInfoByInt(int.Parse(sUserInput)) : GetInfoByString(sUserInput) return result; } 
0
source

Source: https://habr.com/ru/post/1484881/


All Articles