ASP.Net Web API 模型绑定不像在 MVC 3 中那样工作



我的印象是,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; }
        }
        
    }
}

相关内容

  • 没有找到相关文章

最新更新