如何在同一个控制器中使用不同的参数调用不同的GET方法?

时间:2013-06-06 17:38:50

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

我有一个包含两个不同Get方法的Controller。一个获取int值,而另一个获取String值,如下所示:

public class AccountController : ApiController
{
    public String GetInfoByString(String sUserInput)
    {
        return "GetInfoByString received: " + sUserInput;
    }

    public String GetInfoByInt(int iUserInput)
    {
        return "GetInfoByInt received: " + iUserInput;
    }
}

我的RouteConfig.cs未受影响,如下所示:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

我的WebApiConfig.cs也未受影响,如下所示:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

我希望能够使用以下链接点击Web API:

// Hit GetInfoByInt
http://localhost:XXXX/api/account/1

// Hit GetInfoByString
http://localhost:XXXX/api/account/abc

我可以很好地打第一种情况,但每当我尝试击中第二种情况时,我都会收到以下错误:

<Error>
    <Message>The request is invalid.</Message>
        <MessageDetail>
            The parameters dictionary contains a null entry for parameter 'id' of 
            non-nullable type 'System.Int64' for method  'TestProject.String GetInfoByInt(Int64)' in 'TestProject.Controllers.AccountController'. 
            An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
        </MessageDetail>
 </Error>

根据用户是提供String还是int,有没有办法点击任何一种方法?我假设需要在RouteConfig或WebApiConfig中进行更改,但我不太确定如何处理此问题。也许这只是一个简单的解决方案吗?

此外,如果重要,我希望能够使用包含String'ABC123'等字母和数字的'123ABC'来点击GetInfoByString。 GetInfoByInt可以是'123'

我真的很想坚持使用一个控制器,而不是在可能的情况下将其拆分为多个控制器。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:4)

如果你想让两个动作分开,这是一种做事方式:

config.Routes.MapHttpRoute("GetAccountInfoByInt", "api/account/{iUserInput}", new { controller = "account", action = "GetInfoByInt" }, new { iUserInput = @"\d+" });
config.Routes.MapHttpRoute("GetAccountInfoByString", "api/account/{sUserInput}", new { controller = "account", action = "GetInfoByString" });

请注意,我们计划通过在下一版本的Web API中引入属性路由来使这种事情变得更容易:

https://aspnetwebstack.codeplex.com/wikipage?title=Attribute%20routing%20in%20Web%20API

如果您愿意使用我们的夜间版本,它应该已经可用。那么你所要做的就是添加一些属性:

[HttpGet("api/account/{sUserInput}")]
public String GetInfoByString(String sUserInput)

[HttpGet("api/account/{iUserInput:int}")]
public String GetInfoByInt(int iUserInput)

答案 1 :(得分:1)

以下代码适用于我,请注意 ActionName HttpGet 属性,也不需要在配置中定义操作参数API。

public class AccountController : ApiController
{
    [HttpGet]
    [ActionName("GetInfoByString")]
    public String GetInfoByString(String sUserInput)
    {
        return "GetInfoByString received: " + sUserInput;
    }

    [HttpGet]
    [ActionName("GetInfoByInt")]
    public String GetInfoByInt(int iUserInput)
    {
        return "GetInfoByInt received: " + iUserInput;
    }
}

在Config for Api中执行相同操作

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapHttpRoute("DrawWebService",
                "api/{controller}/{action}/{value}",
                new { value = System.Web.Http.RouteParameter.Optional });

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

答案 2 :(得分:0)

克服此限制的一种方法是使用可空参数,例如

public ActionResult GetInfo(string sUserInput, int? iUserInput)

...并使您的逻辑符合非空值。

答案 3 :(得分:0)

解决方法是使用可为空的参数或尝试将字符串解析为整数然后符合条件。

public ActionResult GetInfo(string sUserInput)
{
    var result = sUserInput.IsInt
        ? GetInfoByInt(int.Parse(sUserInput))
        : GetInfoByString(sUserInput)
    return result;
}