我应该如何将多个参数传递给 ASP.Net Web API GET?

Posted

技术标签:

【中文标题】我应该如何将多个参数传递给 ASP.Net Web API GET?【英文标题】:How should I pass multiple parameters to an ASP.Net Web API GET? 【发布时间】:2012-06-11 20:16:20 【问题描述】:

我正在使用 .Net MVC4 Web API 来(希望)实现一个 RESTful api。我需要将一些参数传递给系统并让它执行一些操作,然后返回一个对象列表作为结果。具体来说,我传递了两个日期并返回它们之间的记录。我还在跟踪返回的记录,以便后续调用不会在系统中重新处理。

我考虑了几种方法:

    将参数序列化为一个 JSON 字符串并在 API 中将其分开。 http://forums.asp.net/t/1807316.aspx/1

    在查询字符串中传递参数。What is best way to pass multiple query parameters to a restful api?

    在路由中定义参数: api/controller/date1/date2

    使用本来就可以让我通过参数传递对象的 POST。

    正在研究 ODATA,因为 Web API(当前)支持它。我还没有做太多,所以我对它不是很熟悉。

似乎正确的 REST 实践表明何时提取数据,您应该使用 GET。但是,GET也应该是无效的(不会产生副作用),我想知道我的具体实现是否违反了这一点,因为我在API系统中标记了记录,因此我产生了副作用。

这也让我想到了支持可变参数的问题。如果输入参数列表发生变化,如果这种情况经常发生,则必须为选择 3 重新定义路由将是很乏味的。如果在运行时定义参数可能会发生什么......

无论如何,对于我的具体实现,哪种选择(如果有)似乎最好?

【问题讨论】:

【参考方案1】:

这个记录标记是什么意思?如果这仅用于记录目的,我将使用 GET 并禁用所有缓存,因为您想记录此资源的每个查询。如果记录标记有其他目的,则 POST 是要走的路。用户应该知道,他的行为会影响系统,POST 方法是一个警告。

【讨论】:

通过标记我的意思是简单地跟踪哪些记录被处理和返回,以便后续调用不会重复它们。就我而言,我只是在另一个表中插入以跟踪哪些已处理。 现在我确实将它实现为 POST,主要是因为你说的原因——动作发生并且消费者知道它们。另外,它似乎很容易和最灵活地传递不同的数据。 @sig606:POST 是我的最佳选择,但您的协议似乎并不安全。如果发生某些事情并且在客户端检索了记录,但由于错误而未处理怎么办?您将不再返回它们,客户将丢失数据。 现在我的 API 只返回处理后的记录。所以消费者向 API 传递了两个日期。这两个日期之间的记录将被处理和标记。然后数据返回给调用者。我想如果在处理过程中或处理之后在到达客户之前发生了一些事情,我就有问题了。【参考方案2】:

@LukLed 清楚地解释了使用 GETPOST。关于传递参数的方式,我建议使用第二种方法(我对 ODATA 也不太了解)。

1.将参数序列化为一个 JSON 字符串并在 API 中将其分开。 http://forums.asp.net/t/1807316.aspx/1

这不是用户友好的SEO友好的

2.传递查询字符串中的参数。将多个查询参数传递给 restful api 的最佳方法是什么?

这是通常的首选方法。

3.定义路由中的参数:api/controller/date1/date2

这绝对不是一个好方法。这让人觉得有些date2date1 的子资源,但事实并非如此。 date1date2 都是查询参数,属于同一级别。

在简单的情况下,我会建议这样的 URI,

api/controller?start=date1&end=date2

但我个人喜欢下面的 URI 模式,但在这种情况下,我们必须编写一些自定义代码来映射参数。

api/controller/date1,date2

【讨论】:

