2015-11-09 1 views
0

Я успешно создал простые объекты следующим образом.Как создать сложные объекты .net из json (javascript) в Asp.Net WebApi с помощью RequestCommand

json на стороне клиента js выглядит следующим образом.

{"Page":1, "Take":10, "SortOrder":"Asc", "PropName":"Id"} 

На стороне WebAPI, у меня есть следующий класс

public class PaginatedRequestCommand 
{ 

    public int Page { get; set; } 

    public int Take { get; set; } 

    public string PropName { get; set; } 

    public string SortOrder { get; set; } 
} 

А класс WebApiConfig выглядит следующим образом

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

    // skiped many other lines as they are not relevant 

     config.ParameterBindingRules.Insert(0, typeof(PaginatedRequestCommand), 
      x => x.BindWithAttribute(new FromUriAttribute())); 

    } 
} 

и поэтому в контроллере Wep Api я следующий метод действия ,

[HttpPost] 
    [HttpGet] 
    public PaginatedList<PatientCategory> PatCat(PaginatedRequestCommand cmd) 
    { 
    //...... 
} 

Так вот у меня есть объект PaginatedRequestCommand правильно построен и свойство страница, Take и т.д., правильно доступно. Angaljs ajax-звонок в браузере

$http({ 
      method: 'GET', 
      url: this.callParams.uri, // The URI 
      params: this.callParams.paginationOptions, // This is where the JSON that showed earlier goes. 
      headers: { 'Content-Type': 'application/Json' } 
}) 

Все, что до сих пор так хорошо.

Теперь я хочу передать еще несколько параметров. Я хочу включить массив в JSON следующим образом.

{"Page":1,"Take":10,"SortOrder":"Asc","PropName":"Id", 
    "wherePredicateParams": 
[{"propName":"Name","val":"s"}, 
{"propName":"Description","val":"h"} 
] 
} 

Итак, вы видите, что «wherePredicateParams» является дополнительным объектом, который я хочу передать. Его массив. Какие изменения мне нужно сделать на стороне WebApi?

Я попытался добавить еще одно свойство в классеPaginatedRequestCommand, публичная строка [] wherePredicateParams {получить; задавать; } , поэтому полный класс выглядит следующим образом.

public class PaginatedRequestCommand 
{ 

    public int Page { get; set; } 

    public int Take { get; set; } 

    public string PropName { get; set; } 

    public string SortOrder { get; set; } 

    public string[] wherePredicateParams { get; set; } 
} 

Это на самом деле работает, в том смысле, что свойство wherePredicateParams из PaginatedRequestCommand объекта, созданного с помощью API внутри метода действия вышеупомянутого контроллера предоставляет мне {"propName":"Name","val":"s"} и {"propName":"Description","val":"h"}. Но проблема в том, что я должен разбирать это сам и использовать. Есть ли способ лучше.

Затем я попытался изменить строку [] для whereParam [] и определили класс

public class whereParam 
{ 
    public string propName { get; set; } 
    public string val { get; set; } 
} 

enter image description here Так вы видите PROPNAME и Вэл равны нулю? Что мне не хватает?

ответ

0

После довольно борьбы, я нашел ответ. Проблема не на стороне webApi. Его на стороне клиента. Я использую AngularJS для вызова ajax. Так вот в чем проблема. Здесь я описываю это.

Обратите внимание: я изменил имена классов во время грубого расследования, поэтому теперь имя класса PaginatedRequestCommand будет PaginatedRequest. Точно так же произойдут и другие изменения. Здесь я расскажу все подробности, чтобы избежать путаницы.

Раньше это было

$http({ 
      method: 'GET', 
      url: this.callParams.uri, 
      params: this.callParams.paginationOptions, 
      headers: { 'Content-Type': 'application/Json' } 
}) 

Вы видите this.callParams.paginationOptions. Этот объект javascript будет выглядеть примерно так.

