25

我的印象是,ASP.Net Web API中的模型绑定应该支持与MVC支持的最低级别的功能绑定。ASP.Net Web API模型绑定在MVC中不起作用3

采取以下控制器:

public class WordsController : ApiController 
{ 
    private string[] _words = new [] { "apple", "ball", "cat", "dog" }; 

    public IEnumerable<string> Get(SearchModel searchSearchModel) 
    { 
     return _words 
      .Where(w => w.Contains(searchSearchModel.Search)) 
      .Take(searchSearchModel.Max); 
    } 
} 

public class SearchModel 
{ 
    public string Search { get; set; } 
    public int Max { get; set; } 
} 

我与请求它:

http://localhost:62855/api/words?search=a&max=2 

不幸的是,模型不绑定,因为它会在MVC。为什么这不像我所期望的那样具有约束力?我将在我的应用程序中有很多不同的模型类型。如果绑定正常工作就好了,就像在MVC中一样。

+0

也许帮助你,这[文章] [1]的问题。 [1]:http://stackoverflow.com/questions/12072277/reading-fromuri-and-frombody-at-the-same-time – Cagdas

回答

27

看看这个:How WebAPI does Parameter Binding

你需要来装饰你的复杂的参数,如下所示:

public IEnumerable<string> Get([FromUri] SearchModel searchSearchModel) 

OR

public IEnumerable<string> Get([ModelBinder] SearchModel searchSearchModel) 
1

我发现整个Web API 2是一个困难的学习曲线,有很多“难题”我已经阅读了一些关于这个丰富的产品提供的许多奥妙细节的关键书籍。但基本上,我认为必须有一些核心功能可以利用最好的功能。所以,我着手做四个直接的任务。 1.接受来自浏览器的查询字符串到Api2客户端并填充一个简单的.NET模型。 2.让客户提交异步发布到从先前模型中提取的JSON编码的Api2服务器 3.让服务器对来自客户端的发布请求进行微小的转换。 4.将其全部传回浏览器。就是这个。

using System; 
 
using System.Collections.Generic; 
 
using System.Linq; 
 
using System.Net; 
 
using System.Net.Http; 
 
using System.Web.Http; 
 
using System.Threading.Tasks; 
 
using Newtonsoft.Json; 
 

 
namespace Combined.Controllers // This is an ASP.NET Web Api 2 Story 
 
{ 
 
    // Paste the following string in your browser -- the goal is to convert the last name to lower case 
 
    // The return the result to the browser--You cant click on this one. This is all Model based. No Primitives. 
 
    // It is on the Local IIS--not IIS Express. This can be set in Project->Properties=>Web http://localhost/Combined with a "Create Virtual Directory" 
 
    // http://localhost/Combined/api/Combined?FirstName=JIM&LastName=LENNANE // Paste this in your browser After the Default Page it displayed 
 
    // 
 
    public class CombinedController : ApiController 
 
    { 
 
     // GET: api/Combined This handels a simple Query String request from a Browser 
 
     // What is important here is that populating the model is from the URI values NOT the body which is hidden 
 
     public Task<HttpResponseMessage> Get([FromUri]FromBrowserModel fromBrowser) 
 
     { 
 
      // 
 
      // The Client looks at the query string pairs from the Browser 
 
      // Then gets them ready to send to the server 
 
      // 
 
      RequestToServerModel requestToServerModel = new RequestToServerModel(); 
 
      requestToServerModel.FirstName = fromBrowser.FirstName; 
 
      requestToServerModel.LastName = fromBrowser.LastName; 
 
      // Now the Client send the Request to the Server async and everyone awaits the Response 
 
      Task<HttpResponseMessage> response = PostAsyncToApi2Server("http://localhost/Combined/api/Combined", requestToServerModel); 
 
      return response; // The response from the Server should be sent back to the Browser from here. 
 
     } 
 
     async Task<HttpResponseMessage> PostAsyncToApi2Server(string uri, RequestToServerModel requestToServerModel) 
 
     { 
 
      using (var client = new HttpClient()) 
 
      { 
 
       // Here the Method waits for the Request to the Server to complete 
 
       return await client.PostAsJsonAsync(uri, requestToServerModel) 
 
        .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode()); 
 
      } 
 
     } 
 
     // POST: api/Combined This Handles the Inbound Post Request from the Client 
 
     // NOTICE THE [FromBody] Annotation. This is the key to extraction the model from the Body of the Post Request-- not the Uri ae in [FromUri] 
 
     // Also notice that there are no Async methods here. Not required, async would probably work also. 
 
     // 
 
     public HttpResponseMessage Post([FromBody]RequestToServerModel fromClient) 
 
     { 
 
      // 
 
      // Respond to an HttpClient request Synchronously 
 
      // The model is serialised into Json by specifying the Formatter Configuration.Formatters.JsonFormatter 
 
      // Prep the outbound response 
 
      ResponseToClientModel responseToClient = new ResponseToClientModel(); 
 
      // 
 
      // The conversion to lower case is done here using the Request Body Data Model 
 
      //    
 
      responseToClient.FirstName = fromClient.FirstName.ToLower(); 
 
      responseToClient.LastName = fromClient.LastName.ToLower(); 
 
      // 
 
      // The Client should be waiting patiently for this result 
 
      // 
 
      using (HttpResponseMessage response = new HttpResponseMessage()) 
 
      { 
 
       return this.Request.CreateResponse(HttpStatusCode.Created, responseToClient, Configuration.Formatters.JsonFormatter); // Respond only with the Status and the Model 
 
      } 
 
     } 
 
     public class FromBrowserModel 
 
     { 
 
      public string FirstName { get; set; } 
 
      public string LastName { get; set; } 
 
     } 
 
     public class RequestToServerModel 
 
     { 
 
      public string FirstName { get; set; } 
 
      public string LastName { get; set; } 
 
     } 
 

 
     public class ResponseToClientModel 
 
     { 
 
      public string FirstName { get; set; } 
 
      public string LastName { get; set; } 
 
     } 
 

 
     
 
    } 
 
}