【问题标题】:How can I call different GET Methods in the same Controller utilizing different parameters?如何使用不同的参数在同一个控制器中调用不同的 GET 方法?
【发布时间】:2013-06-02 20:20:11
【问题描述】:

我有一个控制器,它包含两个不同的 Get 方法。一个采用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>

有没有办法根据用户提供Stringint 来点击Get 方法?我假设需要在 RouteConfig 或 WebApiConfig 中进行更改,但我不太确定如何解决这个问题。也许这毕竟只是一个简单的解决方案?

另外,如果重要的话,我希望能够使用包含字母和数字的 String 来访问 GetInfoByString,例如 'ABC123''123ABC'。 GetInfoByInt 可以是 '123'

如果可能的话,我真的很想坚持一个控制器,而不是把它分成多个控制器。

提前感谢您的帮助。

【问题讨论】:

  • 一个 Get 意味着被 web 请求击中,而另一个意味着被其他控制器或代码击中?为什么每个都需要一个 Get 方法?在调用方法之前,只需保留字符串 1 并在 int 中运行 ToString()。
  • 如果您只有两种方法,另一种“hack”是将 HttpGet 属性应用于其中一种方法。
  • 如果你完成了这个,你必须确保没有有效的字符串标识符可以被解析为整数。例如,如果这是用户生成的,并且有人创建了一个字符串标识符“1”,它将路由到整数方法。

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


【解决方案1】:

如果您想将这两个操作分开,这是一种处理方式:

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)

【讨论】:

    【解决方案2】:

    以下代码适用于我,注意 ActionNameHttpGet 属性,也不是在您需要定义 action 参数的配置中接口。

    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 }
        );
    }
    

    【讨论】:

      【解决方案3】:

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

      public ActionResult GetInfo(string sUserInput, int? iUserInput)
      

      ...并将您的逻辑限定为非空值。

      【讨论】:

        【解决方案4】:

        一种解决方法是使用可为空的参数或尝试将字符串解析为整数然后限定。

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

        【讨论】:

          猜你喜欢
          • 2022-11-09
          • 2014-08-01
          • 2021-07-26
          • 2014-11-29
          • 2018-09-10
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 2019-04-20
          相关资源
          最近更新 更多