如何在 Asp.net Web Api 中的 url 参数中发送控制器动作?
How to send controller action in url parameter in Asp.net Web Api?
通常你会像这样调用控制器的动作 http://hostname/MyController/MyAction
我要求我的 Web Api 有这样的路由:
http://hostname/MyController?action=MyAction
,即在url参数中传递动作。
我的控制器:
public class MyController : ApiController
{
[HttpGet]
[Route("WHAT SHOULD BE HERE??")]
public IHttpActionResult MyAction()
{
// some code
}
}
知道如何编写这样的路由吗?
您可以尝试以下方法:
public class MyController : ApiController
{
[HttpGet]
[Route("MyController")]
public IHttpActionResult MyInnerController(String action)
{
switch(action)
{
case "MyAction":
return MyAction();
}
return BadRequest("Invalid action: " + action);
}
public IHttpActionResult MyAction()
{
return Ok();
}
}
如果你需要额外的参数,事情会变得更复杂。
一年多以后,我可以回到这个问题并自己回答。
您可以在此处使用的解决方案是编写自己的 ActionSelector - 这是 class Web Api 框架用于 select 操作,默认情况下它使用 System.Web.Http.Controllers.ApiControllerActionSelector
,您可以覆盖它。
假设您的控制器如下所示:
public class MyController : ApiController
{
[HttpGet]
public IHttpActionResult MyAction()
{
// some code
}
}
然后你可以创建自己的动作select或者像这样(代码可能会改进我写得很快):
public class QueryParameterActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var mapping = GetActionMapping(controllerContext.ControllerDescriptor);
var parameters = controllerContext.Request.GetQueryNameValuePairs();
foreach (var parameter in parameters)
{
if (parameter.Key == "action")
{
if (mapping.Contains(parameter.Value))
{
// Provided that all of your actions have unique names.
// Otherwise mapping[parameter.Value] will return multiple actions and you will have to match by the method parameters.
return mapping[parameter.Value].First();
}
}
}
return null;
}
}
然后最后您必须在 select 或 WebApiConfig.Register
方法中注册此操作。它看起来像这样:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}"
);
config.Services.Replace(typeof(IHttpActionSelector), new QueryParameterActionSelector());
}
}
现在你可以这样调用你的动作了http://hostname/controller?action=MyAction
通常你会像这样调用控制器的动作 http://hostname/MyController/MyAction
我要求我的 Web Api 有这样的路由:
http://hostname/MyController?action=MyAction
,即在url参数中传递动作。
我的控制器:
public class MyController : ApiController
{
[HttpGet]
[Route("WHAT SHOULD BE HERE??")]
public IHttpActionResult MyAction()
{
// some code
}
}
知道如何编写这样的路由吗?
您可以尝试以下方法:
public class MyController : ApiController
{
[HttpGet]
[Route("MyController")]
public IHttpActionResult MyInnerController(String action)
{
switch(action)
{
case "MyAction":
return MyAction();
}
return BadRequest("Invalid action: " + action);
}
public IHttpActionResult MyAction()
{
return Ok();
}
}
如果你需要额外的参数,事情会变得更复杂。
一年多以后,我可以回到这个问题并自己回答。
您可以在此处使用的解决方案是编写自己的 ActionSelector - 这是 class Web Api 框架用于 select 操作,默认情况下它使用 System.Web.Http.Controllers.ApiControllerActionSelector
,您可以覆盖它。
假设您的控制器如下所示:
public class MyController : ApiController
{
[HttpGet]
public IHttpActionResult MyAction()
{
// some code
}
}
然后你可以创建自己的动作select或者像这样(代码可能会改进我写得很快):
public class QueryParameterActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var mapping = GetActionMapping(controllerContext.ControllerDescriptor);
var parameters = controllerContext.Request.GetQueryNameValuePairs();
foreach (var parameter in parameters)
{
if (parameter.Key == "action")
{
if (mapping.Contains(parameter.Value))
{
// Provided that all of your actions have unique names.
// Otherwise mapping[parameter.Value] will return multiple actions and you will have to match by the method parameters.
return mapping[parameter.Value].First();
}
}
}
return null;
}
}
然后最后您必须在 select 或 WebApiConfig.Register
方法中注册此操作。它看起来像这样:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}"
);
config.Services.Replace(typeof(IHttpActionSelector), new QueryParameterActionSelector());
}
}
现在你可以这样调用你的动作了http://hostname/controller?action=MyAction