我的印象是,ASP.Net Web API 中的模型绑定应该支持具有与 MVC 支持的相同最低功能级别的绑定。
以以下控制器为例:
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 中一样,那就太好了。
看看这个: WebAPI 如何进行参数绑定
您需要像这样装饰您的复杂参数:
public IEnumerable<string> Get([FromUri] SearchModel searchSearchModel)
或
public IEnumerable<string> Get([ModelBinder] SearchModel searchSearchModel)
我发现整个 Web API 2 是一个困难的学习曲线,有很多"陷阱" 我读了一些关键书籍,涵盖了这个丰富产品的许多神秘细微差别。但基本上,我认为必须有一些核心功能可以利用最好的功能。因此,我开始做四个直接的任务。1. 接受来自浏览器的查询字符串到 Api2 客户端中,并填充简单的 .NET 模型。2. 让客户端将异步发布提交到以从先前模型中提取的 JSON 编码的 Api2 服务器3. 让服务器对来自客户端的 post 请求进行简单的转换。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; }
}
}
}