{"Page":1,"Take":10,"SortOrder":"Asc","PropName":"Id","whereParams": 
[{"FilterPropName":"Name","FilterPropValue":"jk"}]} 

И это.callParams.uri было бы чем-то вроде этого.

'/api/PatientCategoryApi/PatCat' 

Здесь PatientCategoryApi является контроллером WebAPI и PatCat является метод действия на стороне WebAPI. Необходим метод действия со следующей подписью.

[HttpPost] 
    [HttpGet] 
    public PaginatedList<PatientCategory> PatCat(PaginatedRequest rqst) 

PaginatedRequest класс следующим образом.

public class PaginatedRequest 
{ 
    public int Page { get; set; } // Page Index 
    public int Take { get; set; } // Page Size 
    public string PropName { get; set; } // Property Name for sorting. 
    public string SortOrder { get; set; } // Sort Direction Asc or Desc 
    public List<WhereParam> whereParams { get; set; } 
} 

И WhereParam класс следующим образом

public class WhereParam 
{ 
    public string FilterPropName { get; set; } 
    public string FilterPropValue { get; set; } 
} 

Настройка параметров связывания правил в webApiConfig следующим образом.

config.ParameterBindingRules.Insert(0, typeof(PaginatedRequest), 
    x => x.BindWithAttribute(new FromUriAttribute())); 

Это все к нему. Если бы я использовал JQuery, это сработало бы. Но с AngularJS сериализация отличается. Так хитрость заключается в том, чтобы добавить

paramSerializer: '$httpParamSerializerJQLike', 

для вызова Ajax. Я нашел в этом вопрос AngularJS GET ajax call with Array parameters. Итак, весь вызов теперь будет выглядеть следующим образом.

$http({ 
      method: 'GET', 
      url: this.callParams.uri, 
      paramSerializer: '$httpParamSerializerJQLike', 
      params: this.callParams.paginationOptions, 
      headers: { 'Content-Type': 'application/Json' } 
}) 

Это теперь гарантирует, что сериализация будет способом, которым понимает WebApi. И привязка на стороне WebApi происходит правильно.

Если вы хотите, вы можете также изменить подпись метода действия следующим образом, чтобы разделить свойство List на параметр. В этом случае привязка больше не является сложным объектом, а одним простым объектом и массивом (или списком).

[HttpPost] 
[HttpGet] 
public PaginatedList<PatientCategory> PatCat(PaginatedRequest rqst, 
List<WhereParam> whereParams){...} 

В таком случае PaginatedRequest не будет иметь список WhereParam как свойство.

public class PaginatedRequest 
{ 
    public int Page { get; set; } // Page Index 
    public int Take { get; set; } // Page Size 
    public string PropName { get; set; } // Property Name for sorting. 
    public string SortOrder { get; set; } // Sort Direction Asc or Desc 
    // You dont want this here in this approach. 
    //public List<WhereParam> whereParams { get; set; } 
} 

И в классе webApiConfig вам необходимо дополнительно добавить следующее.

 config.ParameterBindingRules.Insert(0, typeof(List<WhereParam>), 
      x => x.BindWithAttribute(new FromUriAttribute())); 

И никаких других изменений, необходимых на стороне клиента, не требуется. Это должно сработать. В целом, в любом случае, ключ, как я уже говорил,

paramSerializer: '$ httpParamSerializerJQLike',

1

Свойство wherePredicateParams является string[] не whereParam[] так это сделать, что сериализатор DonT сериализует свойства, но я предлагаю вам использовать Json.NET вы можете получить его здесь http://www.newtonsoft.com/json, это Lib позволяет использовать атрибуты в свойствах которые сопоставляют вашу json-схему с классом/типом.

Вы можете сделать что-то вроде примера:

public class WhereParam 
{ 
    [JsonProperty("propName")] 
    public string PropName { get; set; } 
    [JsonProperty("val")] 
    public string Val { get; set; } 
}