WCF踩的坑及个人理解
wpf项目需要提供外部访问的接口,于是想到了WFC,开发过程中发现了许多坑,记录下来方便以后避雷。
基本使用
开启服务
WebServiceHost service = new WebServiceHost(typeof(Service1));
service.Open();
配置文件
<appSettings>
//异步运行,core好像是不需要设置,没有测试
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
//调试 发布改为false
<compilation debug="true" />
</system.web>
<system.serviceModel>
//协议webHttpBinding才可以http请求
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<services>
<service name="WcfService.Service1" behaviorConfiguration="WebBehavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:18733/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- 除非完全限定,否则地址相对于上面提供的基址-->
//behaviorConfiguration设置才可以http请求
<endpoint address="" binding="webHttpBinding"
contract="WcfService.IService1"
behaviorConfiguration="endBehavior"
>
</endpoint>
</service>
</services>
//协议设置
<behaviors>
<serviceBehaviors>
<behavior name="WebBehavior">
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将以下值设置为 true。在部署前设置为 false
以避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name ="endBehavior">
<!--以下参数的释义
1.是否启用帮助页面
2.参数与响应的封装类型(此处为都封装)
3.默认的返回主体格式化(此处为返回json格式)
4.是否自动选择请示正文和响应正文的格式化(如果为true,则会先去找http请示标头上的Accept,
再找契约方法上有无 RequestFormat/ResponseFormat,如果没有,则找此配置中有无
defaultOutgoingResponseFormat
5.启用异常输出
-->
<webHttp helpEnabled="true"
defaultBodyStyle="Bare"
defaultOutgoingResponseFormat="Json"
automaticFormatSelectionEnabled="true"
faultExceptionEnabled="true"
/>
<!--<webHttp />-->
</behavior >
</endpointBehaviors>
</behaviors>
<!--添加绑定-->
<bindings>
<!--添加web绑定-->
<webHttpBinding>
<!--是否启用跨域-->
<binding crossDomainScriptAccessEnabled="false" />
</webHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
服务接口
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "*")]
string GetData(TestParam value);
[OperationContract]
[WebInvoke(Method = "*")]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: 在此添加您的服务操作
}
// 使用下面示例中说明的数据约定将复合类型添加到服务操作。
// 可以将 XSD 文件添加到项目中。在生成项目后,可以通过命名空间“WcfService.ContractType”直接使用其中定义的数据类型。
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
public class TestParam
{
public int value { get; set; }
}
服务实体
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Service1”。
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public string GetData(TestParam value)
{
return string.Format("You entered: {0}", value.value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
以上设置好就可以使用WFC服务了,以下是遇到的坑
WFC不支持net8
WFC只能在framework框加使用,所以net框架不能使用,但可以新建framework的WFC库项目,在net框架下引用。
ajax请求
如果是c# 其它项目访问,默认设置就可以,
但如果想在web端发起GET,POST请求,需要设置以下几点
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<behaviors>
<endpointBehaviors>
<behavior name ="endBehavior">
<webHttp helpEnabled="true"
defaultBodyStyle="Bare"
defaultOutgoingResponseFormat="Json"
automaticFormatSelectionEnabled="true"
faultExceptionEnabled="true" />
</behavior >
</endpointBehaviors>
</behaviors>
app.config中
protocolMapping 协议必须为webHttpBinding
webHttp 必须要有,
defaultBodyStyle=“Bare” 必须是不封装,否则400
defaultOutgoingResponseFormat=“Json” 设置默认格式JSON
IService1接口中
[WebInvoke(Method = “")]
WebInvoke特性是http请求可以访问,必须加,默认POST,(Method = "”)指定为通用。由于app.config中设置了 defaultOutgoingResponseFormat=“Json” ,RequestFormat,ResponseFormat参数可以不用设置,如果都不设置默认是xml格式。
参数必须封装成类
方法体的传参必须封装,个人理解是由于参数都要进行JSON序列化,如果参数直接是int,string等类型,进行json序列化时就会报错,所以必须封装才能使用。此处也是折磨了我很久,一开始测试接口参数只是int,报错还以为是配置文件没有设对。