用户代理在.NET Core

时间:2018-03-13 17:31:29

标签: c# wcf .net-core

我们有一个用.NET Standard 2.0编译的库,它有一个WCF服务。为了向Web服务的请求添加自定义标头,我们在此处实现了代码:https://blogs.msdn.microsoft.com/mohamedg/2012/12/13/adding-http-headers-to-wcf-calls/

当我们在.NET Framework应用程序中引用此库时,我们可以对我们想要的Web服务进行任何调用,并且返回正确的结果。但是,在.NET Core 2.0应用程序中,库通常(但不总是!)会抛出System.FormatException,具体取决于我们设置的用户代理。

像“Mozilla / 4.0”这样的东西不会抛出错误,但“Mozilla / 4.0(兼容; MSIE 6.0; MS Web服务客户端协议4.0.30319.42000)”将但仅带有错误消息“值的格式”(兼容; MSIE 6.0; MS Web服务客户端协议4.0.30319.42000)的核心应用程序无效。“。

简而言之,这是代码(从接口中省略了没有实现的方法)。当前用户代理仅为了排除故障而硬编码。

internal class ClientUserAgentMessage : IClientMessageInspector
{
    public ClientUserAgentMessage(string userAgent) { }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        HttpRequestMessageProperty property = new HttpRequestMessageProperty();

        //This is an example user agent that fails, and we would not expect it to.
        property.Headers["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.42000)";
        request.Properties.Add(HttpRequestMessageProperty.Name, property);

        return null;
    }
}

internal class UserAgentEndpointBehavior : IEndpointBehavior
{
    public UserAgentEndpointBehavior() { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new ClientUserAgentMessage());
    }
}

上面的代码是在引用标准dll的应用程序中实现的(省略客户端初始化详细信息):

//SoapClient and related WCF code is generated from the web service via svcutil.exe
SoapClient client = new SoapClient(...);
client.Endpoint.EndpointBehaviors.Add(new UserAgentEndpointBehavior());

//Call some web service functions...
//This succeeds in a .NET 4.7 app, 
//but blows up in a .NET Core 2.0 app due to the user agent being an "invalid format".
//client.Login();

当用户代理实际上看起来是有效格式时,为什么这只是.NET Core的问题?它似乎抱怨哪里有更多的1 /,括号,冒号,分号,空格......基本上除了第一个/,下划线和小数之外的任何非字母数字。

根据要求,完整的堆栈跟踪:

   at System.Net.Http.Headers.HttpHeaderParser.ParseValue(String value, Object storeValue, Int32& index)
   at System.Net.Http.Headers.ProductInfoHeaderValue.Parse(String input)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.PrepareMessageHeaders(Message message)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.<SendRequestAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.ServiceModel.Channels.RequestChannel.<RequestAsync>d__33.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.ServiceModel.Channels.RequestChannel.<RequestAsyncInternal>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.TaskHelpers.WaitForCompletionNoSpin[TResult](Task`1 task)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
   at generatedProxy_1.Login(LoginRequest )
   at MyServiceNamespace.SoapClient.ServiceNamespace.Soap.Login(LoginRequest request)
   at MyServiceNamespace.SoapClient.Login(String strUser, String strPass, String strKey)
   at MyLibraryNamespace.MyClass.Login(String sUser, String sPass, String sKey)  

FWIW,你可以设置为“User-Agent”以外的标题,一切都很好(至少,我试过“XTESTX”,也没有例外)。

1 个答案:

答案 0 :(得分:0)

我于2018年3月14日在GitHub上打开了issue

看起来像是在五月之后通过此pull request得到了解决和修复,不再是问题。