Reputation: 2057
I'm consuming the following API, that responde either with a Data
object of an Error
object
FooBar Method: Ids is a list of string separated by commas
GET: /FooBar/v1{?ids}
GET: /FooBar/v1/{ids}
Request Header:
X-FooBar-Key: ## My key ##
Response : 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": ""
}
Response : 400/404/etc , Return the content of an Error object
{
"code": "",
"message": ""
}
I want to be able to check [1, N] IDs and with only one object return type Response
with either Data or Error initialised the other at 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; }
}
In order to simply the problem For now I work only on 1 Id at a time.
Using ServiceStack Client to consume the 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();
}
}
This question is not tagged with ServiceStack as I'm open to solution using : HttpWebRequest/Response Class, WebClient Class, HttpClient Class, RestSharp NuGet Package, ServiceStack Http Utils, Or Anything that make my life easier.
I am using ServiceStack because of documentation saying that I could use something like :
client.GetAsync(new Hello { Name = "World!" })
.Success(r => r => r.Result.Print())
.Error(ex => { throw ex; });
Using Success
and Error
to map single return type to my Response
type.
Upvotes: 3
Views: 3593
Reputation: 143284
ServiceStack C#/.NET Service Clients supports both Sync and Async APIs, since your method is synchronous you should only be using the synchronous APIs, e.g:
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;
}
}
You should only use the async APIs if your method is also async, e.g:
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;
}
}
Upvotes: 1
Reputation: 2355
If you are using ServiceStack, then you should use it the way you found in the doc, but this would mean that you actually throw (a custom) exception when ever the id does not exist. Your custom exception would then include the code and message. So you would actually just throw an exception when ever you want to return an error.
However, I don't think that is what you should do, because exceptions should only be used if an exceptional case happens, but as far as I understand, errors is a common and normal behavior that happens often (like the client does try and error with ids). Therefore, I recommend using HttpWebResponse Class as your return type. There you can basically set the HTTP return state (e.g. 400, 404) and json (or actually any) data.
Upvotes: 1