我是自托管WCF WSHttpBinding绑定服务。在运行时,我无法获得服务呼叫的任何变化。你能诊断出这个问题吗?
地址栏中的基本GET
(多个浏览器)因400 Bad Request
而失败。使用GET
,POST
'dataType': 'json'
或'dataType': 'jsonp'
的$ .ajax也是如此。我试过基地址的变化。包含或省略WebInvokeAttribute
并没有什么不同。 HTTP方法是否匹配或不匹配并没有什么不同。
将服务端点设置为较窄的路径,然后浏览到该端点外部的路径会导致错误(关于不允许的方法)。在没有jsonp
的情况下使用ajax中的GET会因为预期的跨站点脚本保护而失败,但我可以避免这种情况。
(这个问题在网上有一百万个版本。有些版本似乎已经解决,但答案没有帮助。其他版本尚未解决。这与其中任何一个都不完全相同。)
WCF跟踪总是指示:“从网络收到的XML存在问题。”与“消息的主体无法读取,因为它是空的”作为内部异常 - 即使是GET
请求,其中应该没有正文(对吗?)。即使我尝试使用''或'{}'的json数据POST
,我仍然会出现此错误。
此代码示例主要来自:http://msdn.microsoft.com/en-us/library/ms730935.aspx,.Net 4.5 WCF示例。该示例比必要的大,我必须添加binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
,以便Windows允许它在没有完全管理权限的情况下运行。我也玩过相对url(现在为空)来测试。
运行此命令并将浏览器指向http://localhost:8000/
正在为MEX / WSDL广告提供服务。这告诉我web服务正在运行,我正在浏览到正确的端点(至少加上或减去服务前缀),并且Windows防火墙或权限不会干扰进程在端口上打开或提供服务的能力。然而http://localhost:8000/Ping
只得到400。
如果我没记错的话(可能不是这样),旧版本的WCF和.NET不允许或不支持自托管的类似Web的协议。我相信这已经改变了。同样,MEX数据的提供与我想要提供的自定义内容并没有什么不同 - 它只是来自同一过程中的不同位置。
sdb.IncludeExceptionDetailInFaults = true;
似乎没有任何有用的效果。
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
namespace WCFWebHost
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8000/");
ServiceHost selfHost = new ServiceHost(typeof(EchoService), baseAddress);
try
{
var binding = new WSHttpBinding();
binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
selfHost.AddServiceEndpoint(typeof(IEcho), binding, "");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
var sdb = selfHost.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;
selfHost.Open();
Console.WriteLine("Open and waiting.");
Console.ReadKey(true);
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
[ServiceContract(Namespace = "http://echo")]
public interface IEcho
{
[OperationContract]
[WebInvoke(
Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "Ping")]
void Ping();
}
public class EchoService : IEcho
{
public void Ping()
{
}
}
}
web配置添加了traces.svc配置:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Verbose, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\Users\...\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
===
对我来说似乎很奇怪的是,跟踪的异常似乎来自错误报告本身。跟踪中的此错误是否隐藏了有关原始故障的更好信息?或者我只是在读错了?
<Exception>
<ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>There is a problem with the XML that was received from the network. See inner exception for more details.</Message>
<StackTrace>
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference)
at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception)
at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource)
at System.Runtime.ExceptionTrace.AsError(Exception exception)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---> System.Xml.XmlException: The body of the message cannot be read because it is empty.
--- End of inner exception stack trace ---</ExceptionString>
<InnerException>
<Exception>
<ExceptionType>System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The body of the message cannot be read because it is empty.</Message>
<StackTrace>
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetInnerException(Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference)
at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception)
at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource)
at System.Runtime.ExceptionTrace.AsError(Exception exception)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Xml.XmlException: The body of the message cannot be read because it is empty.</ExceptionString>
</Exception>
</InnerException>
</Exception>
答案 0 :(得分:1)
WSHttpBinding创建基于soap的绑定。您无法通过导航到URL来访问此端点。您可以通过创建服务代理或使用wcftestclient(用于测试)来访问此绑定。如果您正在寻找开发REST端点,请使用webHttpBinding而不是wsHttpBinding。
Here是关于如何开发基于REST的服务的快速示例。 Here是一篇文章,描述了webHttpBinding&amp; amp;的wsHttpBinding。
答案 1 :(得分:0)
调用使用WSHttp绑定公开的WCF服务
web.config设置
<services>
<service name="MyWcfService.MyService">
<endpoint address="jh" binding="wsHttpBinding" bindingConfiguration="NoSecurity" contract="MyWcfService.IMyService" />
</service>
</services>
html page
//SOAP request generated in order to call the Service method
var whRequest ="<s:Envelope xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\">" +
"<s:Header>" +
"<a:Action s:mustUnderstand=\"1\">http://tempuri.org/IMyService/GetData</a:Action>" +
"<a:MessageID>urn:uuid:7fdde7b6-64c8-4402-9af1-cc848f15888f</a:MessageID>" +
"<a:ReplyTo>" +
"<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>" +
"</a:ReplyTo>" +
"<a:To s:mustUnderstand=\"1\">http://localhost:1415/MyService.svc/jh</a:To>" +
"</s:Header>" +
"<s:Body>" +
"<GetData xmlns=\"http://tempuri.org/\">"+
"<value>9</value>"+
"</GetData>" +
"</s:Body>" +
"</s:Envelope>";
$(document).ready(function () {
$("#btnWCFWSHttp").click(function () {
$.ajax({
type: "POST",
url: "http://localhost:1415/MyService.svc/jh/",
data: whRequest,
timeout: 10000,
contentType: "application/soap+xml",
dataType: "xml",
async: false,
success: function (data, status, xhr) {
$(data).find("GetDataResponse").each(function () {
alert($(this).find("GetDataResult").text());
});
},
error: function (xhr, status, error) {
alert(error);
}
});
});
});