Вопрос по – Привязка модели ASP.Net Web API работает не так, как в MVC 3

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.

Может быть, вам в этом поможет [post] [1] проблема. [1]:stackoverflow.com/questions/12072277/… Cagdas

Ваш Ответ

2   ответа
26

Взгляните на это:Как WebAPI связывает параметры

Вам нужно украсить ваш сложный параметр следующим образом:

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

ИЛИ ЖЕ

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

Я обнаружил, что весь Web API 2 представляет собой сложную учебную кривую с большим количеством «Gotchas». Я прочитал несколько ключевых книг, которые раскрывают многие тайные нюансы этого богатого предложения продуктов. Но в основном я думал, что должна быть какая-то базовая функциональность, которая могла бы использовать все преимущества лучших функций. Итак, я решил выполнить четыре простых задания. 1. Примите строку запроса из браузера в клиент Api2 и заполните простую модель .NET. 2. Попросите Клиента представитьasync Запись на сервер Api2, закодированный в JSON, извлеченный из предыдущей модели 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; }
        }

        
    }
}

Похожие вопросы