我有一个函数可以对接受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行
答案 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 不为空。现在我找不到这样的。