其实,这些都是我的原始解释。我认为 LukLed 照亮了我的标签和 URL 链接。 就 SEO 而言,在这种情况下不适用。这段代码将是“服务器到服务器”,所以我不在乎外界是否发现了它。事实上,我必须确保采取适当的安全措施来避免随机访问。我必须对系统的另一部分进行 JSON 序列化(似乎是一个错误,试图发布大的 obj 列表,所以我必须序列化为字符串),所以在这种情况下不会有太大的延伸. 我希望你已经有了答案,那么你为什么要问这个问题? 抱歉,马克,回复晚了。我尝试了一些解决方案,但不确定哪个是最好的,并试图坚持行业标准的方法,所以我在 SO 上发布了。 @Mark 类似下一个:***.com/questions/9681658/…?【参考方案3】:

我只需要在需要传递参数的地方实现一个 RESTfull api。我通过传递查询字符串中的参数以与 Mark 的第一个示例“api/controller?start=date1&end=date2”所描述的相同的样式来做到这一点

在控制器中,我使用了来自 URL split in C#? 的提示

// uri: /api/courses
public IEnumerable<Course> Get()

    NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
    var system = nvc["System"];
    // BL comes here
    return _courses;

在我的情况下,我通过 Ajax 调用 WebApi,如下所示:

$.ajax(
        url: '/api/DbMetaData',
        type: 'GET',
        data:  system : 'My System',
                searchString: '123' ,
        dataType: 'json',
        success: function (data) 
                  $.each(data, function (index, v) 
                  alert(index + ': ' + v.name);
                  );
         ,
         statusCode: 
                  404: function () 
                       alert('Failed');
                       
        
   );

我希望这会有所帮助...

【讨论】:

我猜您没有使用 WebApi,因为 ParameterBinding 会自动将您的查询字符串映射到您的 api 方法参数... 是的,更好的方法是使用 [Route("api/DbMetaData/system/searchString")] 之类的属性,然后将参数添加到 Get(string system, string searchString),然后用“...api/DbMetaData/mysystem/mysearchstring”调用 我在我的 C# MVC WebApi 中使用了他的示例,它运行良好。例如 +1【参考方案4】:

只需向WebApiConfig 条目添加一条新路由即可。

例如,调用:

public IEnumerable<SampleObject> Get(int pageNumber, int pageSize)  ..

添加:

config.Routes.MapHttpRoute(
    name: "GetPagedData",
    routeTemplate: "api/controller/pageNumber/pageSize"
);

然后将参数添加到HTTP调用中:

GET //<service address>/Api/Data/2/10 

【讨论】:

这似乎是列出所有部分的唯一答案。我希望有人更好地描述如何使用 api/controller?start=date1&amp;end=date2 样式 URI。 @Hot Licks Andrew Veriga 的答案适用于查询字符串参数。本质上,您将查询字符串名称绑定到类属性并将它们传递给您的方法。您的方法将采用一个标有 [FromUri] 属性的类参数,并将您的查询字符串参数作为其属性。 好东西。谢谢! 嗨@HotLicks 和GrahamWright 你认为你可以回答这个问题吗?谢谢,***.com/questions/57565318/…【参考方案5】:

我在http://habrahabr.ru/post/164945/找到了很好的解决方案

public class ResourceQuery

   public string Param1  get; set; 
   public int OptionalParam2  get; set; 


public class SampleResourceController : ApiController

    public SampleResourceModel Get([FromUri] ResourceQuery query)
    
        // action
    

【讨论】:

这里的线索是[FromUri] 虽然这篇文章是俄语的,但@tranceporter 是对的。 “FromUri”看起来是从 url 获取参数的好方法。另一篇可能有用的文章:asp.net/web-api/overview/formats-and-model-binding/… 这是我长期以来一直在做的事情,而且效果很好!我也推荐这个解决方案。 如果你调用另一个辅助方法(不是Get),你还能使用[FromUri]吗?我似乎无法让它发挥作用。【参考方案6】:

使用这里完整描述的参数绑定:http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

【讨论】:

【参考方案7】:

我认为最简单的方法是简单地使用AttributeRouting

在您的控制器中很明显,您为什么要在全局 WebApiConfig 文件中使用它?

例子:

    [Route("api/YOURCONTROLLER/paramOne/paramTwo")]
    public string Get(int paramOne, int paramTwo)
    
        return "The [Route] with multiple params worked";
    

