WCF 服务不喜欢我的 Content-Type
WCF Service Doesn't Like My Content-Type
我正在使用 WCF 构建一组 Rest 服务。我正在使用 Postman 发出测试请求。一切都很顺利,直到我想在请求 header 中指定 "Content-Type"。
服务合同:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "data")]
Stream GetData(Stream iBody);
及其背后的代码:
public Stream GetData(Stream iBody) {
StreamReader objReader = new StreamReader(iBody);
string strBody = objReader.ReadToEnd();
XmlDocument objDoc = new XmlDocument();
objDoc.LoadXml(strBody);
return GetStreamData("Hello There. " + objDoc.InnerText);
}
private Stream GetStreamData(string iContent) {
byte[] resultBytes = Encoding.UTF8.GetBytes(iContent);
return new MemoryStream(resultBytes);
}
只要我不在请求 headers.
中包含值为 "text/xml" 的 "Content-Type",这一切都可以正常工作
有:
没有:
我也试过 "text/xml; charset=utf-8" 和 "application/xml" 的组合,但没有用。它与服务方法接受的类型有什么关系吗?任何指针将不胜感激。
由于您使用的是 raw programming model in the WCF service (using Stream
as a parameter / return type), you need to tell the WCF stack not to try to interpret incoming requests with XML content-type as XML, and instead just let it pass through. You can do that with a WebContentTypeMapper
,它会将所有传入请求(无论其内容类型如何)映射到原始模式。顶部链接的博客 post 提供了更多相关信息,下面的代码显示了处理您的案例的映射器示例。
public class Whosebug_35750073
{
[ServiceContract]
public class Service
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "data")]
public Stream GetData(Stream iBody)
{
StreamReader objReader = new StreamReader(iBody);
string strBody = objReader.ReadToEnd();
XmlDocument objDoc = new XmlDocument();
objDoc.LoadXml(strBody);
return GetStreamData("Hello There. " + objDoc.InnerText);
}
private Stream GetStreamData(string iContent)
{
byte[] resultBytes = Encoding.UTF8.GetBytes(iContent);
return new MemoryStream(resultBytes);
}
}
class RawMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
ServiceEndpoint endpoint1 = host.AddServiceEndpoint(
typeof(Service),
new WebHttpBinding { ContentTypeMapper = new RawMapper() },
"withMapper");
endpoint1.Behaviors.Add(new WebHttpBehavior());
ServiceEndpoint endpoint2 = host.AddServiceEndpoint(
typeof(Service),
new WebHttpBinding(),
"noMapper");
endpoint2.Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
var input = "<hello><world>How are you?</world></hello>";
Console.WriteLine("Using a Content-Type mapper:");
SendRequest(baseAddress + "/withMapper/data", "POST", "text/xml", input);
SendRequest(baseAddress + "/withMapper/data", "POST", null, input);
Console.WriteLine("Without using a Content-Type mapper:");
SendRequest(baseAddress + "/noMapper/data", "POST", "text/xml", input);
SendRequest(baseAddress + "/noMapper/data", "POST", null, input);
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
public static string SendRequest(string uri, string method, string contentType, string body)
{
string responseBody = null;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Method = method;
if (!String.IsNullOrEmpty(contentType))
{
req.ContentType = contentType;
}
if (body != null)
{
byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
req.GetRequestStream().Close();
}
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
if (resp == null)
{
responseBody = null;
Console.WriteLine("Response is null");
}
else
{
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string headerName in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
}
Console.WriteLine();
Stream respStream = resp.GetResponseStream();
if (respStream != null)
{
responseBody = new StreamReader(respStream).ReadToEnd();
Console.WriteLine(responseBody);
}
else
{
Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
}
}
Console.WriteLine();
Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
Console.WriteLine();
return responseBody;
}
}
我正在使用 WCF 构建一组 Rest 服务。我正在使用 Postman 发出测试请求。一切都很顺利,直到我想在请求 header 中指定 "Content-Type"。
服务合同:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "data")]
Stream GetData(Stream iBody);
及其背后的代码:
public Stream GetData(Stream iBody) {
StreamReader objReader = new StreamReader(iBody);
string strBody = objReader.ReadToEnd();
XmlDocument objDoc = new XmlDocument();
objDoc.LoadXml(strBody);
return GetStreamData("Hello There. " + objDoc.InnerText);
}
private Stream GetStreamData(string iContent) {
byte[] resultBytes = Encoding.UTF8.GetBytes(iContent);
return new MemoryStream(resultBytes);
}
只要我不在请求 headers.
中包含值为 "text/xml" 的 "Content-Type",这一切都可以正常工作有:
没有:
我也试过 "text/xml; charset=utf-8" 和 "application/xml" 的组合,但没有用。它与服务方法接受的类型有什么关系吗?任何指针将不胜感激。
由于您使用的是 raw programming model in the WCF service (using Stream
as a parameter / return type), you need to tell the WCF stack not to try to interpret incoming requests with XML content-type as XML, and instead just let it pass through. You can do that with a WebContentTypeMapper
,它会将所有传入请求(无论其内容类型如何)映射到原始模式。顶部链接的博客 post 提供了更多相关信息,下面的代码显示了处理您的案例的映射器示例。
public class Whosebug_35750073
{
[ServiceContract]
public class Service
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "data")]
public Stream GetData(Stream iBody)
{
StreamReader objReader = new StreamReader(iBody);
string strBody = objReader.ReadToEnd();
XmlDocument objDoc = new XmlDocument();
objDoc.LoadXml(strBody);
return GetStreamData("Hello There. " + objDoc.InnerText);
}
private Stream GetStreamData(string iContent)
{
byte[] resultBytes = Encoding.UTF8.GetBytes(iContent);
return new MemoryStream(resultBytes);
}
}
class RawMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
ServiceEndpoint endpoint1 = host.AddServiceEndpoint(
typeof(Service),
new WebHttpBinding { ContentTypeMapper = new RawMapper() },
"withMapper");
endpoint1.Behaviors.Add(new WebHttpBehavior());
ServiceEndpoint endpoint2 = host.AddServiceEndpoint(
typeof(Service),
new WebHttpBinding(),
"noMapper");
endpoint2.Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
var input = "<hello><world>How are you?</world></hello>";
Console.WriteLine("Using a Content-Type mapper:");
SendRequest(baseAddress + "/withMapper/data", "POST", "text/xml", input);
SendRequest(baseAddress + "/withMapper/data", "POST", null, input);
Console.WriteLine("Without using a Content-Type mapper:");
SendRequest(baseAddress + "/noMapper/data", "POST", "text/xml", input);
SendRequest(baseAddress + "/noMapper/data", "POST", null, input);
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
public static string SendRequest(string uri, string method, string contentType, string body)
{
string responseBody = null;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Method = method;
if (!String.IsNullOrEmpty(contentType))
{
req.ContentType = contentType;
}
if (body != null)
{
byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
req.GetRequestStream().Close();
}
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
if (resp == null)
{
responseBody = null;
Console.WriteLine("Response is null");
}
else
{
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string headerName in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
}
Console.WriteLine();
Stream respStream = resp.GetResponseStream();
if (respStream != null)
{
responseBody = new StreamReader(respStream).ReadToEnd();
Console.WriteLine(responseBody);
}
else
{
Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
}
}
Console.WriteLine();
Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
Console.WriteLine();
return responseBody;
}
}