Многократный тип возврата из API - PullRequest
2 голосов
/ 21 марта 2019

Ввод и определение API:

Я использую следующий API, который отвечает либо Data объектом Error объекта

Метод FooBar: Ids - это список строк, разделенных запятыми

GET: /FooBar/v1{?ids}
GET: /FooBar/v1/{ids}

Заголовок запроса:

X-FooBar-Key:   ## My key ##

Ответ: 200

// if there is multiple IDs, response is an array of Data and Error
[{
  "data": { }
}, {
  "data": { }
}, {
  "error": { }
}]

//If there is only one ID, response is the content of the data object
{
    "code":     "",
    "date":     "",
    "status":   "",
    "message":  "",
    "link":     "",
    "type":     ""
}

Ответ: 400/404 / и т. Д. Возврат содержимого объекта Error

{
    "code":     "",
    "message":  ""
}

Вывод и ожидаемые результаты:

Я хочу иметь возможность проверить [1, N] ID и только с одним типом возвращаемого объекта Response, когда Data или Error инициализируют другой в null ...

public class Response
{
    [JsonProperty("data")]
    public Data Data { get; set; }

    [JsonProperty("error")]
    public Error Error { get; set; }

    public string Id{  get; set; }
} 
public class Error
{
    [JsonProperty("message")]
    public string Message { get; set; }

    [JsonProperty("code")]
    [JsonConverter(typeof(StringEnumConverter))]
    public ErrorCode Code { get; set; }
}    
public class Data
{
    [JsonProperty("status")]
    [JsonConverter(typeof(StringEnumConverter))]
    public Status Status { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }

    [JsonProperty("date")]
    public string Date { get; set; }

    [JsonProperty("message")]
    public string Message { get; set; }

    [JsonProperty("link")]
    public string Link { get; set; }
}

Попытка:

Чтобы просто решить проблему, пока я работаю только на 1 Id одновременно.
Использование ServiceStack Client для использования REST API.

public class FooBarAPI : IFooBarAPI
{
    Dictionary<string, string> DefaultHeader;
    string BasePath; // https://foofoo.bar/FooBar/v1
    public FooBarAPI(Dictionary<string, string> defaultHeader, string basePath)
    {
        DefaultHeader = defaultHeader;
        BasePath = basePath;
    }

    public Response GetFooBar(string id)
    {
        JsonServiceClient client = new JsonServiceClient(BasePath);
        client.RequestFilter = httpReq => httpReq.Headers.Add("X-FooBar-Key", DefaultHeader["X-FooBar-Key"]);

        var response = 
                client.GetAsync<Response>($"/{id}");    // Null as for one ID the result is type Data not Response
                // client.GetAsync<Data>($"/{id}");     // Working If not Error  

        var toto = response.Result;
        toto.Id = id;

        return toto;
    }

    public Response[] GetFooBar(string[] ids)
    {   // 
        throw new NotImplementedException();
    }
}

Этот вопрос не помечен ServiceStack, так как я открыт для решения с использованием: HttpWebRequest / класс ответа, Класс WebClient, Класс HttpClient, Пакет RestSharp NuGet, ServiceStack Http Utils, или Все, что делает мою жизнь проще.

Я использую ServiceStack, поскольку документация говорит, что я могу использовать что-то вроде:

client.GetAsync(new Hello { Name = "World!" })
    .Success(r => r => r.Result.Print())
    .Error(ex => { throw ex; });

Использование Success и Error для сопоставления одного возвращаемого типа с моим Response типом.

Ответы [ 2 ]

1 голос
/ 21 марта 2019

ServiceStack C # /. NET Service Clients поддерживает API-интерфейсы Sync и Async, поскольку ваш метод является синхронным, вы должны использовать только синхронные API, например:

public Response GetFooBar(string id)
{
    var client = new JsonServiceClient(BasePath) { 
        RequestFilter = req => req.Headers.Add(
            "X-FooBar-Key", DefaultHeader["X-FooBar-Key"])
    }

    try 
    {
        var response = client.Get<Response>($"/{id}");
        response.Id = id; // Why isn't this already in the response?
        return response;
    }
    catch (WebServiceException ex)
    {
        //Error Details
        //ex.StatusCode;
        //ex.ErrorCode;
        //ex.ErrorMessage;
    }
}

Вы должны только использовать асинхронные API, если ваш метод также асинхронный, например:

public async Task<Response> GetFooBar(string id)
{
    var client = new JsonServiceClient(BasePath) { 
        RequestFilter = req => req.Headers.Add(
            "X-FooBar-Key", DefaultHeader["X-FooBar-Key"])
    }

    try 
    {
        var response = await client.GetAsync<Response>($"/{id}");
        response.Id = id; // Why isn't this already in the response?
        return response;
    }
    catch (WebServiceException ex)
    {
        //Error Details
        //ex.StatusCode;
        //ex.ErrorCode;
        //ex.ErrorMessage;
    }
}
1 голос
/ 21 марта 2019

Если вы используете ServiceStack, то вы должны использовать его так, как вы нашли в документе, но это будет означать, что вы фактически создаете (пользовательское) исключение, когда идентификатор не существует.Ваше пользовательское исключение будет включать код и сообщение.Таким образом, вы на самом деле просто выбросите исключение, когда захотите вернуть ошибку.

Однако я не думаю, что это то, что вам следует делать, потому что исключения должны использоваться только в случае исключительного случая, но, насколько я понимаю, ошибки - это обычное и нормальное поведение, которое часто случается (как клиент пытается и ошибка с идентификаторами).Поэтому я рекомендую использовать класс HttpWebResponse в качестве типа возврата.Там вы можете установить состояние возврата HTTP (например, 400, 404) и данные json (или вообще любые данные).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...