通过 HTTPClient 使用 c# CLR 存储过程调用 Web API 2 方法
Call Web API 2 method using c# CLR stored procedure by HTTPClient
我有一个使用 MVC web 服务的 WPF 应用程序 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 服务器数据库项目来通过 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
当我浏览这个线程时
我找到了使用 HttpWebRequest 而不是 HttpClient 的解决方案。由于我在整个应用程序中一直使用 HttpClient,因此我不想切换到 HttpWebRequest。
任何人都可以建议任何其他方式,以便我可以使用 HttpClient 生成 CLR 存储过程 dll。任何帮助将不胜感激,并提前致谢。
默认情况下,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,因为不必担心部署其他程序集要容易得多在我创建的那个之外。
--
作为参考,如果 link 中断,这些是第一个 link 中列出的库:
The libraries/namespaces supported by CLR integration in SQL Server
are:
- CustomMarshalers
- Microsoft.VisualBasic
- Microsoft.VisualC
- mscorlib
- System
- System.Configuration
- System.Data
- System.Data.OracleClient
- System.Data.SqlXml
- System.Deployment
- System.Security
- System.Transactions
- System.Web.Services
- System.Xml
- System.Core.dll
- System.Xml.Linq.dll
不,HttpClient
在 System.Net.Http
中找到,并且该库不是 supported .NET Framework libraries 之一。您可以手动添加该库,但您不应该这样做,因为它需要设置为 UNSAFE
,并且需要将数据库设置为 TRUSTWORTHY ON
,因为您没有 MS 签名证书。它也不能保证工作,因为 SQLCLR 只允许纯 MSIL 程序集;混合模式程序集将不会加载。当前纯 MSIL 的程序集可以在 .NET Framework 更新中更改为混合。如果您加载的不受支持的框架库发生这种情况,那么您的项目将停止工作,您必须重写它才能不使用该库。
您也不应该在 SQLCLR 中使用异步调用。这些还要求将程序集标记为 UNSAFE
,在这种环境下通常不是一个好主意。
最好、最安全、最可靠的选择是使用 HttpWebRequest
和 HttpWebResponse
。
我有一个使用 MVC web 服务的 WPF 应用程序 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 服务器数据库项目来通过 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
当我浏览这个线程时
我找到了使用 HttpWebRequest 而不是 HttpClient 的解决方案。由于我在整个应用程序中一直使用 HttpClient,因此我不想切换到 HttpWebRequest。
任何人都可以建议任何其他方式,以便我可以使用 HttpClient 生成 CLR 存储过程 dll。任何帮助将不胜感激,并提前致谢。
默认情况下,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,因为不必担心部署其他程序集要容易得多在我创建的那个之外。
--
作为参考,如果 link 中断,这些是第一个 link 中列出的库:
The libraries/namespaces supported by CLR integration in SQL Server are:
- CustomMarshalers
- Microsoft.VisualBasic
- Microsoft.VisualC
- mscorlib
- System
- System.Configuration
- System.Data
- System.Data.OracleClient
- System.Data.SqlXml
- System.Deployment
- System.Security
- System.Transactions
- System.Web.Services
- System.Xml
- System.Core.dll
- System.Xml.Linq.dll
不,HttpClient
在 System.Net.Http
中找到,并且该库不是 supported .NET Framework libraries 之一。您可以手动添加该库,但您不应该这样做,因为它需要设置为 UNSAFE
,并且需要将数据库设置为 TRUSTWORTHY ON
,因为您没有 MS 签名证书。它也不能保证工作,因为 SQLCLR 只允许纯 MSIL 程序集;混合模式程序集将不会加载。当前纯 MSIL 的程序集可以在 .NET Framework 更新中更改为混合。如果您加载的不受支持的框架库发生这种情况,那么您的项目将停止工作,您必须重写它才能不使用该库。
您也不应该在 SQLCLR 中使用异步调用。这些还要求将程序集标记为 UNSAFE
,在这种环境下通常不是一个好主意。
最好、最安全、最可靠的选择是使用 HttpWebRequest
和 HttpWebResponse
。