141

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

我考虑了几种方法:

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

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

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

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

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

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

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

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

4

12 回答 12

149

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

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

例子:

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

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

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

于 2014-11-04T20:07:01.093 回答
49

只需向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 
于 2013-05-14T22:19:00.007 回答
45

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

在控制器中,我使用了C# 中 URL 拆分的提示?

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

我希望这有帮助...

于 2012-09-26T08:04:18.397 回答
39

我在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
    }
}
于 2013-08-22T09:56:03.417 回答
10

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

于 2012-06-07T19:15:06.307 回答
9

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

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

这不是用户友好SEO 友好的

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

这是通常的首选方法。

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

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

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

api/controller?start=date1&end=date2

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

api/controller/date1,date2
于 2012-06-08T10:53:41.647 回答
8

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

于 2013-10-19T03:36:19.347 回答
4
 [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 函数参数(one, two) 应该相同

于 2018-08-23T13:20:15.010 回答
2

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

    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

结果:“找不到该测试”

于 2019-04-04T19:02:47.010 回答
2

现在你可以通过简单地使用来做到这一点

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

这将返回:“值:5 10”

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

于 2019-10-17T13:14:44.193 回答
0
    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");
            }
        }
    }
于 2019-02-15T07:45:23.870 回答
0

这段代码对我有用。然后我可以在 URL http://.../api/GetSomething?paramOne=1¶mTwo=2 上使用常规查询字符串

.NET 6 核心

[Route("api/GetSomething")]
public IActionResult GetSomething(int paramOne, int paramTwo)
{
    ...    
    return Content(jsonData);
}

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

于 2022-02-15T16:47:00.627 回答