Na potrzeby jednego z projektów wykonywałem Web Service przy użyciu technologii Windows Communication Foundation. Usługa musiała zwracać dane w postaci JSNOP tak, aby przeglądarka mogła odwołać się bezpośrednio do niej bez konieczności tworzenia proxy np. w PHP. Niestety, usługi w .NET obsługują tylko dwa format: XML oraz JSON.
Na stronie Microsoftu są dostępne przykłady wykorzystania WCF. Jeden z nich opisuje sposób implementacji JSNOP, ale rozwiązanie wydaje się być bardzo skomplikowane jak na taką prostą funkcjonalność ;)
Z pomocą przyszedł StackOverflow, na którym znalazłem rozwiązanie podobnego problemu. Pytanie dotyczyło wprawdzie zwracania zawartości zdjęcia, ale skoro możemy zwrócić obrazek w postaci binarnej, to z pewnością uda się wysłać do przeglądarki również dane w postaci tekstowej ;)
Rozwiązanie okazało się bardzo proste. Wystarczy ustawić atrybut „BodyStyle” na „Bare”, a typ wartości zwracanej przez metodę na „Stream”. W definicji metody zwracamy obiekt klasy „MemoryStream”, który zawiera dane. Należy również pamiętać o ustawieniu odpowiedniego „ContentType” (w naszym przypadku jest to oczywiście „application/javascript”).
Implementacja:
[OperationContract]
[WebInvoke(
Method = "GET",
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/GetProducts?callback={callback}")]
Stream GetProducts(string callback)
public Stream GetProducts(string callback)
{
string[] values = new string[] { "a", "b", "c" };
OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
context.ContentType = "application/javascript";
context.StatusCode = System.Net.HttpStatusCode.OK;
JavaScriptSerializer js = new JavaScriptSerializer();
string response = string.Format("{0}({1})", callback, js.Serialize(values));
return new MemoryStream(Encoding.ASCII.GetBytes(response));
}
Zmienna „values” to dowolny, serializowalny obiekt. Parametr „callback” to nazwa metody zdefiniowana w JavaScripcie, która zostanie wywołana po odebraniu żądania.