可以公开一个可以像操作一样调用的 WebAPI 方法(Get 或 Post)吗?
Possible to have a WebAPI method exposed (Get or Post) that can be called like an Action?
这可能不是很清楚所以让我详细说明一下:
据我目前所知,网络api控制器的"action"是由参数的数量和类型决定的。因此,如果您传入两个字符串,您将获得方法签名中包含两个字符串的 Get 或 Post。
我想做的是像这样设置几条路线:
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/Delete",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
config.Routes.MapHttpRoute(
name: "fileFunctionsUpload",
routeTemplate: "api/{controller}/{appName}/{userID}/Upload",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
这些显然应该转到同一个控制器,但在 MVC 网站中,我会转到名为 "Delete" 或 "Upload" 的操作。
到目前为止,我所看到的只是 Gets 和 Posts,其中参数的数量和类型用于确定调用的内容。这太令人困惑了。
有什么方法可以让它更像 "MVC website" 通话行为吗?
To clarify: If I want a specific action to fire, I call it by name. "public ActionResult ThisAction(object[] params). In the web api, all the sigatures are like Get or Put or Post. I want to be able to say something like "url:../Delete" and it calls the appropriate delete get or post. I don't want to have to differentiate my methods by the number of parameters I pass in or parse a string to see what the user intended. Those are recipes for failure
更新:
Kenneth、lgor 和 Tu Hoang 的答案都有需要一起考虑的关键信息(约束路线、动作、模型属性等的方法),每个都有构成完整答案的信息。我无法全部标记,所以我将 "most correct" 标记为我的问题。
就我个人而言,我发现当您希望在您的操作中使用自定义路由时,使用属性路由会更容易一些。 As exemplified 在官方 ASP.NET 网站上,您可以使用 [Route]
属性将路由直接应用于您的操作:
例如
public class CustomerController : ApiController
{
[Route("api/Customer/{model.LastName}/{model.FirstName}/Upload")]
public void Post(CustomerModel model)
{
// ...
}
}
我不记得你是否可以在 {controller}
中替换默认路由的方式,但我相信你可以。我有一个复杂的对象作为参数,因此使用点符号,但如果你只是使用简单的类型,那么你可以直接使用变量名(例如 [Route("api/Customer/{lastName}/{firstName}/Upload")]
)。
还有 [RoutePrefix]
属性,您可以将其应用于控制器,这样您就不必重复 api/Customer/
,例如,在每个操作上:
[RoutePrefix("api/Customer")]
public class CustomerController : ApiController
{
[Route("{model.LastName}/{model.FirstName}/Upload")]
public void Post(CustomerModel model)
这不是一个很好的例子,因为我正在演示 POST 并且参数是通过 URL 传入的,但它应该可以证明这个想法。
您可以像在 MVC 中一样在 routeTemplate
中指定 action
占位符。看下面的代码,我用{action}
替换了Delete
。它可能会变得棘手,但如果你在参数之间是可选的,那么这里的顺序可能很关键,我更喜欢它是 api/{controller}/{action}/{appName}/{userID}/
或 api/{action}/{controller}/{appName}/{userID}/
。
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/{action}",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
(from comment) ... with a sample method signature
方法签名与任何其他签名一样。
// I am not sure what type of parameters these are so I am going to take a wild guess
[HttpPost]
public async Task<IHttpActionResult> Post(string appName = null, int? userID = null, CancellationToken token) {}
这取决于你传递的是什么。这同样适用于 post、put、get、delete 或您可能拥有的自定义名称。如果您想根据 http 动词限制访问(这里没有什么不同),请记住应用 HttpGet/HttpPost/HttpPut/HttpDelete 属性。
您还可以使用 Kennith 指定的 Route 和 RoutePrefix 属性。我不会窃取他的答案,这是一个很好的答案,如果根据情况不喜欢也完全可以接受。
像下面这样?您需要 action
默认值并在控制器操作上匹配 ActionName
属性。
话虽这么说,您的路线示例看起来需要一些改进。具体来说,所有路由参数都是可选的是什么意思。如果 userId
是可选的,删除会做什么?如果 appName
是可选的,路由是否有效。
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/Delete",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
action = "Delete"
},
constraints: new { HttpMethod = new HttpMethodConstraint(HttpMethod.Post) });
);
[HttpPost]
[ActionName("Delete")]
public async Task<HttpResponseMessage> DeleteUser(
string controller,
string appName,
string userID)
{
}
这可能不是很清楚所以让我详细说明一下:
据我目前所知,网络api控制器的"action"是由参数的数量和类型决定的。因此,如果您传入两个字符串,您将获得方法签名中包含两个字符串的 Get 或 Post。
我想做的是像这样设置几条路线:
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/Delete",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
config.Routes.MapHttpRoute(
name: "fileFunctionsUpload",
routeTemplate: "api/{controller}/{appName}/{userID}/Upload",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
这些显然应该转到同一个控制器,但在 MVC 网站中,我会转到名为 "Delete" 或 "Upload" 的操作。
到目前为止,我所看到的只是 Gets 和 Posts,其中参数的数量和类型用于确定调用的内容。这太令人困惑了。
有什么方法可以让它更像 "MVC website" 通话行为吗?
To clarify: If I want a specific action to fire, I call it by name. "public ActionResult ThisAction(object[] params). In the web api, all the sigatures are like Get or Put or Post. I want to be able to say something like "url:../Delete" and it calls the appropriate delete get or post. I don't want to have to differentiate my methods by the number of parameters I pass in or parse a string to see what the user intended. Those are recipes for failure
更新:
Kenneth、lgor 和 Tu Hoang 的答案都有需要一起考虑的关键信息(约束路线、动作、模型属性等的方法),每个都有构成完整答案的信息。我无法全部标记,所以我将 "most correct" 标记为我的问题。
就我个人而言,我发现当您希望在您的操作中使用自定义路由时,使用属性路由会更容易一些。 As exemplified 在官方 ASP.NET 网站上,您可以使用 [Route]
属性将路由直接应用于您的操作:
例如
public class CustomerController : ApiController
{
[Route("api/Customer/{model.LastName}/{model.FirstName}/Upload")]
public void Post(CustomerModel model)
{
// ...
}
}
我不记得你是否可以在 {controller}
中替换默认路由的方式,但我相信你可以。我有一个复杂的对象作为参数,因此使用点符号,但如果你只是使用简单的类型,那么你可以直接使用变量名(例如 [Route("api/Customer/{lastName}/{firstName}/Upload")]
)。
还有 [RoutePrefix]
属性,您可以将其应用于控制器,这样您就不必重复 api/Customer/
,例如,在每个操作上:
[RoutePrefix("api/Customer")]
public class CustomerController : ApiController
{
[Route("{model.LastName}/{model.FirstName}/Upload")]
public void Post(CustomerModel model)
这不是一个很好的例子,因为我正在演示 POST 并且参数是通过 URL 传入的,但它应该可以证明这个想法。
您可以像在 MVC 中一样在 routeTemplate
中指定 action
占位符。看下面的代码,我用{action}
替换了Delete
。它可能会变得棘手,但如果你在参数之间是可选的,那么这里的顺序可能很关键,我更喜欢它是 api/{controller}/{action}/{appName}/{userID}/
或 api/{action}/{controller}/{appName}/{userID}/
。
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/{action}",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
fileAction= RouteParameter.Optional
}
);
(from comment) ... with a sample method signature
方法签名与任何其他签名一样。
// I am not sure what type of parameters these are so I am going to take a wild guess
[HttpPost]
public async Task<IHttpActionResult> Post(string appName = null, int? userID = null, CancellationToken token) {}
这取决于你传递的是什么。这同样适用于 post、put、get、delete 或您可能拥有的自定义名称。如果您想根据 http 动词限制访问(这里没有什么不同),请记住应用 HttpGet/HttpPost/HttpPut/HttpDelete 属性。
您还可以使用 Kennith 指定的 Route 和 RoutePrefix 属性。我不会窃取他的答案,这是一个很好的答案,如果根据情况不喜欢也完全可以接受。
像下面这样?您需要 action
默认值并在控制器操作上匹配 ActionName
属性。
话虽这么说,您的路线示例看起来需要一些改进。具体来说,所有路由参数都是可选的是什么意思。如果 userId
是可选的,删除会做什么?如果 appName
是可选的,路由是否有效。
config.Routes.MapHttpRoute(
name: "fileFunctionsDelete",
routeTemplate: "api/{controller}/{appName}/{userID}/Delete",
defaults: new {
appName = RouteParameter.Optional,
userID= RouteParameter.Optional,
action = "Delete"
},
constraints: new { HttpMethod = new HttpMethodConstraint(HttpMethod.Post) });
);
[HttpPost]
[ActionName("Delete")]
public async Task<HttpResponseMessage> DeleteUser(
string controller,
string appName,
string userID)
{
}