我有一个旧的 WCF 项目,它接收 xml 类型的调用后。
最近,呼叫者称他们在拨打我们的端点时遇到 500。
但当我们查看日志时,并没有与调用失败相关的记录。
经过进一步调查,我们认为调用从未执行/正确输入方法,因此没有日志。
该调用没有命中该方法,因为帖子中的 xml 内容被截断,因此无法反序列化参数。
例如
<!-- missing </PartNumberUpdate> -->
<PartNumberUpdate>
<PartNumbers>
<PartNumber>
<LicenseNo>001</LicenseNo>
<Description>xxx</Description>
</PartNumber>
<PartNumber>
<LicenseNo>001</LicenseNo>
<Description>yyy</Description>
</PartNumber>
<PartNumbers>
// the xml in post can't convert to param input cause it's incomplete
public void ProcessPartNumberUpdate(PartNumberUpdate input)
{
...
}
但是调用者声称他们发布的 XML 是完整的,并且由于调用从未命中该方法,因此我们没有任何日志来判断这是否属实。
因此,我试图找到一种方法来记录错误,即使该方法未执行。 我在网上搜索了一下,似乎IErrorHandler最符合我的要求。
但是,根据说明将代码和xml设置移植到我的项目后。 我遇到了
类型'Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior, HostApplication,版本=0.0.0.0,文化=中性, PublicKeyToken=null' 为扩展 'enforceGreetingFaults' 注册 无法加载。
而 IIS 则表达 Visual Studio 中的 Web 服务。
错误列表中也有警告
元素“behavior”具有无效的子元素 '强制问候错误'。预期可能的元素列表: 'serviceAuthenticationManager,明确,serviceAuthorization, 服务凭证、服务元数据、服务安全审计、 服务节流、数据契约序列化器、服务调试、 serviceTimeouts、删除、useRequestHeadersForMetadataAddress、 persistenceProvider、workflowRuntime、etwTracking、bufferedReceive、 工作流空闲、工作流UnhandledException、sendMessageChannelCache、 sqlWorkflowInstanceStore、workflowInstanceManagement、 服务发现、路由'。
不知道是不是因为我的WCF已经很老了?但我已经将目标框架更新到4.7.2.
我使用指令中的所有 C# 代码创建了一个 ServiceHostGeneralErrorHandler 类。
并将xml设置移植到我的as
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true"/>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="MyPorjectMetadata_RESTService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</sectionGroup>
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General" logWarningsWhenNoCategoriesMatch="false">
<listeners>
<add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" source="MyPorjectMetadata" formatter="Text Formatter" log="MyPorjectMetadata" machineName="." traceOutputOptions="None"/>
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" template="Message: {message}{newline}" name="Text Formatter"/>
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="Event Log Listener"/>
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="Off" name="All Events"/>
<notProcessed switchValue="Off" name="Unprocessed Category"/>
<errors switchValue="Off" name="Logging Errors & Warnings">
<listeners>
<add name="Event Log Listener"/>
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
<system.net>
<mailSettings>
<smtp>
<network host="smtp-americas.my-company.com" port="25"/>
</smtp>
</mailSettings>
</system.net>
<connectionStrings>
<add name="MyPorjectMetadata_RESTService.Properties.Settings.strConnectionString" connectionString="server=.;database=my-companyDistributionKeyStore;Trusted_Connection=Yes; application name=MyPorjectMetadata_RESTService"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.7.2"/>
<authentication mode="Windows"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="largeMessageBinding" maxReceivedMessageSize="4194304"/>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MyPorjectMetadata_RESTService.Service1Behavior" name="MyPorjectMetadata_RESTService.Service1">
<endpoint address="" binding="webHttpBinding" contract="MyPorjectMetadata_RESTService.IService1" behaviorConfiguration="web" bindingConfiguration="largeMessageBinding">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyPorjectMetadata_RESTService.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<enforceGreetingFaults/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add
name="enforceGreetingFaults"
type="Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior, HostApplication, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
<applicationSettings>
<MyPorjectMetadata_RESTService.Properties.Settings>
<!-- some properites -->
</MyPorjectMetadata_RESTService.Properties.Settings>
</applicationSettings>
</configuration>
我想也许是因为我没有dll?所以我试图从 Nuget 中找到
Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior
但找不到类似的东西。
总结一下我的问题,
我的资深同事指导我使用。
关键是,
Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior
是我们应该自己写的。
所以你需要在你的项目下创建类(IServiceBehavior
)。
public class EnforceGreetingFaultBehavior : BehaviorExtensionElement, IServiceBehavior
{
public override Type BehaviorType => typeof(EnforceGreetingFaultBehavior);
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler = new ServiceHostGeneralErrorHandler();
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
cd.ErrorHandlers.Add(errorHandler);
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
return;
}
protected override object CreateBehavior()
{
return new EnforceGreetingFaultBehavior();
}
}
然后是
IErrorHandler
的课程
public class ServiceHostGeneralErrorHandler : IErrorHandler
{
#region IErrorHandler Members
public bool HandleError(Exception error)
{
Console.WriteLine("HandleError called.");
// Returning true indicates you performed your behavior.
return true;
}
// This is a trivial implementation that converts Exception to FaultException<GreetingFault>.
public void ProvideFault(
Exception error,
MessageVersion ver,
ref Message msg
)
{
Console.WriteLine("ProvideFault called. Converting Exception to GreetingFault....");
FaultException<string> fe
= new FaultException<string>(error.Message);
MessageFault fault = fe.CreateMessageFault();
msg = Message.CreateMessage(
ver,
fault,
"http://microsoft.wcf.documentation/ISampleService/SampleMethodGreetingFaultFault"
);
}
#endregion
}
最后,在 web.config 中
behaviorExtensions
,您需要正确的程序集限定名称
<extensions>
<behaviorExtensions>
<add
name="enforceGreetingFaults"
type="MyPorjectMetadata_RESTService.ServiceBehaviors.EnforceGreetingFaultBehavior, MyPorjectMetadata_RESTService, Version=2.0.0.5, Culture=neutral, PublicKeyToken=null"
/>
</behaviorExtensions>
</extensions>
您可以获得合格的名字
string qn = typeof(EnforceGreetingFaultBehavior).Assembly.FullName.ToString();
完成上述
<enforceGreetingFaults/>
中的 serviceBehaviors
后应该可以正常工作。