2017-06-14 5 views
2

J'ai une application WPF qui consomme les services de l'API Web MVC 2. Créer un wrapper RestClient en utilisant HTTPClient pour appeler des méthodes asynchrones telles que PostAsync et GetAsync. Par exemple mon wrapper de méthode POST serait comme:Appel de la méthode Web API 2 à l'aide de la procédure stockée C# CLR par HTTPClient

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

Qui fonctionne bien. En ce moment j'essaye d'appeler certains des appels d'API par la procédure stockée de C# CLR en créant le projet de base de données de SQL Server.

procédure C# CLR stocké sera comme:

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

Lorsque je tente de générer la DLL de cette procédure que je reçois construire erreur. Son parce que le compilateur ne reconnaît pas les références de l'Assemblée, comme

System.Net.Http.dll

Comme je l'ai passé par ce fil

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

J'ai trouvé une solution utiliser HttpWebRequest au lieu de HttpClient. Depuis que j'utilise HttpClient dans mon application, je ne veux pas passer à HttpWebRequest.

Quelqu'un peut-il suggérer d'une autre manière afin que je puisse générer la procédure stockée CLR dll en utilisant HttpClient. Toute aide sera appréciée et merci d'avance.

Répondre

2

Non, HttpClient se trouve dans System.Net.Http, et que la bibliothèque est pas l'un des supported .NET Framework libraries. Vous pouvez ajouter cette bibliothèque manuellement, mais vous ne devriez pas l'avoir car elle doit être définie sur UNSAFE et cela nécessitera de définir la base de données sur TRUSTWORTHY ON puisque vous n'avez pas le certificat de signature MS. Il n'est pas non plus garanti de fonctionner car SQLCLR n'autorise que des assemblages MSIL purs; Les assemblages en mode mixte ne seront pas chargés. Et les assemblys qui sont actuellement MSIL pur peuvent être modifiés dans une mise à jour .NET Framework. Si cela se produit pour une bibliothèque d'infrastructure non prise en charge que vous avez chargée, votre projet cesse de fonctionner et vous devez le réécrire pour ne pas utiliser cette bibliothèque.

Vous ne devriez également pas utiliser d'appels asynchrones dans SQLCLR. Ceux-ci exigent également que l'assemblage soit marqué comme UNSAFE et ne sont pas une bonne idée en général dans cet environnement.

L'option la meilleure, la plus sûre et la plus fiable consiste à utiliser HttpWebRequest et HttpWebResponse.

2

Seul un sous-ensemble des bibliothèques .net est disponible par défaut sur le serveur SQL, ce que je pense des listes this page.

WebRequest fait partie de l'espace de noms System.Net chargé par System.dll, ce qui est la raison pour laquelle vous pouvez l'utiliser facilement dans le cadre d'un CLR, et pourquoi la solution que vous regardiez utilise probablement.

Vous pouvez charger des assemblages supplémentaires dans SQL pour une utilisation par CLR comme décrit dans la section "Unsupported Libraries" de la page. Donc, je pense qu'en théorie vous pouvez charger les assemblages nécessaires pour utiliser HttpClient, bien que vous puissiez trouver qu'il y en a plusieurs si vous voulez utiliser les extensions.

par exemple. HttpClient fait partie de System.Net.Http.dll
et .PostAsJsonAsync fait partie de System.Net.Http.Formatting.dll

Il y a aussi des exigences de sécurité potentielles pour les assemblages, qu'idéalement ils sont signés, etc., à moins que vous désactivez ces contrôles lorsque vous importez les assemblys. Je me suis amusé à regarder cela avant, et même si je n'ai pas passé trop de temps à essayer de faire fonctionner HttpClient, j'ai fini par utiliser WebRequest parce qu'il était plus facile de ne pas avoir à se soucier du déploiement d'autres assemblages de celui que je créais.

-
Pour référence, en cas de rupture de lien, ce sont les bibliothèques inscrites sur le premier lien:

Les bibliothèques/espaces de noms pris en charge par l'intégration du CLR dans SQL Server sont:

  • CustomMarshalers
  • Microsoft.VisualBasic
  • Microsoft.VisualC
  • mscorlib
  • Système
  • 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