WCF + REST:请求数据在哪里?

时间:2009-12-04 23:15:00

标签: wcf rest request

我目前正在开发WCF RESTful服务。在POST数据的验证中,如果请求XML不符合我们的业务规则,我会抛出异常。

目标是在收到被认为无效的请求时向相应的工作人员发送电子邮件。但是,除了传入的请求标头,方法和URI之外,我还想发送已发布的XML。

我无法找到访问此数据的方法。在我有机会访问它之前,WCF是否真的会破坏请求正文/数据,或者我错过了什么?

我很感激您的帮助,因为我对为什么无法访问请求数据感到困惑。

5 个答案:

答案 0 :(得分:9)

遗憾的是,这不受支持 - 我们有类似的需求,并通过调用内部成员进行反思来实现。我们只是在错误处理程序中使用它(所以我们可以转储原始请求),但它工作正常。我不推荐它用于您不拥有和操作的系统(例如,不要将此代码发送给客户),因为它可以随时更改服务包或其他任何内容。

public static string GetRequestBody()
{
    OperationContext oc = OperationContext.Current;

    if (oc == null)
        throw new Exception("No ambient OperationContext.");

    MessageEncoder encoder = oc.IncomingMessageProperties.Encoder;
    string contentType = encoder.ContentType;
    Match match = re.Match(contentType);

    if (!match.Success)
        throw new Exception("Failed to extract character set from request content type: " + contentType);

    string characterSet = match.Groups[1].Value;

    object bufferedMessage = operationContextType.InvokeMember("request",
        BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField,
        null, oc, null);

    //TypeUtility.AssertType(bufferedMessageType, bufferedMessage);

    object messageData = bufferedMessageType.InvokeMember("MessageData",
        BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty,
        null, bufferedMessage, null);

    //TypeUtility.AssertType(jsonBufferedMessageDataType, messageData);

    object buffer = jsonBufferedMessageDataType.InvokeMember("Buffer",
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty,
        null, messageData, null);

    ArraySegment<byte> arrayBuffer = (ArraySegment<byte>)buffer;

    Encoding encoding = Encoding.GetEncoding(characterSet);

    string requestMessage = encoding.GetString(arrayBuffer.Array, arrayBuffer.Offset, arrayBuffer.Count);

    return requestMessage;
}

答案 1 :(得分:9)

所以,如果你宣布你的合同是这样的:

[WebInvoke(Method = "POST", UriTemplate = "create", ResponseFormat=WebMessageFormat.Json)]
 int CreateItem(Stream streamOfData);

(您可以使用XML代替) streamOfData应该是HTTP POST的主体。您可以使用以下内容对其进行反序列化:

 StreamReader reader = new StreamReader(streamId);
 String res = reader.ReadToEnd();
 NameValueCollection coll = HttpUtility.ParseQueryString(res);

至少对我们这样的工作。您可能希望使用不同的方法将字符串转换为XMLDocument或其他内容。这适用于我们的JSON帖子。可能不是最优雅的解决方案,但它正在发挥作用。

我希望这会有所帮助。

格伦

答案 2 :(得分:2)

试试这个,

OperationContext.Current.RequestContext.RequestMessage

答案 3 :(得分:2)

以下是没有反思的方法:

using (var reader = OperationContext.Current.RequestContext.RequestMessage.GetReaderAtBodyContents ()) {
    if (reader.Read ())
        return new string (Encoding.ASCII.GetChars (reader.ReadContentAsBase64 ()));
                return result;
    }
}

如果读者是HttpStreamXmlDictionaryReader(就像我的情况那样),该类的方法ReadContentAsBase64(byte[] buffer, int index, int count)的实现只是将这些参数传递给Stream.Rea d方法。

我有byte[]后,我通过ASCII编码将字节转换为字符串。为了正确实施,您可以使用内容类型&amp;根据消息的标题编码,按照HTTP规范进行编码。

答案 4 :(得分:0)

您可以在WCF服务的自定义HttpModule中阻止.less m,读取流并在自定义HttpModule的事件处理程序中再次将其位置设置为0。然后将其存储在会话中并在实际.css中进一步访问。

例如:

HttpApplication.Request.InputStrea