C#Swagger生成的客户端如何验证和使用自动生成的代码

时间:2020-11-07 12:05:09

标签: c# .net rest swagger nswag

我已经使用nSwag Studio从Swagger Definition(Openapi 3.0.3)成功地生成了类,但是我不知道如何正确地将其用作客户端。

手动使用RestSharp代码可以正常工作,但是我想使用自动生成的代码来使用Web服务方法并且无法正确完成

这工作正常:

string clientId = "dev";
string clientSecret = @"pass";

var client = new RestClient("http://192.168.1.10/xyz/api/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("grant_type", "client_credentials");

var credentials = string.Format("{0}:{1}", clientId, clientSecret);
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
request.AddHeader("Authorization", $"Basic {headerValue}");
request.AddParameter($"application/x-www-form-urlencoded", $"grant_type=client_credentials&client_id={clientId}&client_secret{clientSecret}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request, Method.POST);

我尝试使用自动生成的代码。我错误地举报,但找不到任何例子。 例子很少,但看起来客户端是通过不同的方式生成的(使用基本url初始化客户端-但在这种情况下仍不了解基本授权) Googling大多返回“如何创建服务器端”或向asp / mvc / webapi项目添加招摇。

        string URL = @"http://192.168.1.10/xyz/api";
        string clientId = "dev";
        string clientSecret = @"pass";

        IO.Swagger.Client.ApiClient client = new IO.Swagger.Client.ApiClient(URL);
        IO.Swagger.Client.Configuration.DefaultApiClient = client; //<<this throws error
        IO.Swagger.Client.Configuration.Username = clientId;
        IO.Swagger.Client.Configuration.Password = clientSecret;
        client.AddDefaultHeader("Authorization", "bearer TOKEN");

        IO.Swagger.Api.AuthApi authApi = new IO.Swagger.Api.AuthApi(client);

ApiClient类错误

public ApiClient(String basePath="/xyz/api")
{
BasePath = basePath;
RestClient = new RestClient(BasePath); //System.UriFormatException: 'Invalid URI: The format of the URI could not be determined.'
}

我尝试了许多字符串形式的url(类未明确接受Uri)

配置

using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace IO.Swagger.Client
{
    public class Configuration
    {
        public const string Version = "1.0.0";
        public static ApiClient DefaultApiClient = new ApiClient();
        public static String Username { get; set; }
        public static String Password { get; set; }
        public static Dictionary<String, String> ApiKey = new Dictionary<String, String>();
        public static Dictionary<String, String> ApiKeyPrefix = new Dictionary<String, String>();
        private static string _tempFolderPath = Path.GetTempPath();
        public static String TempFolderPath
        {
            get { return _tempFolderPath; }
  
            set 
            {
                if (String.IsNullOrEmpty(value))
                {
                    _tempFolderPath = value;
                    return;
                }
      
                // create the directory if it does not exist
                if (!Directory.Exists(value)) 
                    Directory.CreateDirectory(value);
      
                // check if the path contains directory separator at the end
                if (value[value.Length - 1] == Path.DirectorySeparatorChar)
                    _tempFolderPath = value;
                else
                    _tempFolderPath = value  + Path.DirectorySeparatorChar;
            }
        }

        private const string ISO8601_DATETIME_FORMAT = "o";
        private static string _dateTimeFormat = ISO8601_DATETIME_FORMAT;

        public static String DateTimeFormat
        {
            get
            {
                return _dateTimeFormat;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    // Never allow a blank or null string, go back to the default
                    _dateTimeFormat = ISO8601_DATETIME_FORMAT;
                    return;
                }

                // Caution, no validation when you choose date time format other than ISO 8601
                // Take a look at the above links
                _dateTimeFormat = value;
            }
        }

        public static String ToDebugReport()
        {
            String report = "C# SDK (IO.Swagger) Debug Report:\n";
            report += "    OS: " + Environment.OSVersion + "\n";
            report += "    .NET Framework Version: " + Assembly
                     .GetExecutingAssembly()
                     .GetReferencedAssemblies()
                     .Where(x => x.Name == "System.Core").First().Version.ToString()  + "\n";
            report += "    Version of the API: 2.0.1\n";
            report += "    SDK Package Version: 1.0.0\n";
  
            return report;
        }
    }
}

客户

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
using System.Linq;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Extensions;

namespace IO.Swagger.Client
{
    public class ApiClient
    {
        private readonly Dictionary<String, String> _defaultHeaderMap = new Dictionary<String, String>();
  
        public ApiClient(String basePath="/xyz/api")
        {
            BasePath = basePath;
            RestClient = new RestClient(BasePath);
        }
    
        public string BasePath { get; set; }
        public RestClient RestClient { get; set; }
        public Dictionary<String, String> DefaultHeader
        {
            get { return _defaultHeaderMap; }
        }
        public Object CallApi(String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
            Dictionary<String, String> headerParams, Dictionary<String, String> formParams, 
            Dictionary<String, FileParameter> fileParams, String[] authSettings)
        {

            var request = new RestRequest(path, method);
   
            UpdateParamsForAuth(queryParams, headerParams, authSettings);

            // add default header, if any
            foreach(var defaultHeader in _defaultHeaderMap)
                request.AddHeader(defaultHeader.Key, defaultHeader.Value);

            // add header parameter, if any
            foreach(var param in headerParams)
                request.AddHeader(param.Key, param.Value);

            // add query parameter, if any
            foreach(var param in queryParams)
                request.AddParameter(param.Key, param.Value, ParameterType.GetOrPost);

            // add form parameter, if any
            foreach(var param in formParams)
                request.AddParameter(param.Key, param.Value, ParameterType.GetOrPost);

            // add file parameter, if any
            foreach(var param in fileParams)
                request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);

            if (postBody != null) // http body (model) parameter
                request.AddParameter("application/json", postBody, ParameterType.RequestBody);

            return (Object)RestClient.Execute(request);

        }
    
        public void AddDefaultHeader(string key, string value)
        {
            _defaultHeaderMap.Add(key, value);
        }
    
        public string EscapeString(string str)
        {
            return RestSharp.Contrib.HttpUtility.UrlEncode(str);
        }
    
        public FileParameter ParameterToFile(string name, Stream stream)
        {
            if (stream is FileStream)
                return FileParameter.Create(name, stream.ReadAsBytes(), Path.GetFileName(((FileStream)stream).Name));
            else
                return FileParameter.Create(name, stream.ReadAsBytes(), "no_file_name_provided");
        }
    
        public string ParameterToString(object obj)
        {
            if (obj is DateTime)
                // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
                // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
                // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
                // For example: 2009-06-15T13:45:30.0000000
                return ((DateTime)obj).ToString (Configuration.DateTimeFormat);
            else if (obj is List<string>)
                return String.Join(",", (obj as List<string>).ToArray());
            else
                return Convert.ToString (obj);
        }
    
        public object Deserialize(string content, Type type, IList<Parameter> headers=null)
        {
            if (type == typeof(Object)) // return an object
            {
                return content;
            }

            if (type == typeof(Stream))
            {
                var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath)
                    ? Path.GetTempPath()
                    : Configuration.TempFolderPath;

                var fileName = filePath + Guid.NewGuid();
                if (headers != null)
                {
                    var regex = new Regex(@"Content-Disposition:.*filename=['""]?([^'""\s]+)['""]?$");
                    var match = regex.Match(headers.ToString());
                    if (match.Success)
                        fileName = filePath + match.Value.Replace("\"", "").Replace("'", "");
                }
                File.WriteAllText(fileName, content);
                return new FileStream(fileName, FileMode.Open);

            }

            if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object
            {
                return DateTime.Parse(content,  null, System.Globalization.DateTimeStyles.RoundtripKind);
            }

            if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type
            {
                return ConvertType(content, type); 
            }
    
            // at this point, it must be a model (json)
            try
            {
                return JsonConvert.DeserializeObject(content, type);
            }
            catch (IOException e)
            {
                throw new ApiException(500, e.Message);
            }
        }
    
        public string Serialize(object obj)
        {
            try
            {
                return obj != null ? JsonConvert.SerializeObject(obj) : null;
            }
            catch (Exception e)
            {
                throw new ApiException(500, e.Message);
            }
        }
    
        public string GetApiKeyWithPrefix (string apiKeyIdentifier)
        {
            var apiKeyValue = "";
            Configuration.ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue);
            var apiKeyPrefix = "";
            if (Configuration.ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix))
                return apiKeyPrefix + " " + apiKeyValue;
            else
                return apiKeyValue;
        }
    
        public void UpdateParamsForAuth(Dictionary<String, String> queryParams, Dictionary<String, String> headerParams, string[] authSettings)
        {
            if (authSettings == null || authSettings.Length == 0)
                return;

            foreach (string auth in authSettings)
            {
                // determine which one to use
                switch(auth)
                {
                    case "BasicAuth":
                        headerParams["Authorization"] = "Basic " + Base64Encode(Configuration.Username + ":" + Configuration.Password);
                        
                        break;
                    case "BearerAuth":
                        
                        
                        break;
                    default:
                        //TODO show warning about security definition not found
                        break;
                }
            }
        }
 
        public static string Base64Encode(string text)
        {
            var textByte = System.Text.Encoding.UTF8.GetBytes(text);
            return System.Convert.ToBase64String(textByte);
        }
    
        public static Object ConvertType(Object fromObject, Type toObject) {
            return Convert.ChangeType(fromObject, toObject);
        }
    }
}

