WCF ResponseFormat For WebGet
WCF oferuje dwie opcje dla atrybutu ResponseFormat w adnotacji WebGet w ServiceContract.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "greet/{value}", BodyStyle = WebMessageBodyStyle.Bare)]
string GetData(string value);
[OperationContract]
[WebGet(UriTemplate = "foo", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
string Foo();
Opcje ResponseFormat to WebMessageFormat.Json i WebMessageFormat.Xml. Czy jest możliwość napisania własnego formatu wiadomości www? Chciałbym, żeby klient wywołując metodę foo() otrzymywał surowy ciąg znaków-bez wrapperów json czy xml.
4 answers
WebGetAttribute
jest dostarczany przez Microsoft, i nie sądzę, że można rozszerzyć WebMessageFormat
. Jednak prawdopodobnie można przedłużyć WebHttpBinding
który używa WebGetAttribute
. Możesz dodać własny atrybut jak
[WebGet2(UriTemplate = "foo", ResponseFormat = WebMessageFormat2.PlainText)]
string Foo();
Ogólnie rzecz biorąc, dostosowywanie układu wiadomości w WCF nazywa się niestandardowym koderem/kodowaniem wiadomości. Microsoft dostarcza przykład: Custom Message Encoder: Compression Encoder . Innym częstym rozszerzeniem jest rozszerzenie zachowania, aby dodać niestandardowy błąd obsługi, więc można szukać jakiegoś przykładu w tym kierunku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 02:43:38
Spróbuj użyć
BodyStyle = WebMessageBodyStyle.Bare
Następnie zwróć System. IO. Stream z twojej funkcji.
Oto kod, którego używam, aby zwrócić obraz z bazy danych, ale dostępny przez URL:
[OperationContract()]
[WebGet(UriTemplate = "Person/{personID}/Image", BodyStyle = WebMessageBodyStyle.Bare)]
System.IO.Stream GetImage(string personID);
Realizacja:
public System.IO.Stream GetImage(string personID)
{
// parse personID, call DB
OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
if (image_not_found_in_DB)
{
context.StatusCode = System.Net.HttpStatusCode.Redirect;
context.Headers.Add(System.Net.HttpResponseHeader.Location, url_of_a_default_image);
return null;
}
// everything is OK, so send image
context.Headers.Add(System.Net.HttpResponseHeader.CacheControl, "public");
context.ContentType = "image/jpeg";
context.LastModified = date_image_was_stored_in_database;
context.StatusCode = System.Net.HttpStatusCode.OK;
return new System.IO.MemoryStream(buffer_containing_jpeg_image_from_database);
}
W Twoim przypadku, aby zwrócić surowy ciąg znaków, Ustaw ContentType na coś w rodzaju "text / plain" i zwróć dane jako strumień. Na zgadywanie, coś takiego:
return new System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(string_to_send));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 03:49:11
Zaimplementowałem ten atrybut w ten sposób, może w przyszłości komuś pomoże:
[AttributeUsage(AttributeTargets.Method)]
public class WebGetText : Attribute, IOperationBehavior
{
public void Validate(OperationDescription operationDescription)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter = new Formatter(dispatchOperation.Formatter);
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
}
public class Formatter : IDispatchMessageFormatter
{
IDispatchMessageFormatter form;
public Formatter (IDispatchMessageFormatter form)
{
this.form = form;
}
public void DeserializeRequest(Message message, object[] parameters)
{
form.DeserializeRequest(message, parameters)
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
IEnumerable<object> cl = (IEnumerable<object>)result;
StringBuilder csvdata = new StringBuilder();
foreach (object userVariableClass in cl) {
Type type = userVariableClass.GetType();
PropertyInfo[] fields = type.GetProperties();
// Dim header As String = String.Join(";", fields.Select(Function(f) f.Name + ": " + f.GetValue(userVariableClass, Nothing).ToString()).ToArray())
// csvdata.AppendLine("")
// csvdata.AppendLine(header)
csvdata.AppendLine(ToCsvFields(";", fields, userVariableClass));
csvdata.AppendLine("");
csvdata.AppendLine("=====EOF=====");
csvdata.AppendLine("");
}
Message msg = WebOperationContext.Current.CreateTextResponse(csvdata.ToString());
return msg;
}
public static string ToCsvFields(string separator, PropertyInfo[] fields, object o)
{
StringBuilder linie = new StringBuilder();
foreach (PropertyInfo f in fields) {
if (linie.Length > 0) {
}
object x = f.GetValue(o, null);
if (x != null) {
linie.AppendLine(f.Name + ": " + x.ToString());
} else {
linie.AppendLine(f.Name + ": Nothing");
}
}
return linie.ToString();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-19 12:18:41
Jest jeden sposób, jak to osiągnąć, jeśli masz do czynienia z HTTP, nie jest to do końca miłe, ale pomyślałem, że mogę o tym wspomnieć.
Możesz ustawić typ zwracanej metody na void i po prostu wypisać surowy ciąg znaków bezpośrednio do odpowiedzi.
[OperationContract]
[WebGet(UriTemplate = "foo")]
void Foo()
{
HttpContext.Current.Response.Write("bar");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-16 16:27:49