Can';t仅通过配置为WCF正确公开REST XML、REST JSON和SOAP
我希望能够构建一个WCF服务,实现以下目标: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方法的单独函数。我已经做了大量的研究,但我找不到任何可靠的证据来证明这是否完全可以通过配置
- 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>