AuthApi

using System;
using System.Collections.Generic;
using RestSharp;
using IO.Swagger.Client;
using IO.Swagger.Model;

namespace IO.Swagger.Api
{
    public interface IAuthApi
    {
        InlineResponse200 OauthTokenPost (string grantType);
    }
  
    public class AuthApi : IAuthApi
    {
        public AuthApi(ApiClient apiClient = null)
        {
            if (apiClient == null) // use the default one in Configuration
                this.ApiClient = Configuration.DefaultApiClient; 
            else
                this.ApiClient = apiClient;
        }
    
        public AuthApi(String basePath)
        {
            this.ApiClient = new ApiClient(basePath);
        }
    
        public void SetBasePath(String basePath)
        {
            this.ApiClient.BasePath = basePath;
        }
    
        public String GetBasePath(String basePath)
        {
            return this.ApiClient.BasePath;
        }
    
        public ApiClient ApiClient {get; set;}
    
        public InlineResponse200 OauthTokenPost (string grantType)
        {
    
            var path = "/oauth/token";
            path = path.Replace("{format}", "json");
                
            var queryParams = new Dictionary<String, String>();
            var headerParams = new Dictionary<String, String>();
            var formParams = new Dictionary<String, String>();
            var fileParams = new Dictionary<String, FileParameter>();
            String postBody = null;
    
            if (grantType != null) formParams.Add("grant_type", ApiClient.ParameterToString(grantType)); // form parameter
                
            // authentication setting, if any
            String[] authSettings = new String[] { "BasicAuth" };
    
            // make the HTTP request
            IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
    
            if (((int)response.StatusCode) >= 400)
                throw new ApiException ((int)response.StatusCode, "Error calling OauthTokenPost: " + response.Content, response.Content);
            else if (((int)response.StatusCode) == 0)
                throw new ApiException ((int)response.StatusCode, "Error calling OauthTokenPost: " + response.ErrorMessage, response.ErrorMessage);
    
            return (InlineResponse200) ApiClient.Deserialize(response.Content, typeof(InlineResponse200), response.Headers);
        }
    
    }
}

1 个答案:

答案 0 :(得分:0)

给我的印象是,您的主要问题是Uri格式。我建议这样做可以找到确切的问题

    string URL = @"http://192.168.1.10/xyz/api";
    Uri baseAddress = new Uri(URL);
    string clientId = "dev";
    string clientSecret = @"pass";

    IO.Swagger.Client.ApiClient client = new IO.Swagger.Client.ApiClient(baseAddress.ToString());
    IO.Swagger.Client.Configuration.DefaultApiClient = client; //<<this throws error
    IO.Swagger.Client.Configuration.Username = clientId;
    IO.Swagger.Client.Configuration.Password = clientSecret;
    client.AddDefaultHeader("Authorization", "bearer TOKEN");

    IO.Swagger.Api.AuthApi authApi = new IO.Swagger.Api.AuthApi(client);
相关问题