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

 
     
 
    } 
 
}