名称需要与您的参数匹配。

就这么简单,现在你有一个单独的GET 来处理这个实例中的多个参数。

【讨论】:

这很棒。大多数人建议在WebApiConfig文件中设置路由,但这确实更好。 确实,我们(大多数人)确实建议为您的配置设置一个集中管理区域。对于 Web API(Microsoft 或其他),REST 的集中式模式是关键。属性路由很可爱,但它让一次性异常太诱人了。 同意,我实际上需要更新我的答案。使用 GET 处理多个参数有更好的方法。当我对 WebAPI 较新时发布了这个,现在我不使用 AttributeRouting(除非我只是不想创建新的控制器),并在 QueryString 中传递所有参数,它们会自动映射。当我有机会时更新,这样人们就不会使用这种旧方法 有没有办法为命名参数(例如查询参数)设置Route 如果需要操作方法名称,可以对其进行修改以适应这种情况。 [Route("api/YOURCONTROLLER/Get/paramOne/paramTwo")] public string Get(int paramOne, int paramTwo) return "something"; 【参考方案8】:
 [Route("api/controller/one/two")]
    public string Get(int One, int Two)
    
        return "both params of the root link(one,two) and Get function parameters (one, two)  should be same ";
    

根链接的参数(one,two)和Get函数参数(一,二)应该相同

【讨论】:

【参考方案9】:
    public HttpResponseMessage Get(int id,string numb)
    
        //this will differ according to your entity name
        using (MarketEntities entities = new MarketEntities())
        
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            
            else
            
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            
        
    

【讨论】:

【参考方案10】:

我知道这真的很老了,但我最近也想要同样的东西,这就是我发现的......

    public HttpResponseMessage Get([FromUri] string var, [FromUri] string test) 
        var retStr = new HttpResponseMessage(HttpStatusCode.OK);
        if (var.ToLower() == "getnew" && test.ToLower() == "test") 
            retStr.Content = new StringContent("Found Test", System.Text.Encoding.UTF8, "text/plain");
         else 
            retStr.Content = new StringContent("Couldn't Find that test", System.Text.Encoding.UTF8, "text/plain");
        

        return retStr;
    

所以现在在你的地址/URI/...

http(s)://myURL/api/myController/?var=getnew&test=test

结果:“找到测试”


http(s)://myURL/api/myController/?var=getnew&test=anything

结果:“找不到那个测试”

【讨论】:

我个人喜欢 C# 中的这种风格,因为我可以更改原始方法的签名,并重载我想要完成的任务,而无需调整路由配置。希望它可以帮助其他习惯于这种(可能是过时的)发出 GET 请求的方法的人。 我不得不创建一个由第三方日历应用程序使用的事件 API,该应用程序使用这种方法。我很高兴找到了这个答案!【参考方案11】:

现在您只需使用即可做到这一点

        public string Get(int id, int abc)
        
            return "value: " + id + "  " + abc;
        

这将返回:“值:5 10”

如果你调用它https://yourdomain/api/yourcontroller?id=5&abc=10

【讨论】:

【参考方案12】:

此代码对我有用。然后我可以在 url 上使用常规查询字符串 http://.../api/GetSomething?paramOne=1&paramTwo=2

.NET 6 核心

[Route("api/GetSomething")]
public IActionResult GetSomething(int paramOne, int paramTwo)

    ...    
    return Content(jsonData);


而不是执行以下操作 [Route("api/GetSomething/paramOne/paramTwo")]

【讨论】:

以上是关于我应该如何将多个参数传递给 ASP.Net Web API GET?的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个参数传递给 ASP.NET Core 中的 get 方法

如何将多个参数传递给 ASP.NET CORE MVC 中的 HttpGet 方法?

如何使用 vba 将参数传递给 asp.net web api?

如何通过asp.net schtasks将参数传递给bat文件

如何将模型作为参数传递给 ASP.NET MVC 中的 [HttpPost] ActionMethod?

如何将参数传递给 ASP.NET MVC 中的局部视图?