C# WebGet 的 WCF 响应格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/992533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:06:17  来源:igfitidea点击:

WCF ResponseFormat For WebGet

c#wcfwebgetresponseformat

提问by mgamer

WCF offers two options for ResponseFormat attribute in WebGet annotation in ServiceContract.

WCF 在 ServiceContract 的 WebGet 注释中为 ResponseFormat 属性提供了两个选项。

[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();

The options for ResponseFormat are WebMessageFormat.Json and WebMessageFormat.Xml. Is it possible to write my own web message format? I would like that when client calls foo() method he gets raw string - without json or xml wrappers.

ResponseFormat 的选项是 WebMessageFormat.Json 和 WebMessageFormat.Xml。是否可以编写我自己的 Web 消息格式?我希望当客户端调用 foo() 方法时,他得到原始字符串 - 没有 json 或 xml 包装器。

采纳答案by Eugene Yokota

WebGetAttributeis shipped by Microsoft, and I don't think you can extend WebMessageFormat. However you could probably extend the WebHttpBindingthat uses WebGetAttribute. You could add your own attribute like

WebGetAttribute由 Microsoft 提供,我认为您无法扩展WebMessageFormat. 但是,您可能会扩展WebHttpBinding使用WebGetAttribute. 您可以添加自己的属性,例如

[WebGet2(UriTemplate = "foo", ResponseFormat = WebMessageFormat2.PlainText)]
string Foo();

In general, customizing the message layout in WCF is called custom message encoder/encoding. Microsoft provides an example: Custom Message Encoder: Compression Encoder. Also another common extension people do is to extend behavior to add custom error handling, so you could look for some example in that direction.

通常,在 WCF 中自定义消息布局称为自定义消息编码器/编码。Microsoft 提供了一个示例:自定义消息编码器:压缩编码器。人们所做的另一个常见扩展是扩展行为以添加自定义错误处理,因此您可以在该方向上寻找一些示例。

回答by geofftnz

Try using

尝试使用

BodyStyle = WebMessageBodyStyle.Bare

Then return a System.IO.Stream from your function.

然后从您的函数返回 System.IO.Stream。

Here's some code I use to return an image out of a database, but accessible via a URL:

这是我用来从数据库中返回图像的一些代码,但可以通过 URL 访问:

[OperationContract()]
[WebGet(UriTemplate = "Person/{personID}/Image", BodyStyle = WebMessageBodyStyle.Bare)]
System.IO.Stream GetImage(string personID);

Implementation:

执行:

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);
}

In your case, to return a raw string, set the ContentType to something like "text/plain" and return your data as a stream. At a guess, something like this:

在您的情况下,要返回原始字符串,请将 ContentType 设置为“text/plain”之类的内容,并将您的数据作为流返回。猜测是这样的:

return new System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(string_to_send));

回答by Kuba Beránek

There is one way how to achieve this if you're dealing with HTTP, it's not exactly nice, but I thought I could mention it.

如果您正在处理 HTTP,有一种方法可以实现这一点,这不是很好,但我想我可以提到它。

You can set the return type of your method to void and just output your raw string directly into the response.

您可以将方法的返回类型设置为 void,然后将原始字符串直接输出到响应中。

[OperationContract]
[WebGet(UriTemplate = "foo")]
void Foo()
{
   HttpContext.Current.Response.Write("bar");
}

回答by AiSatan

I implemented this attribute like this, maybe it will help someone in the future:

我像这样实现了这个属性,也许将来会对某人有所帮助:

[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();
    }
}