我需要支持将数据发布到我们的 WCF 服务,内容类型为x-www-form-urlencoded
。由于 WCF 不喜欢本机执行此操作,因此我的想法是使用MessageInspector
来截获具有该内容类型的传入消息,读出正文,将其转换为 JSON 字符串,然后替换请求消息。
问题是我似乎无法制作我的服务真正喜欢的新Message
对象。我可以很好地获取正文并将其转换为 JSON 字符串,但我创建的新消息会导致错误,而不是继续使用适当的服务方法。
这就是我目前所拥有的。我已经修补了一天多一点,尝试了几种不同的方法,但运气不佳。我将在我目前收到的错误下面发布。
我想调用的 Web 服务方法:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/PostTest", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public string PostTest(TestObject thinger)
{
return thinger.Thing;
}
邮件检查器:
public class FormPostConverter : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var contentType = (request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers["Content-Type"];
if (!request.IsEmpty && contentType == "application/x-www-form-urlencoded")
{
var body = HttpUtility.ParseQueryString(new StreamReader(request.GetBody<Stream>()).ReadToEnd());
var json = new JavaScriptSerializer().Serialize(body.AllKeys.ToDictionary(k => k, k => body[k]));
Message newMessage = Message.CreateMessage(MessageVersion.None, "", json, new DataContractJsonSerializer(typeof(string)));
newMessage.Headers.CopyHeadersFrom(request);
newMessage.Properties.CopyProperties(request.Properties);
(newMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers.Set(HttpRequestHeader.ContentType, "application/json");
newMessage.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(WebContentFormat.Json);
request = newMessage;
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{ }
}
我得到的错误:
请求错误服务器在处理请求时遇到错误。 异常消息是"预期状态'元素'。遇到 具有名称"的"文本",命名空间"。'.
所以,似乎我并没有很好地表达我实际上想要完成的事情,但在与它进行了更多的斗争之后,我终于弄清楚了。
我生成的消息检查器如下所示:
public class FormPostConverter : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var contentType = (request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers["Content-Type"];
if (!request.IsEmpty && contentType == "application/x-www-form-urlencoded")
{
var body = HttpUtility.ParseQueryString(new StreamReader(request.GetBody<Stream>()).ReadToEnd());
if (body != null && body.HasKeys())
{
Message newMessage = Message.CreateMessage(MessageVersion.None, "", new XElement("root", body.AllKeys.Select(o => new XElement(o, body[o]))));
newMessage.Headers.CopyHeadersFrom(request);
newMessage.Properties.CopyProperties(request.Properties);
(newMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers.Set(HttpRequestHeader.ContentType, "application/json");
newMessage.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(WebContentFormat.Json);
request = newMessage;
}
}
return true;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{ }
}
事实证明,我真正需要做的只是将我的身体转换为XML元素,而不是尝试将其作为JSON进行。在检查了一开始以JSON形式出现的正常运行的POST之后,我发现在这个阶段它已经在消息对象中变成了XML。
有了这个,我能够正常编写我的服务方法(没有流参数并手动解析(,并以应用程序/json 或 x-www-form-urlencoding 内容类型接受对它们的帖子。