ASP.NET MVC 4中的多个HttpRoute

时间:2012-11-21 12:59:22

标签: asp.net-mvc-4 routes asp.net-web-api

我正在尝试在Web API中创建一个RouteConfig,它允许以下模式:

模式:

/api/{controller}
/api/{controller}/{id} (int, optional)

/api/{controller}/{action}
/api/{controller}/{action}/{id} (int, optional)

用例:

/api/profile/ (get all profiles)
/api/profile/13 (get profile number 13)

/api/profile/sendemail/ (send email to all profiles)
/api/profile/sendmail/13 (send email to profile number 13)

我正在尝试的是以下内容:

routes.MapHttpRoute(
    name: "ControllerAndID",
    routeTemplate: "api/{controller}/{id}",
    defaults: null,
    constraints: new { id = @"^\d+$" } // Dekkar heiltölur eingöngu í id parameter
);

routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { action = "Get", id = RouteParameter.Optional }
);

我得到的错误是:

  

找到与请求匹配的多个操作:   \ r \ nMinarSidur.Models.DataTransfer.UserProfileDTO sendmail(System.String)   在类型上   MinarSidur.Controllers.ProfileController \ r \ nMinarSidur.Models.DataTransfer.UserProfileDTO   sendpaycheck(System.String)类型MinarSidur.Controllers.ProfileController

你能帮我完成吗?

2 个答案:

答案 0 :(得分:1)

您的异常实际上抱怨他们在Profile控制器上的这两种方法之间存在冲突:

  • sendpaycheck(字符串)
  • sendmail的(字符串)

不是Get and Get(?);虽然这也是一个问题。

实际上,在执行进行更改或触发操作的RPC操作时,您应该使用POST动词。这样做可以解决上面提到的路由问题。

<强>更新

您是否考虑过针对您问题的更加以资源为中心的方法?在所有情况下,资源都是“Profile”,它似乎具有唯一的id。它似乎还有另外两个可能的唯一id的电子邮件和ssn?

如果这些是您可以接受的URL

http://localhost/api/profile
http://localhost/api/profile/x
http://localhost/api/profile/?email=myemail@x.com
http://localhost/api/profile/?ssn=x

你可以使用:

public class ProfileController : ApiController
{
    public string Get(int id)
    {
        return string.Format("http://localhost/api/profile/{0}", id);
    }

    public string Get([FromUri] string email = null, [FromUri] int? ssn = null)
    {
        if (!string.IsNullOrEmpty(email))
        {
            return string.Format("http://localhost/api/profile/?email={0}", email);
        }

        if (ssn.HasValue)
        {
            return string.Format("http://localhost/api/profile/?ssn={0}", ssn.Value);
        }

        return "http://localhost/api/profile";
    }
}

只使用标准的webapi路由:

 config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }

<强>但是

如果您确实想继续使用/ email和/ ssn,则可能会遇到电子邮件问题...特别是“。”在电子邮件地址中,这可能会混淆路由引擎...为此,您必须设置一个尾部斜杠,即http://localhost/api/profile/email/me@me.com/我认为您会发现http://localhost/api/profile/email/me@me.com无效。

这支持:

http://localhost/api/profile
http://localhost/api/profile/x
http://localhost/api/profile/email/myemail@x.com/
http://localhost/api/profile/ssn/x

我会尝试这个并使用(NB。使用名称 rpcId 来区分路线):

public class ProfileController : ApiController
{
    public string Get(int id)
    {
        return string.Format("http://localhost/api/profile/{0}", id);
    }

    public string Get()
    {
        return "http://localhost/api/profile";
    }

    [HttpGet]
    public string Ssn(int rpcId)
    {
        return string.Format("http://localhost/api/profile/ssn/{0}", rpcId);

    }

    [HttpGet]
    public string Email(string rpcId)
    {
        return string.Format("http://localhost/api/profile/email/{0}", rpcId);

    }
}

我的路由将是:

       config.Routes.MapHttpRoute(
         name: "ProfileRestApi",
         routeTemplate: "api/profile/{id}",
         defaults: new { id = RouteParameter.Optional, Controller = "Profile" }
         );


        config.Routes.MapHttpRoute(
            name: "PrfileRpcApi",
            routeTemplate: "api/profile/{action}/{rpcId}",
            defaults: new { Controller = "Profile" }
        );

答案 1 :(得分:0)

规则重叠。路由中Id的验证是否会造成巨大损失?在Get操作中,您仍然可以将Id参数作为int。如果是这种情况,我认为您可以完全删除ControllerAndID ,只需使用与您的所有用例匹配的第二个。