request.GetRequestStream()抛出“Value not not null”异常

时间:2017-05-15 11:57:13

标签: c# webrequest .net-4.6.2

我有一个函数可以对接受jsons的api服务器执行http请求:

 private static string DoRequest(object objToSend, string Url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.Accept = "application/json";
            var jsonString= Obj2Json(objToSend);
            if (string.IsNullOrEmpty(jsonString))
                throw new ArgumentNullException("objToSend", "Objcet was converted to json string and produces an empty string");
            var buffer = Encoding.UTF8.GetBytes(jsonString);
            request.ContentLength = buffer.Length;
            using (var stream = request.GetRequestStream())
            {
                stream.Write(buffer, 0, buffer.Length);
            }
            var response = (HttpWebResponse)request.GetResponse();
            var sResponse = new System.IO.StreamReader(response.GetResponseStream()).ReadToEnd();

            return sResponse;
        }

当我跑线时:

using (var stream = request.GetRequestStream())

我有一个例外: mscorlib.dll中的“System.ArgumentNullException”(“值不能为空。”)System.ArgumentNullException。

在StackTrace中有一行说:

  

“System.Enum.TryParseEnum(类型enumType,String value,Boolean ignoreCase,EnumResult& parseResult)”

单击F10键即可消除异常。

有没有人知道为什么抛出异常?

我想强调它会在GetRequestStream()之前抛出异常,这是在使用stream之前的.Write()

在浪费了大量时间之后,我发现从ServicePointManager.cs中抛出了这个excaption,它是system.dll的一部分。 这是函数导致异常:

private static void LoadDisableStrongCryptoConfiguration()
{
    try
    {
        bool disableStrongCryptoInternal = false;
        int schUseStrongCryptoKeyValue = 0;

        if (LocalAppContextSwitches.DontEnableSchUseStrongCrypto)
        {
            //.Net 4.5.2 and below will default to false unless the registry key is specifically set to 1.
            schUseStrongCryptoKeyValue =
                RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 0);

            disableStrongCryptoInternal = schUseStrongCryptoKeyValue != 1;
        }
        else
        {
            // .Net 4.6 and above will default to true unless the registry key is specifically set to 0.
            schUseStrongCryptoKeyValue =
                RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 1);

            disableStrongCryptoInternal = schUseStrongCryptoKeyValue == 0;
        }

        if (disableStrongCryptoInternal)
        {
            // Revert the SecurityProtocol selection to the legacy combination.
            s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
        }
        else
        {
            s_SecurityProtocolType =
                SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

            string appSetting = RegistryConfiguration.AppConfigReadString(secureProtocolAppSetting, null);

            SecurityProtocolType value;
            try
            {
                value = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), appSetting);
                ValidateSecurityProtocol(value);
                s_SecurityProtocolType = value;
            }
            // Ignore all potential exceptions caused by Enum.Parse.
            catch (ArgumentNullException) { }
            catch (ArgumentException) { }
            catch (NotSupportedException) { }
            catch (OverflowException) { }
        }

        disableStrongCrypto = disableStrongCryptoInternal;
    }
    catch (Exception e)
    {
        if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
        {
            throw;
        }
    }
}

这是完整的调用Stack

  

mscorlib.dll!System.Enum.TryParseEnum(System.Type enumType,string   value,bool ignoreCase,ref System.Enum.EnumResult parseResult)   mscorlib.dll!System.Enum.Parse(System.Type enumType,string value,   bool ignoreCase)   的 System.dll中!System.Net.ServicePointManager.LoadDisableStrongCryptoConfiguration()   System.dll中!System.Net.ServicePointManager.EnsureConfigurationLoaded()   System.dll中!System.Net.ServicePointManager.SecurityProtocol.get()   System.dll中!System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult   结果)System.dll!System.Net.TlsStream.Write(byte [] buffer,int   offset,int size)System.dll!System.Net.PooledStream.Write(byte []   buffer,int offset,int size)   System.dll!System.Net.ConnectStream.WriteHeaders(bool async)   System.dll中!System.Net.HttpWebRequest.EndSubmitRequest()   System.dll中!System.Net.HttpWebRequest.SetRequestSubmitDone(System.Net.ConnectStream   submitStream)System.dll!System.Net.Connection.CompleteConnection(bool   async,System.Net.HttpWebRequest request)   System.dll!System.Net.Connection.CompleteStartConnection(bool async,   System.Net.HttpWebRequest httpWebRequest)   System.dll中!System.Net.Connection.CompleteStartRequest(布尔   onSubmitThread,System.Net.HttpWebRequest请求,System.Net.TriState   needReConnect)   System.dll中!System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest   请求,bool forcedsubmit)   System.dll中!System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest   请求,字符串connName)   System.dll中!System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint   服务点)   System.dll中!System.Net.HttpWebRequest.GetRequestStream(出   System.Net.TransportContext context)   System.dll中!System.Net.HttpWebRequest.GetRequestStream()   RivhitApi.dll!RivhitApi.RivhitService.DoRequest(object objToSend,   string Url)第59行

2 个答案:

答案 0 :(得分:1)

根据the documentation,当缓冲区为空时,Write方法将抛出ArgumentNullException。在您的情况下,这意味着bJsonReq为空。

在致电Write之前确保它不为空。

答案 1 :(得分:0)

根据this microsoft document添加这行代码解决了这个问题。

private const string DisableCachingName = @"TestSwitch.LocalAppContext.DisableCaching";
private const string DontEnableSchUseStrongCryptoName = @"Switch.System.Net.DontEnableSchUseStrongCrypto";
AppContext.SetSwitch(DisableCachingName, true);
AppContext.SetSwitch(DontEnableSchUseStrongCryptoName, true);

在该文件中还有更多选项来设定这种定义。

但缺点可能是安全性下降。 我正在寻找一个更智能的解决方案,可能是以某种方式设置 ServicePointManager ,其方式是 SecurityProtocolType 不为空。现在我找不到这样的。