Как связать параметры MVC API в JSONP Get?

Я создал проект API-интерфейса MVC VS 2012 с нуля, загрузил Nuget "WebApiContrib.Formatting.Jsonp", добавил маршрут, средство форматирования и попытался отправить параметры в виде сериализованного JSON в виде запроса JSONP. Как определить или получить доступ к этим параметрам в контроллере?

WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}/{format}",
    defaults: new { id = RouteParameter.Optional, 
        format = RouteParameter.Optional }
);
config.Formatters.Insert(0, new JsonpMediaTypeFormatter());

Метод API:

public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

JQuery:

$.ajax({
    type: 'GET',
    url: '/api/Values',
    data: JSON.stringify({ "message": "\"Hello World\"" }),
    contentType: "application/json; charset=utf-8",
    dataType: 'jsonp',
    success: function (json) {
        console.dir(json.sites);
    },
    error: function (e) {
        console.log(e.message);
    }
});

Я попытался изменить метод Api, чтобы включить:

Get( [FromUri] string value)
Get( [FromBody] string value)
Get( CustomClass stuff)
Get( [FromUri] CustomClass stuff)
Get( [FromBody] CustomClass stuff)

Где CustomClass определяется как:

public class CustomClass
{
    public string message { get; set; }
}

Пока что ни один из них не дает ничего, кроме нуля для параметров. Как мне соединить эти параметры с объектом, размещенным в строке запроса?

РЕДАКТИРОВАТЬ:

Я могу обмануть его, изменив JJuery Ajax так:

data: {"value":JSON.stringify({ "message": "\"Hello World\"" })}

для которого я могу de-stringify [FromUri] string value и получить мой строго типизированный объект.

Тем не менее, я ожидаю, что механизм связывания данных десериализует параметры в строго типизированные объекты. Какая техника делает это возможным?

1 ответ

Решение

Вы делаете GET запрос и в случае GET В запросе нет тела, только URI. Все данные, которые вы предоставляете для $.ajax() вызов будет помещен в URI, например, ваша версия EDIT сгенерирует URI следующим образом:

.../api/Values?value=%7B%22message%22%3A%22%5C%22Hello%20World%5C%22%22%7D

(обратите внимание, что JSON будет также кодироваться в URL).

Теперь параметры URI в Web API связываются с использованием ModelBinderParameterBindingЭто означает, что веб-API не будет использовать какие-либо MediaTypeFormatter (который выводит сложные типы), но ModelBinder/ValueProvider (который в этом случае будет выводить простой тип - строка).

Вы можете подойти к вашему сценарию, внедрив ModelBinder (не забудьте использовать надлежащие классы и интерфейсы из пространств имен ASP.NET Web API, а не из ASP.NET MVC):

public class JsonModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == null)
            return false;

        bindingContext.Model = JsonConvert.DeserializeObject(valueProviderResult.AttemptedValue, bindingContext.ModelType);

        return true;
    }
}

public class JsonModelBinderProvider : ModelBinderProvider
{
    public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        return new JsonModelBinder();
    }
}

И прикрепив его к вашему параметру с помощью ModelBinderAttribute:

public IEnumerable<string> Get([ModelBinder(typeof(JsonModelBinderProvider))]CustomClass value)
{
    return new string[] { "value1", "value2" };
}

Вы можете найти более подробную информацию о предмете здесь:

Другие вопросы по тегам