Can';t仅通过配置为WCF正确公开REST XML、REST JSON和SOAP

Can';t仅通过配置为WCF正确公开REST XML、REST JSON和SOAP,xml,json,wcf,rest,configuration,Xml,Json,Wcf,Rest,Configuration,我希望能够构建一个WCF服务,实现以下目标: RESTfully公开JSON RESTfully公开XML 暴露肥皂 其他绑定(如有必要) 这里的关键是,我希望通过配置来完成所有的,并且对于每个所需的方法,只使用一个用代码编写的函数,而不必在代码ResponseFormat=ResponseFormat.Json或ResponseFormat=ResponseFormat.Xml中分别指定RESTful方法的单独函数。我已经做了大量的研究,但我找不到任何可靠的证据来证明这是否完全可以通过配置

我希望能够构建一个WCF服务,实现以下目标:

  • RESTfully公开JSON
  • RESTfully公开XML
  • 暴露肥皂
  • 其他绑定(如有必要)
这里的关键是,我希望通过配置来完成所有的,并且对于每个所需的方法,只使用一个用代码编写的函数,而不必在代码
ResponseFormat=ResponseFormat.Json
ResponseFormat=ResponseFormat.Xml
中分别指定RESTful方法的单独函数。我已经做了大量的研究,但我找不到任何可靠的证据来证明这是否完全可以通过配置实现

奇怪的是,当我构建项目时,当我通过URL访问RESTful方法时,RESTful方法会工作,但WSDL会抛出一个错误——即,如果有人想通过SOAP引用/使用服务,它将在WSDL导入步骤失败

服务的代码和配置如下所示,服务在本地托管,以便在下进行测试。以下2个RESTful调用成功工作,并在浏览器中成功返回XML和JSON:

localhost/WCF/service1.svc/json/students

localhost/WCF/service1.svc/rest/students

但是,如果我打电话,我会得到下面的错误。如果删除其中一个webhttpBinding端点配置,WSDL将正常工作和显示,因此可以被引用

配置中不可能有多个WebHttpBinding(即必须通过单独的方法和属性,如
ResponseFormat=ResponseFormat.Json
)才能有效生成WSDL吗?或者我在这里配置了错误的东西

任何需要帮助的地方,都可以通过配置直接完成,从而指定具有序列化的额外函数。谢谢

