为什么我必须指定[FromUri]才能使它起作用?

5

我是使用Asp.NET WebApi,有一件事情让我感到困惑,那就是请求绑定。

我有这个ViewModel:

[DataContract(Name="Store")]
public class StoreDm
{
    [DataMember(IsRequired = true)]
    [MinLength(3)]
    public string Name { get; set; }

    [DataMember(IsRequired = true)]
    public double Latitude { get; set; }

    [DataMember(IsRequired = true)]
    public double Longitude { get; set; }
}

public HttpResponseMessage GetStoreNames(StoreDm vm)
{
    if (ModelState.IsValid)
    {

    }
}

RestClient c = new RestClient("http://localhost:3333/api/store");
RestRequest r = new RestRequest("/GetStoreNames", Method.GET);
r.AddParameter("Name", autoComplete);
r.AddParameter("Latitude", "4");
r.AddParameter("Longitude", "-7");
var d =  c.BuildUri(r);
c.ExecuteAsync(r, response2 =>
  {
      var content = response2.Content;
  });

我的 StoreDm 为空。

我无法理解这个问题。首先,我在所有属性上设置了 IsRequired,但出于某种原因 ModelState 认为 “null” 的 ViewModel 是有效的。

其次,我不明白为什么它是 null。我必须添加 [FromUri] 才能绑定它。如果这是一个 Post 请求,并且有人使用 Fiddler 请求正文会发生什么。

如果我被迫放置 [FromUri],那么我认为 Fiddler 正文请求将无法工作。

如何使两个请求都正常通过并正确绑定?


如果有人进行了POST操作,它将命中不同的动作方法,而该方法将不具备FromUri。 - Darrel Miller
1个回答

11

Web API参数绑定(摘自此处:路由和操作选择)的作用:

参数绑定。参数绑定是Web API为参数创建值的方式。下面是参数绑定的默认规则:

  • 简单类型参数从URI中获取。
  • 复杂类型参数从请求正文中获取。

因此,任何复杂类型(如类StoreDm)默认情况下都应该是请求正文的一部分。

如标准定义中所述超文本传输协议4.3消息主体

请求和响应中允许消息主体的规则有所不同。如果请求的消息头中包含Content-Length或Transfer-Encoding标头字段,则请求中包含消息主体。如果请求方法(第5.1.1节)的规范不允许在请求中发送实体主体,则请求中不能包含消息主体。因此,虽然Web API提供了一些常见的功能,但它试图是通用的。可能会有带有或不带有消息主体的请求。因此,具有此功能,操作选择和参数绑定是通用的,而不需要推断“当前”请求的特定设置,甚至是显而易见的设置(我们认为,GET将始终在URI中具有所有参数(StoreDm对象的属性)...但引擎不会这样做)POST会自动绑定StoreDm,因为它的属性将在主体中找到,这是复杂对象的标准绑定。
GET方法违反了规则,属性(复杂类型)都在URI中,因此我们只需要通知框架:[FromUri]。在其他情况下,将找到方法,null(绑定自消息体)将被传递。

因为设计上假定可能没有消息体,所以所有“复杂获取”都需要在其中加入[FromUri]。但仍然不太清楚为什么Get如此特殊,不能像POST一样工作。如果有人通过正文传递GET会发生什么?如果您为GET传递了正文,则无法绑定,这有点糟糕。 - chobo2
如果我通过URI传递给Post构建,则它不会绑定?Get是从什么自动构建的,所以什么都没有? - chobo2
是的,如果我们在URI中传递任何内容,除非它是SimpleType或标记为[FromUri],否则它不会被绑定。机制确实是相同的。不同之处只在于数据传递的方式。因为它完全不同,所以我们必须通知API。因此,我们可以为Get(myobject)Post(myobject)编写类似的代码...但在Get的情况下,我们将通知API应该从作为URI部分发送的数据构建它。 - Radim Köhler
如果我在GET中使用[FromBody],是否会带来像POST一样的优势?我猜在我的API文档中,对于GET请求,我必须指定需要构建URI吗?对于Post,如果他们发送了一个URI而不是BODY,它会绑定吗?现在考虑到这一点,当处理复杂对象时,我还必须始终检查NULL,因为在这种情况下似乎Model State没有得到更新。 - chobo2
你看,我在我的GET请求中有参数,想知道将这些参数传递给服务器的最佳方法是什么。 - chobo2
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接