2015-07-30 4 views
0

я должен создать PUT службы RESTful WCF, которая будет иметь URI шаблон что-то вроде этого:Как создать метод в службе WCF RESTful в данном сценарии?

/rs/close_copy/{user_token}?term={term}&brand={brandname} 

Запрос, который приходит к нам имеет тело JSON в этом формате:

“acc”: 
“counters”:[ 
{“format”: 
“ink”: 
“ctr”: 
“duplex”: }, 
{…}] 

Но issue is, "counters" Параметр выше не всегда является массивом объекта JSON, как ожидалось. Когда в "counter" присутствует только один элемент, запрос приходит как отдельный объект JSON, а не как список объектов JSON с одним элементом.

Это третья сторона, которая звонит в наш сервис, и они не могут внести изменения в свой запрос. Я реализовал в WCF-то, как показано ниже:

[WebInvoke(Method = "PUT", ResponseFormat = WebMessageFormat.Json, 
      RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, 
      UriTemplate = "/rs/close_copy/{user_token}?term={term}&brand={brandname}")] 
JsonResponse EndSession(string user_token, string term, string brandname, EndSessionRequest request); 

где EndSessionRequest является:

[DataContract] 
public class EndSessionRequest 
{ 
    [DataMember] 
    public string acc { get; set; }   

    [DataMember] 
    public IEnumerable<PageDetails> counters { get; set; } 
} 

и PageDetails является:

[DataContract] 
public class PageDetails 
{ 
    [DataMember] 
    public string format { get; set; } 
    [DataMember] 
    public string ink { get; set; } 
    [DataMember] 
    public int ctr { get; set; } 
    [DataMember] 
    public bool duplex { get; set; } 
} 

Проблема с вышеуказанной реализации является, когда counters имеет один элемент, запрос приходит к нам как:

{"acc":"ramaccnz","counters":{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}} 

Но согласно нашей реализации, запрос, как ожидается, как:

{"acc":"ramaccnz","counters":[{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}]} 

В других случаях, когда запрос содержит несколько элементов, наша работа по обслуживанию, как и ожидалось.

Есть ли способ справиться с этим в реализации WCF?

+0

Ваш код верный, проблема заключается в стороннем клиенте, который не звонит вам правильно, соблюдая ваш контракт на обслуживание. –

ответ

0

Я смог сделать это, получив строку запроса в формате JSON, используя OperationContext, а затем обрабатывая запрос вручную, используя DataContractJsonSerializer. Ниже приведен фрагмент кода:

[DataContract] 
public class EndSessionRequestMany 
{ 
    [DataMember] 
    public string acc { get; set; } 
    [DataMember] 
    public List<PageDetails> counters { get; set; } 
} 

public JsonResponse EndSession(string user_token, string term, string brandname) 
{ 
    string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString(); 

    XmlReader reader = XmlReader.Create(new StringReader(JSONstring)); 
    EndSessionRequestMany objEndSessionMany = (EndSessionRequestMany)new DataContractJsonSerializer(typeof(EndSessionRequestMany)).ReadObject(reader); 
} 
1

Хорошо. Это довольно сложно. Я тоже работаю над RESTful Service. Есть что-то под названием CollectionDataContract, возможно, это один из способов достижения вашей цели, но я новичок в WCF, поэтому больше не могу вам рассказать. Другим способом было бы получить необработанный поток данных, который вы запрашиваете, поэтому вам нужно будет получить и десериализовать данные JSON самостоятельно, используя JavaScriptSerializer. В этом случае вы можете самостоятельно обрабатывать данные, входящие в систему. Как ..

public JsonResponse ServiceCall(Stream dataStream, object parameter) { 
    var dataBytes = dataStream.ReadToEnd(); 
    // use the required encoding to get the string data 
    var dataString = Encoding.UTF8.GetString(dataBytes); 
    var dataJson = default(EndSessionRequest); 
    try { dataJson = new JavaScriptSerializer().Deserialize<EndSessionRequest>(); } 
    catch { 
     // the request includes just one entry that's why 
     // the serializer fails getting the object so 
     // you could continue like.. 
     dataJson = new JavaScriptSerializer().Deserialize<EndSessionRequestWithSingleCounter>(); 
    } 
    // handle request ... 
} 

Чтобы использовать необработанный поток внутри вашего метода вызова запроса просто удалить спецификацию типа параметра EndSessionRequest и вставить поток. Вы Web.config также нуждается в некоторых изменениях в этом случае ..

<!-- insert into system.web tag --> 
<system.web> 
    <httpRuntime targetFramework="4.5" maxRequestLength="2000000" /> 
    <!-- other stuff.. --> 
</system.web> 
<!-- insert into system.serviceModel > bindings --> 
<system.serviceModel> 
    <bindings> 
     <webHttpBinding> 
      <binding 
       name="YourBindingName" 
       maxBufferSize="65536" 
       maxreceiveMessageSize="2000000000" 
       transferMode="Streamed" /> 
     </webHttpBinding> 
    </bindings> 
</system.serviceModel> 

И не забудьте установить bindingConfiguration = «YourBindingName» к вашему поведению службы.

Но как @Ricardo Pontual уже упоминалось. Это третья сторона вызывает неправильное обращение к вашему сервису.

+0

Я согласен с @Jan Unld, получаю поток необработанных данных. Затем вы можете получить исходную строку json в качестве аргумента для счетчиков. Deserialize with newtonsoft затем проанализируйте, что у вас есть, массив или объект словаря. Это большая боль в прикладе, но я сделал это и могу написать больше кода, если хотите. – brando

 Смежные вопросы

  • Нет связанных вопросов^_^