3

I have a function to do http request to a api servers who accept jsons:

 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;
        }

When I run the line:

using (var stream = request.GetRequestStream())

I got an Exception: 'System.ArgumentNullException' in mscorlib.dll ("Value cannot be null.") System.ArgumentNullException.

in the StackTrace there was one line that says:

"System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)"

the Exception is disappearing by clicking the F10 key.

Does anyone have any idea about, why the exception was thrown?

I want to emphasize that it throws the exception at the GetRequestStream(), that is before to any use of the stream.Write()

After wasting huge of time, I discovered that the excaption was thrown from ServicePointManager.cs that is part of system.dll. Here is the function was causes the exception:

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;
        }
    }
}

here is the full call 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 result) 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(bool onSubmitThread, System.Net.HttpWebRequest request, System.Net.TriState needReConnect) System.dll!System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest request, bool forcedsubmit) System.dll!System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest request, string connName) System.dll!System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint servicePoint) System.dll!System.Net.HttpWebRequest.GetRequestStream(out System.Net.TransportContext context) System.dll!System.Net.HttpWebRequest.GetRequestStream() RivhitApi.dll!RivhitApi.RivhitService.DoRequest(object objToSend, string Url) Line 59

Developer
  • 788
  • 6
  • 10

2 Answers2

1

According to the documentation, the Write method will throw an ArgumentNullException when the buffer is null. In your case that would mean that bJsonReq is null.

Make sure it isn't null before you call Write.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 'bJsonReq' is not null. by clicing the F10 key it works perfectly = it get the properly response from the server. in addition - it throws the exception at the "GetRequestStream()" part, before it try to use the bJsonReq at all – Developer May 15 '17 at 12:01
  • Is it empty maybe? – Patrick Hofman May 15 '17 at 12:02
  • @Developer is it being set by another thread, or by code running asynchronously? That could explain why it works in line-by-line debugging, but not when run normally. – Nick Mertin May 15 '17 at 12:06
  • @Nicholas Mertin internally, the sync GetRequestStream() method is using the async BeginGetRequestStream method. so it can couse an other thread to create the stream? what can i do about? – Developer May 15 '17 at 14:03
  • 1
    @Developer never mind, looking at the code in your screenshot that can't be the issue. I was referring to the possibility of bJsonReq being assigned by another thread entirely, not from a return value as it currently is. Please post a stack trace of the exception, that will help in finding a solution. – Nick Mertin May 15 '17 at 16:23
  • to @Patrick Hofman. first i thank you for the reference. I edited the question so it contains the updated code. I was added a new code to prove that the problem isn't being caused due to an real null object. any help is welcomed. – Developer May 15 '17 at 21:29
  • Let me check the .NET source code tomorrow. Maybe there is something useful in there. You mean to say the error is ignored right? It executes as normal after that. – Patrick Hofman May 15 '17 at 21:39
0

according to this microsoft document adding this lines of code solves the problem.

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

there is in that document some more options to set this defination.

but the cons are probably the decreasing of security. I'm looking for a smarter solution, maybe by setting the ServicePointManager somehow, In a manner that the SecurityProtocolType would not be null. For now I don't find such as.

Developer
  • 788
  • 6
  • 10