【问题标题】:Call Web API 2 method using c# CLR stored procedure by HTTPClient通过 HTTPClient 使用 c# CLR 存储过程调用 Web API 2 方法
【发布时间】:2017-06-14 08:53:49
【问题描述】:

我有一个 WPF 应用程序,它使用 MVC Web API 2 的服务。使用 HTTPClient 创建了 RestClient 包装器来调用 PostAsync 和 GetAsync 等异步方法。例如,我的 POST 方法包装器如下:

using (var client = new HttpClient(new HttpClientHandler()
                                       { AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip }))
{
    var content = new FormUrlEncodedContent(postObject);

    SetupClient(client, methodName, apiUrl, postObject, headerContent);

    if (apiKey != null && appId != null)
        await SetAuthorizationHeader(client, methodName, apiUrl, appId, apiKey, content).ConfigureAwait(false);

    using (HttpResponseMessage response = Task.Run(() => client.PostAsync(apiUrl, content)).Result)
    {
        response.EnsureSuccessStatusCode();

        using (HttpContent httpContent = response.Content)
        {
            if (response.IsSuccessStatusCode)
            {
                result = response.Content.ReadAsAsync<T>().Result;
            }
        }
    }
}

哪个工作正常。现在我正在尝试通过创建 SQL Server 数据库项目来通过 C# CLR 存储过程调用一些 API 调用。

C# CLR 存储过程会是这样的:

[Microsoft.SqlServer.Server.SqlProcedure]
public static void SQLRestClient(SqlString weburl, SqlString postBody, SqlString appIdString, SqlString apiKeyString, SecureString baseAddress, out SqlString returnval)
{
    string apiUrl = Convert.ToString(weburl);
    string baseAddressString = Convert.ToString(baseAddress);

    string result = string.Empty;
    var appId = ConvertToSecureString(Convert.ToString(appIdString));
    var apiKey = ConvertToSecureString(Convert.ToString(apiKeyString));

    try
    {
        string methodName = HttpMethod.Post.Method.ToUpper();

        using (var client = new HttpClient(new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
        }))
        {
            var content = new FormUrlEncodedContent(postObject);

            SetupClient(client, methodName, apiUrl, postObject, headerContent);

            if (apiKey != null && appId != null)
                await SetAuthorizationHeader(client, methodName, apiUrl, appId, apiKey, content).ConfigureAwait(false);

            using (HttpResponseMessage response = Task.Run(() => client.PostAsync(apiUrl, content)).Result)
            {
                response.EnsureSuccessStatusCode();

                using (HttpContent httpContent = response.Content)
                {
                    if (response.IsSuccessStatusCode)
                    {
                        result = response.Content.ReadAsStringAsync();
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        SqlContext.Pipe.Send(ex.Message.ToString());
    }

    returnval = result;
}

当我尝试生成此过程的 DLL 时,我遇到了构建错误。 这是因为编译器无法识别汇编引用,例如

System.Net.Http.dll

当我浏览这个帖子时

Sending HTTP POST request from SQL Server 2012 or SQL CLR C#

我找到了使用 HttpWebRequest 而不是 HttpClient 的解决方案。由于我在整个应用程序中一直使用 HttpClient,因此我不想切换到 HttpWebRequest。

任何人都可以建议任何其他方式,以便我可以使用 HttpClient 生成 CLR 存储过程 dll。任何帮助将不胜感激,并提前致谢。

【问题讨论】:

    标签: c# .net sql-server asp.net-web-api sqlclr


    【解决方案1】:

    不,HttpClientSystem.Net.Http 中找到,并且该库不是supported .NET Framework libraries 之一。您可以手动添加该库,但不应该因为它需要设置为 UNSAFE 并且需要将数据库设置为 TRUSTWORTHY ON,因为您没有 MS 签名证书。它也不能保证工作,因为 SQLCLR 只允许纯 MSIL 程序集;混合模式程序集将不会加载。当前纯 MSIL 的程序集可以更改为混合在 .NET Framework 更新中。如果您加载的不受支持的框架库发生这种情况,那么您的项目将停止工作,您必须重写它以不使用该库。

    您也不应该在 SQLCLR 中使用异步调用。这些还需要将程序集标记为UNSAFE,在这种环境中通常不是一个好主意。

    最好、最安全、最可靠的选择是使用HttpWebRequestHttpWebResponse

    【讨论】:

      【解决方案2】:

      默认情况下,SQL 服务器上只有一部分 .net 库可用,我认为这是 this page 列表。

      WebRequest 是 System.dll 加载的 System.Net 命名空间的一部分,这就是为什么您可以轻松地将其用作 CLR 的一部分,以及您查看的解决方案可能使用它的原因。

      您可以将其他程序集加载到 SQL 中以供 CLR 使用,如页面的“Unsupported Libraries”部分所述。所以我认为理论上你可以加载使用 HttpClient 所需的任何程序集,尽管如果你想使用扩展,你可能会发现有几个。

      例如HttpClient 是 System.Net.Http.dll 的一部分
      并且 .PostAsJsonAsync 是 System.Net.Http.Formatting.dll 的一部分

      程序集也有潜在的安全要求,最好是签名等,除非您在导入程序集时禁用这些检查。

      我之前确实看过这个问题,虽然我没有花太多时间尝试让 HttpClient 工作,但我最终还是使用了 WebRequest,因为不必担心在外部部署其他程序集要容易得多我正在创建的那个。

      --
      作为参考,如果链接断开,这些是第一个链接上列出的库:

      SQL Server 中的 CLR 集成支持的库/命名空间 是:

      • 自定义编组器
      • Microsoft.VisualBasic
      • Microsoft.VisualC
      • mscorlib
      • 系统
      • 系统配置
      • System.Data
      • System.Data.OracleClient
      • System.Data.SqlXml
      • System.Deployment
      • 系统安全
      • System.Transactions
      • System.Web.Services
      • System.Xml
      • System.Core.dll
      • System.Xml.Linq.dll

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多