ASP.NET WebApi - 具有类似操作方法的两个控制器

时间:2014-01-03 20:42:32

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

我有一个场景,我有2个不同的控制器,每个控制器都有多个Get方法。我有使用ActionName属性修饰的方法,但路由不能正常工作。

的ContactController

public ContactModel GetContactByID(string id)
{
    ...
}

[ActionName("username")]
public ContactModel GetContactByUserName(string text)
{
    ...
}

PaymentController

public PaymentModel Get(Guid id)
{
    ...
}

[HttpGet, ActionName("sale")]
public PaymentActivityModel Sale(Guid id)
{
    ...
}

路线

config.Routes.MapHttpRoute(
    "PaymentControllerActionId", 
    "api/client/{clientId}/{controller}/{action}/{id}", 
    defaults: null 
);

config.Routes.MapHttpRoute(
    "ContactControllerActionText", 
    "api/client/{clientId}/{controller}/{action}/{text}", 
    defaults: null
);

config.Routes.MapHttpRoute(
    "ClientControllerId", 
    "api/client/{clientId}/{controller}/{id}", 
    new { id = RouteParameter.Optional }
);

当我导航到付款时,它运行正常。但是当我导航到联系人时,我会收到:

  

找不到与请求URI匹配的HTTP资源,... / api / client /.../ contact / username / exampleUserName

     

在与请求匹配的控制器“联系人”上未找到任何操作。

我认为参数名称会与操作名称(textid)匹配。

问题是,使用Guid个ID且使用string个ID?

这是一个面向客户端的API,我有一个客户端友好的ContactID是一个字符串。而PaymentID是Guid。

2 个答案:

答案 0 :(得分:0)

首先,我想指出你的路线没有多大意义。

此路由表示它适用于PaymentControllerActionId,但是您将路由打开以使用任何控制器,而不是指定它仅用于支付控制器。

config.Routes.MapHttpRoute(
    "PaymentControllerActionId", 
    "api/client/{clientId}/{controller}/{action}/{id}", 
    defaults: null 
);

回答你的问题。您可能需要将{text}指定为可选的RouteParameter。否则,框架通常期望您已经定义了自定义路由约束(并且您应该在{clientId} IMO上设置路由约束。)

此外,如果您的某个操作需要GUID。将它作为Guid参数类型,WebAPI将正确匹配它。或者,由于两个函数都需要名称或guid,因此您只能使用一个带字符串的函数,并在数据库中执行与GUID或NAME匹配的select语句并返回联系。更少的代码,更容易阅读,更有意义。

答案 1 :(得分:0)

如果您使用的是Web API 2,则可以使用属性路由来实现此目的。

在下面的示例中,控制器使用传统+属性路由的混合,但是如果需要,您可以将其更改为仅通过属性路由。

示例:

路线配置

config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
    "ClientControllerId", 
    "api/client/{clientId}/{controller}/{id}", 
    new { id = RouteParameter.Optional }
);

<强>的ContactController

[RoutePrefix("api/client/{clientId}/Contact")]
public class ContactController
{
    // this uses conventional route
    public ContactModel GetContactByID(string id)
    {
        ...
    }

    [Route("username/{userName}")]
    public ContactModel GetContactByUserName(string userName)
    {
        ...
    }
}

<强> PaymentController

[RoutePrefix("api/client/{clientId}/Payment")]
public class PaymentController
{
    // this uses conventional route
    public PaymentModel Get(Guid id)
    {
        ...
    }

    [HttpGet, Route("sale/{id}")]
    public PaymentActivityModel Sale(Guid id)
    {
        ...
    }
}