我有一个包含两个项目的解决方案.一个项目是ASP.NET Web应用程序项目,一个是类库.Web应用程序具有对类库的项目引用.这些都没有强烈的名称.
在类库中,我称之为"Framework",我有一个端点行为(一个IEndpointBehavior实现)和一个配置元素(一个派生自BehaviorExtensionsElement的类).配置元素是我可以通过配置将端点行为附加到服务.
在Web应用程序中,我有一个支持AJAX的WCF服务.在web.config中,我将AJAX服务配置为使用我的自定义行为.配置的system.serviceModel部分非常标准,如下所示:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehavior">
<enableWebScript />
<customEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="WebSite.AjaxService">
<endpoint
address=""
behaviorConfiguration="MyEndpointBehavior"
binding="webHttpBinding"
contract="WebSite.AjaxService" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add
name="customEndpointBehavior"
type="Framework.MyBehaviorExtensionsElement, Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
在运行时,这非常有效.启用AJAX的WCF服务正确使用我自定义配置的端点行为.
问题是当我尝试添加新的AJAX WCF服务时.如果我执行Add - > New Item ...并选择"启用了AJAX的WCF服务",我可以看到它添加.svc文件和代码隐藏,但是当它更新web.config文件时,我收到此错误:
配置文件不是WCF服务库的有效配置文件.
无法加载为扩展名'customEndpointBehavior'注册的类型'Framework.MyBehaviorExtensionsElement,Framework,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'.
显然,配置完全有效,因为它在运行时完美运行.如果我暂时从我的行为配置中删除该元素,然后添加启用了AJAX的WCF服务,那么一切都顺利进行.
不幸的是,在一个更大的项目中,我们将拥有各种配置的多个服务,暂时删除所有自定义行为将容易出错.虽然我意识到我可以不使用向导并且手动完成所有操作,但不是每个人都可以,并且能够使用产品,因为它本意使用 - 向导和所有.
为什么找不到我的自定义WCF行为扩展元素类型?
更新/澄清:
我在Microsoft Connect上提交了此问题,但事实证明您必须将自定义配置元素放在GAC中或将其放在IDE文件夹中.他们不会修复它,至少目前是这样.我已经发布了他们提供的解决方法作为这个问题的"答案".
我是代码审查WCF服务.在每条消息的标题中,我们注入服务稍后将用于构建到DB的连接字符串的数据.这是因为该服务将被许多不同的站点使用,每个站点都有自己的DB,服务必须查询.我们使用wcf扩展性.我们有一个自定义MessageInspector,在收到请求后,从消息头中提取数据,创建一个上下文(实现IExtension)并将其添加到OperationContext.Current.Extensions.在发送回复之前,将从Extencions集合中删除自定义上下文.
这是一种相当常见的模式,如下所述:
在哪里存储当前WCF呼叫的数据?ThreadStatic安全吗?
和这里:
只要服务收到请求,处理请求,发送回复并接收下一个请求,这一切都可以正常工作.但是,如果服务收到请求并且在能够回复之前获得第二个请求怎么办?我构建了一个小型控制台应用程序来测试它.我从2个不同的线程发送2条消息,我让wcf服务等待2秒,以确保第一个请求在第一个请求完成之前进入,这就是我得到的:
网站ID:test1450; 会话:uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70; id = 2:线程ID:6
网站ID:test1450; 会话:uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70; id = 3:线程ID:22
看起来wcf在2个不同的线程上创建了2个会话,但Site Id是相同的.它不应该.从这一点来看,它看起来像OperationContext.Current.Extensions是一个在线程之间共享的集合.现在我倾向于认为我的测试是错误的,我错过了一些东西.
有没有人尝试类似的东西,发现OperationContext.Current不是线程安全的?
我正在努力更好地了解WCF的调度过程,特别是对各种可扩展性点的影响和影响.从底部列出的网页看,一旦消息通过通道堆栈传递给调度程序,WCF将按照所述顺序执行以下操作.
我试图找到一些选项来解决我遇到的问题,我想到的一种方法是使用Message Inspector,Operation Selector,Message Formatting和Operation Invoker的组合.不幸的是,我的观察似乎表明执行的顺序如下:
我可以理解在格式化消息之前调用自定义调用者AllocateInputs()方法的细微差别,因为消息格式化部分基本上将给定消息反序列化为一组方法参数,以传递给适当的操作和调用者的AllocateInputs( )方法指定预期的参数数量.
抛出我的部分是Message Inspector和Operation Selector之间的序列反转.对于我来说,消息检查器首先运行,因为它们对消息起作用,而操作选择器确定消息所针对的服务操作,这听起来合乎逻辑.
问题:
参考页:
扩展WCF以支持自定义数据格式 - Zulfiqar的博客
使用自定义行为扩展WCF - MSDN服务站2007年12月
消息流拦截点 - Nicholas Allen的Indigo博客
注意:对于不提供链接,我道歉,因为我还是菜鸟,所以不能有多个链接.=)
我一直在fx3.5上使用WCF学习和构建JSONP Web服务.您可以阅读我在.NET ASMX上的一些试验- 返回Pure JSON?我终于得到了一个样本运行,但现在我正在将它拖入我的应用程序中.
该服务的web.config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="JsonpServiceBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="RivWorks.Web.Service.CustomerService">
<endpoint address=""
binding="customBinding"
bindingConfiguration="jsonpBinding"
behaviorConfiguration="JsonpServiceBehavior"
contract="RivWorks.Web.Service.ICustomerService" />
</service>
<service name="RivWorks.Web.Service.NegotiateService">
<endpoint address=""
binding="customBinding"
bindingConfiguration="jsonpBinding"
behaviorConfiguration="JsonpServiceBehavior"
contract="RivWorks.Web.Service.INegotiateService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="jsonpBinding" >
<jsonpMessageEncoding />
<httpTransport manualAddressing="true"/>
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="jsonpMessageEncoding"
type="RivWorks.Web.Service.JSONP.JsonpBindingExtension
, RivWorks.Web.Service
, Version=1.0.0.0
, Culture=neutral
, …Run Code Online (Sandbox Code Playgroud) 我试图在Silverlight客户端应用程序中捕获来自WCF服务的常规异常.为此,我已经在我的WCF服务中包含了相应的更改,如本MSDN文章中所述.
但是,当我配置行为扩展并在端点行为中使用相同的行为时,上面提到的错误即将发生,并且由于此错误,服务无法运行.
我在这里配置我的配置.请建议我该如何解决这个问题?
<extensions>
<!--Add a behavior extension within the service model-->
<!-- Here SilverlightFaultBehavior is a class in AppServiceLib namespace -->
<behaviorExtensions>
<add name="myFaultExtension"
type="AppServiceLib.SilverlightFaultBehavior,AppServiceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<endpointBehaviors>
<behavior name="myFaultBehavior">
<**myFaultExtension**/>
</behavior>
</endpointBehaviors>
Run Code Online (Sandbox Code Playgroud) 我在我的项目中定义了一个覆盖的类,我IDispatchMessageInspector添加了相关的配置,但它不起作用
System.Configuration.ConfigurationErrorsException:无法加载为扩展名'customHeaders'注册的类型'InMotionGIT_NT.Address.Service,CustomHeaders,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'.(C:\ Users\jmachado\Documents\Visual Studio 2010\Projects\InMotionGIT_NT\Address Service\InMotionGIT_NT.Address.Service\bin\Debug\InMotionGIT_NT.Address.Service.dll.config line 67)
这就是我调用自定义扩展的方式
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
<customHeaders/>
<!--<webHttp/>-->
</behavior>
</endpointBehaviors>
Run Code Online (Sandbox Code Playgroud)
这就是我定义自定义扩展的方式
<behaviorExtensions>
<add name="customHeaders" type="InMotionGIT_NT.Address.Service, CustomHeaders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
Run Code Online (Sandbox Code Playgroud)
这是我定义的类,它在我的项目中
[AttributeUsage(AttributeTargets.Class)]
public class CustomHeaders : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, ClientChannel channel, InstanceContext instanceContext)
{
if ((WebOperationContext.Current.IncomingRequest.Method == "GET"))
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我是否会错过配置中的某些内容?
一些上下文:我们有一个自定义XSD,并使用WSCF.blue生成WSDL和C#代码.客户端使用ChannelFactory<T>并共享接口,该接口包括WSCF.blue添加的所有属性以匹配XSD中的内容.
我正在尝试实现IErrorHandler.ProvideFault它提供泛型的地方FaultException<T>,但在客户端我得到的是非泛型的FaultContract.这是我的ProvideFault方法的样子:
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (!(error is FaultException))
{
FaultException faultException = FaultExceptionFactory.CreateFaultException(error);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
Run Code Online (Sandbox Code Playgroud)
在每个服务方法中,如果我使用try/catch,throw FaultExceptionFactory.CreateFaultException(ex)它按预期工作,所以我认为[FaultContract],工厂,绑定等都是正确的.以防万一,这就是工厂的工作原理:
BusinessRuleFaultExceptionType businessRuleFaultException = new BusinessRuleFaultExceptionType();
BusinessRuleFaultException.Code = exception.Code.ToString();
BusinessRuleFaultException.Reason = exception.Message;
return new FaultException<BusinessRuleFaultExceptionType>(
businessRuleFaultException,
exception.Message,
new FaultCode(exception.Code.ToString())
);
Run Code Online (Sandbox Code Playgroud)
我认为问题在于如何创建消息IErrorHandler,也许是在CreateMessageFault().我已经读过这个动作应该faultException.Action代替null,但实际上faultException.Action是null.也许这导致了这个问题.我可以在工厂设置一个动作,但是动作应该是什么,为什么不会出现手动抛出? …
在我的WCF项目中,我需要在响应中使用自定义标头,因此我实现了IDispatchMessageInspector.老实说,一切都很好,但我对一件小事情感到不安.
问题是即使我只是将.svc作为页面打开,或者将服务加载到WCF测试客户端,BeforeSendReply和AfterReceiveRequest都会触发.
所以,第一个问题:这种行为是正常的吗?有没有办法以声明方式处理(可能是一些web.config技巧)?
目前我使用下一个代码:
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.Properties.Any(x => x.Key == "httpResponse"))
return;
MessageHeader header = MessageHeader.CreateHeader("Success", "NS", !reply.IsFault);
reply.Headers.Add(header);
}
Run Code Online (Sandbox Code Playgroud)
所以现在我通过使用它来处理所有不是服务调用的调用:
if (reply.Properties.Any(x => x.Key == "httpResponse"))
return;
Run Code Online (Sandbox Code Playgroud)
但我很确定还有其他一些更好的方法可以解决这个问题.所以我的主要问题是:请建议我一个更好的方法来处理描述的情况.
提前致谢!
更新1
我的system.serviceModel部分
<system.serviceModel>
<services>
<service behaviorConfiguration="someBehavior" name="serviceName">
<endpoint address="" binding="basicHttpBinding" contract="my contract" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="someBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<exceptionInspector/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="exceptionInspector" type="class which …Run Code Online (Sandbox Code Playgroud) 对于我的 WCF 客户端,我希望能够为给定端点的每个操作做一些前期和后期工作。
鉴于此,IParameterInspector(及其BeforeCall和AfterCall)给了我几乎所有我需要的东西。问题是
AfterCall不会被调用(请参阅此处)。 为了帮助解决这个问题,我可以添加一个,IClientMessageInspector因为它AfterReceiveReply确实会在遇到异常时被调用。这让我有能力
题:
IClientMessageInspector.AfterReceiveReply获取(或创建等效的)异常来表示最终将抛出给调用者的内容。如果是这样,有没有办法将异常标记为已处理,以便调用者不会收到异常?这是我的客户端WCF配置文件:
<configuration>
<system.net>
<defaultProxy
enabled="true"
useDefaultCredentials="true">
<proxy
usesystemdefault="False"
bypassonlocal="False"
proxyaddress="http://172.20.20.254:8088/"
/>
</defaultProxy>
</system.net>
<system.serviceModel>
<client>
<endpoint
address="http://172.20.20.100:8080/Demo/text"
binding="customBinding"
bindingConfiguration="text"
contract="DemoService.IDemoService"
behaviorConfiguration="largeObjectGraph_behaviorConfig"
name="text" />
</client>
<!-- Allow To Desrialize Larg Data -->
<behaviors>
<endpointBehaviors>
<behavior name="largeObjectGraph_behaviorConfig">
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="text"
closeTimeout="10675199.02:48:05.4775807"
openTimeout="10675199.02:48:05.4775807"
receiveTimeout="10675199.02:48:05.4775807"
sendTimeout="10675199.02:48:05.4775807">
<CustomMessageEncoder
MaxArrayLength="1073741824"
MaxBytesPerRead="1073741824"
MaxDepth="1073741824"
MaxNameTableCharCount="1073741824"
MaxStringContentLength="1073741824" />
<httpTransport
maxBufferPoolSize="1073741824"
maxReceivedMessageSize="1073741824"
maxBufferSize="1073741824" />
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="CustomMessageEncoder" type="CustomMessageEncoder.CustomMessageEncodingElement, CustomMessageEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bindingElementExtensions>
</extensions>
</system.serviceModel>
</configuration>
Run Code Online (Sandbox Code Playgroud)
使用CustomMessageEncoder绑定以压缩和加密消息.
这是问题:我们的局域网中有Proxy-Server [172.20.20.254:8088]. …
如果我有几个相同类型的WCF扩展模块(如参数检查器),我可以确定它们是按照我在配置文件中定义它们的顺序执行的吗?
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="MyInspectorA" type="blabla" />
<add name="MyInspectorB" type="blabla" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
我需要更多的保证,而不仅仅是我的观察,但在MSDN上找不到任何确认.
如果同时IParameterInspector和IErrorHandler连接到一个服务,我可以肯定IErrorHandler.HandleError()将在同一个线程在那里叫上IParameterInspector.BeforeCall()叫?
我需要这个,因为在抛出错误的情况下IParameterInspector.AfterCall()永远不会被调用,并且没有办法(据我所知)我可以获得创建的关联状态对象BeforeCall().所以我希望通过ThreadStatic在我的接口实现中有一个字段来克服这个问题:(
wcf ×12
wcf-extensions ×12
.net ×6
c# ×5
.net-4.0 ×1
jsonp ×1
wcf-4 ×1
wcf-binding ×1
web-config ×1