【问题标题】:UPS rate request using .net web service使用 .net Web 服务的 UPS 费率请求
【发布时间】:2018-06-28 00:43:32
【问题描述】:

我有一个使用 .NET C# 的现有 Web 服务。我们的内部应用程序调用该服务,该服务使用 XML 连接到 UPS 以处理请求。它在几周前停止工作。我连接到 UPS,他们说要更新我所做的 URL。他们还提到他们看到很多 TLS 失败,但我们的 IIS 8 和 Windows Server 2012 都是最新的。我还运行了安全检查,SSL3 和 TLS 都被禁用了。

在我的开发系统上,我正在尝试测试更改。首先,我编写了一个连接到 UPS 服务器的小型控制台应用程序,它按预期工作。我将代码移至 Web 服务并运行相同的测试,但它失败了。我已经验证了 Web 服务和控制台代码运行的是相同版本的 .NET。

我已经比较了发送的数据,所以我确信两者都是有效的。错误发生在 shipRequest.GetRequestStream()。知道为什么它在 Web 服务上失败,但在控制台应用程序上却没有?

我刚刚添加了 ServerCertificateValidationCallback 部分,如果删除它并出现相同的错误,它将不起作用。

Rate_Tool_SampleRequest.xml 是从 UPS 开发站点下载的。

internal string UPSAccessKey;
internal string UPSPassword;
internal string UPSUserID;
internal string UPSAccount;
internal string Server = "https://onlinetools.ups.com/ups.app/xml/Rate";
// test file, to be removed.
private static string RateFile = @"D:\Projects\UPS-Tracking\samples\Rate_Tool_SampleRequest.xml";

internal string GetRates(UPS_RateEstimate request)
{
    try
    {
       // var data = this.AccessRequest + request.Data;

        // Read UPS test file and replace key filds
        var data = File.ReadAllText(RateFile)
            .Replace("Your_License", UPSAccessKey)
            .Replace("Your_ID", UPSPassword)
            .Replace("Your_Password", UPSUserID)
            .Replace("Ship Number", UPSAccount);

        var response = this.RequestData(data);
        return response;
    }
    catch (Exception exc)
    {
        System.Diagnostics.Debug.WriteLine(exc);
        return exc.ToString();
    }
}

private string RequestData(string request)
{
    HttpWebRequest shipRequest;
    try
    {
        // convert request to bytes
        ASCIIEncoding encoding = new ASCIIEncoding();
        byte[] data = encoding.GetBytes(request); // Request
        shipRequest = (HttpWebRequest)WebRequest.Create(Server);
        shipRequest.Method = "POST";
        shipRequest.ContentType = "application/x-www-form-urlencoded";
        shipRequest.ContentLength = data.Length;
        shipRequest.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return true; };
        using (var requestStream = shipRequest.GetRequestStream())
        {
            // Send the data
            requestStream.Write(data, 0, data.Length);
            requestStream.Close();
            using (var response = shipRequest.GetResponse())
            {
                using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                {
                    var result = sr.ReadToEnd();
                    File.WriteAllText(RateTestResultFile, result);
                    return result;
                }
            }
        }
    }
    finally
    {
        shipRequest = null;
    }
}

System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. 
    ---> System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.TlsStream.CallProcessAuthentication(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   at UPSHelper.RequestData(String request) in \App_Code\UPS\UPSHelper.cs:line 99
   at UPSHelper.GetRates(UPS_RateEstimate request) in \App_Code\UPS\UPSHelper.cs:line 34

【问题讨论】:

  • 谷歌如何使用这个:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
  • 非常感谢@Crowcoder,Tls12 和 Tls11 一样好用。注意.net平台必须设置为4.5或以上。
  • 这也适用于我。感谢 Crowcoder 和 John Hughes!

标签: c# asp.net .net web-services ups


【解决方案1】:

我认为你错过了这一行:

这是一个完整的代码示例:

        string Testing = "https://wwwcie.ups.com/rest/Rate";
        string Production = "https://onlinetools.ups.com/rest/Rate";
        string json = Newtonsoft.Json.JsonConvert.SerializeObject(upsRate);
        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11; //This line will ensure the latest security protocol for consuming the web service call.
        WebRequest httpWebRequest = WebRequest.Create(Production);
        httpWebRequest.ContentType = "application/json";
        httpWebRequest.Method = "POST";

        using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            streamWriter.Write(json);
            streamWriter.Flush();
            streamWriter.Close();
        }

        HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        string returnResult = "";
        using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            returnResult = streamReader.ReadToEnd();
        }
        if (string.IsNullOrEmpty(returnResult))
        {
            return NotFound();
        }

        return Ok(returnResult);

注意:我正在序列化一个 UPSRate 对象,而您正在从一个看起来像的文件中读取属性。

【讨论】:

    猜你喜欢
    • 2015-09-14
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 2018-03-15
    相关资源
    最近更新 更多