我有这项服务
[OperationContract]
[WebGet(UriTemplate = "/GetData")]
List<FieldInfo> GetSerializedData();
和web.config
<system.web>
<webServices>
<protocols>
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
<httpRuntime executionTimeout="90" maxRequestLength="1048576" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100"/>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingSettings" maxBufferPoolSize="524288" maxReceivedMessageSize="654321" sendTimeout="00:10:00" closeTimeout="00:01:00" openTimeout="00:10:00" receiveTimeout="00:10:00">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
<wsHttpBinding>
<binding name="wsHttpBindingSettings" maxBufferPoolSize="524288" maxReceivedMessageSize="654321" sendTimeout="00:10:00" closeTimeout="00:01:00" openTimeout="00:10:00" receiveTimeout="00:10:00">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MetadataBehavior" name="ServiceModel.Service">
<endpoint name="soap" address="soap" behaviorConfiguration="Default" binding="wsHttpBinding"
bindingConfiguration="wsHttpBindingSettings" contract="ServiceModel.IService" />
<endpoint name="Json" address="json" behaviorConfiguration="JSON" binding="webHttpBinding"
bindingConfiguration="webHttpBindingSettings" contract="ServiceModel.IService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://service.com/Service.svc/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MetadataBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="JSON">
<webHttp automaticFormatSelectionEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="10000000"/>
</behavior>
<behavior name="Default">
<dataContractSerializer maxItemsInObjectGraph="10000000"/>
</behavior>
</endpointBehaviors>
</behaviors>
为什么在客户端只生成一个端点?
<client>
<endpoint address="http://service.renault.com/Service.svc/soap"
binding="wsHttpBinding" bindingConfiguration="soap" contract="ServiceReference1.IService"
name="soap" />
</client>
我的观点是从asp.net页面代码隐藏执行服务方法,而soap或json中的wcf返回数据依赖于ContentType。但是当它有text / html内容时,如何在asp.net页面内容类型中设置application / json。我理解它有问题。
答案 0 :(得分:3)
为什么在客户端只生成一个端点?
因为WCF不为非SOAP端点发出元数据。与用于SOAP的WSDL和MEX不同,“REST”端点没有广泛使用的元数据格式(WADL是其中之一,但它没有太多使用而且没有由WCF实现),因此在添加服务引用(或svcutil)上只会看到元数据中的一个端点,只创建一个端点。
我想使用WCF功能,选择正确的序列化类型取决于请求的ContentType
JSON vs XML是序列化类型决策; JSON vs SOAP不是(SOAP是一个定义良好的协议,具有请求应该是什么样的规则) - 请参阅WCF Dynamic Response Format的更多信息。您的webHttBinding
- 端点将执行此操作(根据传入请求返回JSON或XML),因为您启用了自动格式选择,但您使用此服务的方式不需要与WCF客户端一起使用 - 使用WebClient
,HttpWebRequest
应该可以正常运行。
答案 1 :(得分:1)
如果可能的话,尝试像这样设计Visual Studio:
以下是我在类似于您的场景中使用的示例类:
public class ServiceHelper
{
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TService">The type of the service to use</typeparam>
/// <param name="action">Lambda of the action to performwith the service</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingProxy<TService>(Action<TService> action)
where TService : ICommunicationObject, IDisposable, new()
{
var service = new TService();
bool success = false;
try
{
action(service);
if (service.State != CommunicationState.Faulted)
{
service.Close();
success = true;
}
}
finally
{
if (!success)
{
service.Abort();
}
}
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <remarks>In the configuration, an endpoint with names that maches the <typeparamref name="TIServiceContract"/> name
/// must exists. Otherwise, use <see cref="UsingContract<TIServiceContract>(string endpointName, Action<TIServiceContract> action)"/>. </remarks>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(Action<TIServiceContract> action)
{
UsingContract<TIServiceContract>(
typeof(TIServiceContract).Name,
action
);
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <param name="endpointName">Name of the endpoint to use</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(
string endpointName,
Action<TIServiceContract> action)
{
var cf = new ChannelFactory<TIServiceContract>(endpointName);
var channel = cf.CreateChannel();
var clientChannel = (IClientChannel)channel;
bool success = false;
try
{
action(channel);
if (clientChannel.State != CommunicationState.Faulted)
{
clientChannel.Close();
success = true;
}
}
finally
{
if (!success) clientChannel.Abort();
}
}
}
在客户端配置中,我手动设置了我的引用:
<system.serviceModel>
<client>
<endpoint address="http://localhost/myapp/myservice.svc/soap"
binding="wsHttpBinding"
contract="MyProject.Contracts.IMyService"
name="IMyServiceSoap"/>
<endpoint address="http://localhost/myapp/myservice.svc/rest"
binding="webHttpBinding"
contract="MyProject.Contracts.IMyService"
name="IMyServiceRest"/>
</client>
</system.serviceModel>
然后,在您的代码中,您只需致电:
ServiceHelper.UsingContract<"IMyServiceSoap", MyProject.Contracts.IMyService>(
svc => svc.DoTheJob()
);
或
ServiceHelper.UsingContract<"IMyServiceRest", MyProject.Contracts.IMyService>(
svc => svc.DoTheJob()
);
[edit] 服务器配置与此类似:
<services>
<service name="MyService">
<endpoint address="soap"
binding="wsHttpBinding"
contract="MyContracts.IMyService"/>
<endpoint address="rest"
binding="webHttpBinding"
contract="MyContracts.IMyService"/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>