尝试添加服务引用会导致错误请求(400)在一个项目中,否则运行正常

时间:2014-04-14 18:44:33

标签: c# wcf windows-services

我处在一个微妙的情况:正如标题所示,我似乎无法连接到我在Windows服务中包含的WCF服务。我按照教程http://msdn.microsoft.com/en-us/library/ms733069%28v=vs.110%29.aspx执行了每一步,并以这种方式让多次工作,而不是一个特定项目。我真的不知道它是什么,我有一个非常简单的接口只有一个方法作为合同,我的服务安装得很好,也开始很好。一旦我尝试在另一个项目中添加服务引用,我会收到错误400,错误请求和元数据问题。 我甚至重新编写了原型项目(它基本上是同一个项目,在合同的实现中代码较少;但我们仍在谈论仍然低于300行代码)运行完全正常,并出现了同样的错误。当我这样做时,我没有更改任何app.config代码,之前我可以连接,但事后却提出了错误请求。

问题的另一个原因是我不能在这里发布任何代码(我正在工作的虚拟机上工作,我没有互联网访问,加上我实际上在物理机上的互联网访问是所以限制我不能打开任何类型的董事会/论坛/博客/什么,所以我不能发布确切的错误)。由于我的所有最小例子都有效,我的“最小不工作示例”无论如何都是总代码。

我在这里完全失败了。我挖掘了错误请求错误的所有其他主题,明天还要做一些检查,但我想我宁愿在这里发帖,也许会就如何进一步测试我的项目错误得到一些建议。 万一它有帮助,app.config除了服务和合同名称之外与以下相同:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>    <services>
      <!-- This section is optional with the new configuration model
           introduced in .NET Framework 4. -->
      <service name="Microsoft.ServiceModel.Samples.CalculatorService"
               behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
          </baseAddresses>
        </host>
        <!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModelSamples/service  -->
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

什么可能从头开始三次尝试工作,但第四次不再工作,唯一的区别是文件的大小和2个没有做其他事情的辅助类?我的意思是,服务必须在那里,否则我会得到404 Not Found错误,但是元数据有问题,尽管我在另一次尝试中使用了完全(!)相同的app.config并且在那里它的工作原理。

非常感谢任何建议/提示。我明天会尝试增加绑定中的缓冲区大小,我听说这对一些人有帮助,但我不知道我在那里,因为我还没有发送任何东西,是吗?我只是想添加服务引用,我不知道大小是否重要。我也已经尝试过TCP和basicHTTP绑定到相同的结果。

提前致谢并对文字墙感到抱歉;我今天在工作中非常沮丧,甚至由于那些愚蠢的工作条件甚至无法正确研究错误,并且再次写下这种挫折感......;)

3 个答案:

答案 0 :(得分:2)

一开始你必须找到一个问题,我的意思是你需要知道服务器端会发生什么。您需要处理所有错误并记录它们。

记录错误

    public class GlobalErrorHanler: IErrorHandler 
    {
        //to use log4net you have to have a proper configuration in you web/app.config
        private static readonly ILog Logger = LogManager.GetLogger(typeof (GlobalErrorHandler));

        public bool HandleError(Exception error)
        {
            //if you host your app on IIS you have to log using log4net for example
            Logger.Error("Error occurred on the service side", error);

            //Console.WriteLine(error.Message); 
            //Console.WriteLine(error.StackTrace);

            return false;
        }

        public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
        {
            //you can provide you fault exception here
        }
    }

然后服务行为(继承属性以增加将其用作服务实现的属性的可能性):

public class MyErrorHandlingBehavior : Attribute, IServiceBehavior
{

    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        return;
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)
            disp.ErrorHandlers.Add(new GlobalErrorHanler());
    }

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {        }
}

在您的配置中使用它的扩展元素:

public class ErrorHandlerExtention: BehaviorExtensionElement
{

    public override Type BehaviorType
    {
        get { return typeof(MyErrorHandlingBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new MyErrorHandlingBehavior();
    }
}

然后添加到配置文件:

<system.serviceModel>
  <extensions>
    <behaviorExtensions>
      <!-- Extension.ErrorHandlerExtention: fully qualified class name, ArrayList: assebmly name-->
      <add name="errorHandler" type="Extension.ErrorHandlerExtention, Extensions"/>
    </behaviorExtensions>
  </extensions>

<behaviors>
  <serviceBehaviors>
    <behavior name="CalculatorServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="False"/>

      <!-- the name of this element must be the same as in the section behaviorExtensions -->
      <errorHandler />

    </behavior>
  </serviceBehaviors>
</behaviors>

</system.serviceModel>

这将允许您收到错误。如果您有错误,请返回论坛。

使用此技术的更多帖子:Error 1Error 2

<强>跟踪:

要启用跟踪,您必须将这些行添加到配置中:

<system.diagnostics>
  <trace autoflush="true" />
  <sources>
    <source name="System.ServiceModel"
            switchValue="Information, ActivityTracing"
            propagateActivity="true">
      <listeners>
        <add name="log"
            type="System.Diagnostics.XmlWriterTraceListener"
            initializeData= "C:\traces.svclog" />
      </listeners>
    </source>
  </sources>
</system.diagnostics>

跟踪工具Trace Viewer

答案 1 :(得分:1)

不能说问题是什么,但这里有一些信息可以帮助您找到问题。

当您执行“添加服务引用”时,会有一个http get Call转到该服务。我假设是这个调用返回http 400.你有一个mex端点和httpgetenabled,缺少这些是正常的问题。

您可以尝试使用浏览器阅读wsdl并查看是否可以使用。

原因可能是:

  • 端口8000被阻止
  • IIS站点位于不同的端口
  • 您正在使用计算机名访问该站点,而配置使用本地主机
  • 在该端口的iis中未启用绑定

答案 2 :(得分:1)

对于遇到类似问题且没有详细错误的人,我将描述我的问题是什么。在我的Visual Studio项目中,我使用了类似于以下的类:

public class Info
{
  public string Key { get; set; }
  public string Value { get; set; }

  public Info(string key, string value)
  {
    this.Key = key;
    this.Value = value;
  }
}

与其他项目(有效)的不同之处在于,此POCO具有一个带参数的构造函数,因此不提供没有任何参数的标准构造函数。但是,为了将Info对象序列化(我希望我在这里正确使用该术语)并反序列化,这是必需的。所以为了使它工作,要么只是添加一个可能什么也不做的标准构造函数,或者(或许更好)使用以下代码:

[DataContract]
public class Info
{
  [DataMember]
  public string Key { get; set; }
  [DataMember]
  public string Value { get; set; }

  public Info(string key, string value)
  {
    this.Key = key;
    this.Value = value;
  }
}

之前我没有考虑DataContract部分,因为我没有使用任何自定义构造函数,只是初始化了像

这样的对象
Info info = new Info { Key = "a", Value = "b" };