可以像操作一样调用WebAPI方法(Get或Post)吗?

时间:2016-03-24 18:47:17

标签: c# asp.net-mvc-4 asp.net-web-api asp.net-web-api-routing

这可能不是很清楚所以让我详细说明:

正如我目前所知,"行动" web api控制器的数量由参数的数量和类型决定。因此,如果您传入两个字符串,您将获得方法签名中包含两个字符串的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网站上,我会去一个名为"删除"或"上传"。

到目前为止,我所看到的只是获取和帖子,其中params的数量和类型用于确定所调用的内容。这太令人困惑了。

有没有什么方法可以让它更多" MVC网站" - 就像通话行为一样?

  

澄清:如果我想要一个特定的行动,我会通过名字来称呼它。 " public ActionResult ThisAction(object [] params)。在web api中,所有的sigatures都像Get或Put或Post。我希望能够说出像" url:../删除"并调用相应的删除获取或发布。我不希望必须通过传入的参数数量来区分我的方法,或者解析字符串以查看用户的意图。这些是失败的食谱

更新

Kenneth,lgor和Tu Hoang的答案都有关键信息需要合在一起(限制路线,动作,模型属性等方法),每个信息都有完整答案的信息。我无法将它们全部标记,所以我标记了最正确的#34;对于我的问题。

3 个答案:

答案 0 :(得分:4)

就个人而言,当您想要在您的操作上使用自定义路由时,我发现属性路由更容易使用。在官方ASP.NET网站上As exemplified,您可以使用[Route]属性将路由直接应用于您的操作:

e.g。

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来的,但它应该证明这个想法。

答案 1 :(得分:1)

您可以在action中指定routeTemplate占位符,就像在MVC中一样。请参阅下面的代码,我将Delete替换为{action}。如果你在参数之间是可选的,那么它可能会变得棘手,所以这里的顺序可能很关键,我希望它是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
    }
);
  

(来自评论)...带有样本方法签名

方法签名与任何其他签名一样。

// 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属性。我不会窃取他的答案,这是一个很好的答案,如果不是首选的话,也完全可以接受,视情况而定。

答案 2 :(得分:1)

如下所示?您需要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)
{
}