25

我的印象是,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 中一样。

4

2 回答 2

26

看看这个:WebAPI如何做参数绑定

您需要像这样装饰您的复杂参数:

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

或者

public IEnumerable<string> Get([ModelBinder] SearchModel searchSearchModel)
于 2012-06-02T17:17:49.643 回答
1

我发现整个 Web API 2 是一个困难的学习曲线,有很多“陷阱”。我已经阅读了一些关键书籍,这些书籍涵盖了这个丰富的产品提供的许多奥秘的细微差别。但基本上,我认为必须有一些核心功能可以利用最好的功能。所以,我着手做四项直截了当的任务。1. 接受来自浏览器的查询字符串到 Api2 客户端并填充一个简单的 .NET 模型。2. 让客户端向 Api2 服务器提交一个异步Post,该 Api2 服务器以从先前模型 3 中提取的 JSON 编码。让服务器对来自客户端的 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; }
        }

        
    }
}

于 2015-05-11T20:49:05.660 回答