2010-06-25 14 views
18

Czy możliwe jest zastąpienie domyślnego zachowania WCF DataContractSerializer podczas tworzenia szeregów/DeSerialize i używania JSON.NET zamiast?Jak ustawić Json.Net jako domyślny serializer dla usługi WCF REST

Mam następującą umowę serwisową na obsługę podmiotu City. Ze względów projektowych jednostka City ma wartość IsReference = true, dlatego domyślny obiekt DataContractSerializer powoduje błędy.

Dla metod "GET" mogę obsłużyć sytuację z JsonConvert.DeserializeObject, ale z metodami "PUT, POST, DELETE" DataContractSerializer ma pierwszeństwo i nie może narzekać, że podmioty IsReference nie mogą być serializowane.

Mam znaleźć Post do wdrożenia IOperationBehavior i zapewnić mój własny Serializer ale nie wiem jak zintegrować Json.NET z tym. i uważam, że powinno to być bardziej proste podejście.

Doceniam każdą pomoc lub wskazówki dotyczące tego scenariusza lub porady dotyczące innych metod.

[ServiceContract] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed) 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class CityService 
{ 
    [Description("Get all Cities")] 
    [WebGet(UriTemplate = "")] 
    public Message Cities() 
    { 

    } 

    [Description("Allows the details of a single City to be updated.")] 
    [WebInvoke(UriTemplate = "{code}", Method = "PUT")] 
    public Message UpdateCity(string code, City city) 
    { 
    } 
} 

Dziękujemy

Hossam

Odpowiedz

19

Zastosowanie rozszerzających enkoderów i serializatorów (patrz http://msdn.microsoft.com/en-us/library/ms733092.aspx) lub innych metod rozszerzania WCF, takich jak korzystanie z DataContractSerializerOperationBehavior jest bardzo interesujące, ale dla Twojego szczególnego problemu są łatwiejsze sposoby rozwiązania.

Jeśli używałeś Message rodzaj powrotu wyników jest wykorzystanie WCF4 można zrobić coś jak następuje:

public Message UpdateCity(string code, City city) 
{ 
    MyResponseDataClass message = CreateMyResponse(); 
    // use JSON.NET to serialize the response data 
    string myResponseBody = JsonConvert.Serialize(message); 
    return WebOperationContext.Current.CreateTextResponse (myResponseBody, 
       "application/json; charset=utf-8", 
       Encoding.UTF8); 
} 

W przypadku błędów (jak HttpStatusCode.Unauthorized lub HttpStatusCode.Conflict) lub w innych sytuacjach, gdy trzeba ustawić kod statusu HTTP (np. HttpStatusCode.Created) można nadal używać WebOperationContext.Current.OutgoingResponse.StatusCode.

Jako alternatywę można również zwracają Stream (patrz http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx i http://msdn.microsoft.com/en-us/library/ms732038.aspx) zamiast Message do zwrotu jakichkolwiek danych bez dodatkowego przetwarzania domyślnej przez Microsoft JSON serializatora. W przypadku WCF4 można użyć CreateStreamResponse (patrz http://msdn.microsoft.com/en-us/library/dd782273.aspx) zamiast CreateTextResponse. Nie zapomnij ustawić pozycji strumienia na 0 po zapisaniu w strumieniu, jeśli użyjesz tej techniki do wygenerowania odpowiedzi.

+0

Oleg, wielkie dzięki, działa jak czar, zwracając typ Stream, zatrzymuje serializer Microsft. Jestem świadomy DataContractSerializerOperationBehavior, ale zabiera mi to mój własny Serializer z XmlObjectSerializer, co nie jest zadaniem łatwym. Twoja propozycja jest znacznie prostsza i prosta, jeszcze raz dziękuję. – Hossam

+0

W jaki sposób obsługuje deserializację przychodzącego obiektu City? –

+1

@ Christopher Stott: Zobacz na przykład http://msdn.microsoft.com/en-us/library/ms734675.aspx, począwszy od "Reading Messages". – Oleg

1

Czy jest jakiś powód, dla którego chcesz użyć biblioteki Json.NET specjalnie. Jeśli chcesz zwrócić JSON, dlaczego nie wystarczy użyć właściwości ResponseFormat z atrybutów WebGet i WebInvoke?

[WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)] 

To powinno w większości przypadków. Jaką wersję WCF używasz? Każdy powód, dla którego zwracasz typ wiadomości, a nie rzeczywisty typ?

+0

To WCF4. W mojej sieci.config, mój ma defaultOutgoingResponseFormat = "Json", więc nie muszę dekorować metod serwisowych. Zgodnie z projektem wszystkie moje jednostki mają [IsReference = true] i nie można uzyskać serializacji z domyślnym DataContractSerializer. Więc muszę użyć innego Serializera, takiego jak Json.net, który może obsługiwać encje z [IsReference = true]. Powracam do typu wiadomości, aby moja odpowiedź nie została dwukrotnie zeskanowana, raz przez json.net, a następnie przez DataContractSerializer. Jeśli zwrócę typ elementu wykonawczego, otrzymam nieprawidłowy json w stylu "{\" Miasto \ ": \" Kair \ "}" Za odpowiedź. – Hossam

+0

To działa dla Ciebie, jeśli nie używasz atrybutu IsReference, ale musisz go używać z projektu z innego powodu? –

+0

Prawidłowo, IsReference to jedyny problem. Jest to zgłaszane w wielu postach DataContractJsonSerializer nie może serializować podmiotów oznaczonych IsReference = true. Właśnie dlatego szukam innego Serializera. Wielkie dzięki – Hossam

0

Zdefiniuj go w serwis internetowy config na zachowaniach usług:

<endpointBehaviors> 
    <behavior name="restfulBehavior"> 
     <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" /> 
     <!--<enableWebScript />--> 
    </behavior> 
</endpointBehaviors> 

lub w umowie o pracy swojego interfejsu

Powiązane problemy