WSDL生成错误

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
    System.NullReferenceException: Object reference not set to an instance of an object.
       at System.ServiceModel.Description.WsdlExporter.CreateWsdlBindingAndPort(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, Port& wsdlPort, Boolean& newBinding, Boolean& bindingNameWasUniquified)
       at System.ServiceModel.Description.WsdlExporter.ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName)
       at System.ServiceModel.Description.WsdlExporter.ExportEndpoints(IEnumerable`1 endpoints, XmlQualifiedName wsdlServiceQName)
       at System.ServiceModel.Description.ServiceMetadataBehavior.MetadataExtensionInitializer.GenerateMetadata()
       at System.ServiceModel.Description.ServiceMetadataExtension.EnsureInitialized()
       at System.ServiceModel.Description.ServiceMetadataExtension.get_Metadata()
       at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.InitializationData.InitializeFrom(ServiceMetadataExtension extension)
       at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.GetInitData()
       at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.TryHandleMetadataRequest(Message httpGetRequest, String[] queries, Message& replyMessage)
       at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.ProcessHttpRequest(Message httpGetRequest)
       at SyncInvokeGet(Object , Object[] , Object[] )
       at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
       at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
Web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="httpGetBehavior" name="WCF.Service1">
        <endpoint address="json" binding="webHttpBinding" name="jsonRest" contract="WCF.IService1" behaviorConfiguration="jsonBehavior"></endpoint>
        <endpoint address="rest" binding="webHttpBinding" name="xmlRest" contract="WCF.IService1" behaviorConfiguration="restBehaviour"></endpoint>
        <endpoint address="soap" binding="basicHttpBinding" name="soap" contract="WCF.IService1"></endpoint>
        <endpoint name="mex" address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/WCF"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="httpGetBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <webHttp defaultOutgoingResponseFormat="Json"/>
        </behavior>
        <behavior name="restBehaviour">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
</configuration>

代码

public class Service1 : IService1
{       
    public IList<Student> GetStudents()
    {
        IList<Student> students = new List<Student>();
        students.Add(new Student() { FirstNme = "Bob", LastName = "Long", StudentId = 1, Subject = "Economics" });
        students.Add(new Student() { FirstNme = "Jack", LastName = "Short", StudentId = 2, Subject = "IT" });
        return students;
    }
}

[ServiceContract]
public interface IService1
{       
    [WebGet(UriTemplate = "/students")]
    [OperationContract]
    IList<Student> GetStudents();

}

[DataContract]
public class Student
{
    private int _studentId;
    private string _firstName;
    private string _lastName;
    private string _subject;

    [DataMember]
    public int StudentId
    {
        get { return _studentId; }
        set { _studentId = value; }
    }

    [DataMember]
    public string FirstNme
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    [DataMember]
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    [DataMember]
    public string Subject
    {
        get { return _subject; }
        set { _subject = value; }
    }
}
公共类服务1:IService1
{       
公共图书馆(学生)
{
IList students=新列表();
添加(newstudent(){FirstNme=“Bob”,LastName=“Long”,StudentId=1,Subject=“Economics”});
添加(newstudent(){FirstNme=“Jack”,LastName=“Short”,StudentId=2,Subject=“IT”});
留学生;
}
}
[服务合同]
公共接口IService1
{       
[WebGet(UriTemplate=“/students”)]
[经营合同]
IList GetStudents();
}
[数据合同]
公立班学生
{
私立国际学生ID;
私有字符串_firstName;
私有字符串_lastName;
私有字符串(subject);;
[数据成员]
公立国际学生
{
获取{return\u studentId;}
设置{u studentId=value;}
}
[数据成员]
公共字符串FirstNme
{
获取{return\u firstName;}
设置{u firstName=value;}
}
[数据成员]
公共字符串姓氏
{
获取{return\u lastName;}
设置{u lastName=value;}
}
[数据成员]
公共字符串主题
{
获取{return\u subject;}
设置{u subject=value;}
}
}

这是一个已知的问题,在该问题中,为单个服务使用json、xml和soap端点会引发异常

我把它当作一个错误提出来了

如果您将框架切换到3.5,那么这将起作用,或者也提供了一个解决方案。您只需从请求对象获取内容头,并在代码中确定,以设置响应格式并相应地发送响应

同样在Web API中,如果WebGet/WebInvoke属性中未指定任何内容,则框架会根据内容类型自动确定这一点,并相应地返回响应


注意:当我试图在MS Connect上打开链接时,在MS Connect站点上发现一些系统错误。如果您想要解决方法,请让我知道我可以发送给您。另外,MS已经确认他们不会修复它,因为没有多少客户端希望在一个服务上公开所有3种格式。

Hmmm,我创建了一个非常简单的服务,可以使用SOAP、JSON和XML端点。它的工作仅仅是因为它的简单吗

我发现我必须为json和xml声明单独的绑定配置(尽管是空的)。以下是配置(已更新,因为以前只有system.serviceModel部分可见):

这是数据合同:

[ServiceContract]
public interface IAddressbookService {
  [OperationContract]
  [WebGet(UriTemplate = "Version")]
  string GetVersion();

  [OperationContract]
  [WebGet(UriTemplate = "Entries/Count")]
  int GetEntriesCount();

  [OperationContract]
  [WebGet(UriTemplate = "Entries")]
  Address[] GetEntries();

  [OperationContract]
  [WebGet(UriTemplate = "Entries/{name}")]
  Address[] SearchEntriesByName(string name);

  [OperationContract]
  [WebInvoke(Method = "POST", UriTemplate = "Entries/Add")]
  bool AddEntry(Address entry);

  [OperationContract]
  [WebInvoke(Method = "DELETE", UriTemplate = "Entries/Remove")]
  bool RemoveEntry(Address entry);
}
[DataContract]
public class Address {
  [DataMember]
  public string FirstName { get; set; }
  [DataMember]
  public string LastName { get; set; }
  [DataMember]
  public string Street { get; set; }
  [DataMember]
  public string City { get; set; }
  [DataMember]
  public int ZipCode { get; set; }
  [DataMember]
  public string Country { get; set; }
  [DataMember]
  public string Phone { get; set; }
  [DataMember]
  public string Email { get; set; }
}
请试一试



感谢您的反馈,实际上我终于在其他地方隐约找到了它,但似乎不容易找到。在这里,请求内容类型解决方案听起来像是一个不错的选择。WebAPI不提供WSDLA。您是在.NET 3.5还是.NET 4上?
[DataContract]
public class Address {
  [DataMember]
  public string FirstName { get; set; }
  [DataMember]
  public string LastName { get; set; }
  [DataMember]
  public string Street { get; set; }
  [DataMember]
  public string City { get; set; }
  [DataMember]
  public int ZipCode { get; set; }
  [DataMember]
  public string Country { get; set; }
  [DataMember]
  public string Phone { get; set; }
  [DataMember]
  public string Email { get; set; }
}
<bindings>
  <webHttpBinding>
    <binding name="webBindingXML"></binding>
    <binding name="webBindingSOAP"></binding>
  </webHttpBinding>
</bindings>