0

我自托管 WCF WSHttpBinding 绑定服务。运行时,我无法对服务调用进行任何更改。你能诊断出这个问题吗?

地址栏(多个浏览器)中的基本GET信息失败并显示400 Bad Request. $.ajax with GET, POSTwith 'dataType': 'json'or也是如此'dataType': 'jsonp'。我已经尝试了基地址的变体。包括或省略WebInvokeAttribute没有任何区别。HTTP 方法是否匹配或不匹配都没有区别。

将服务端点设置为更窄的路径,然后适当地浏览到该端点之外的路径会导致错误(关于不允许的方法)。由于预期的跨站点脚本保护,从 ajax 使用 GETjsonp会失败,但我可以避免这种情况。

(网上这个问题有一百万个版本。有些似乎已解决,但答案无济于事。其他未解决。这不是其中任何一个的完全重复。)

WCF 跟踪总是指示:“从网络接收的 XML 存在问题。” 与“无法读取消息的正文,因为它是空的”作为内部异常 - 即使对于GET不应该有正文的请求(对吗?)。即使我尝试POST使用 '' 或 '{}' 的 json 数据,我仍然会得到这个错误。

此代码示例主要来自: 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. ---&gt; 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>
4

2 回答 2

1

WSHttpBinding 创建一个基于soap 的绑定。您无法使用浏览器通过导航到 URL 来访问此端点。您可以通过创建服务代理或使用 wcftestclient(用于测试)来访问此绑定。如果您正在寻找开发 REST 端点,请使用 webHttpBinding 而不是 wsHttpBinding。

是一个关于如何开发基于 REST 的服务的快速示例。是一篇描述 webHttpBinding 和 wsHttpBinding 之间区别的帖子。

于 2013-06-17T19:34:05.440 回答
0

调用使用 WSHttp 绑定公开的 WCF 服务

web.config 设置

<services> <service name="MyWcfService.MyService"> <endpoint address="jh" binding="wsHttpBinding" bindingConfiguration="NoSecurity" contract="MyWcfService.IMyService" /> </service> </services>

html页面

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

                  }
              });
          });
      });
于 2014-10-13T04:48:01.897 回答