M
Martin Nikolaev
Guest
Hello, I am trying to develop some code with generics, the idea is following:
We have plenty of API tests and each one of them requires some very long and complicated call, since they are hard to memorize I was thinking of a way to do that with classes. You create two classes with Request and Response and fill up the needed properties and serialize that into XML, JSON or FORM and get the results populated in the Response class.
To make this happen I have two abstract classes - RESTfulRequest and RESTfulResponse.
These two classes are to be inherited by any class that is going to be used for RESTful call.
public abstract class RESTFulRequest
{
#region Public Fields
public string Url { get; set; }
public ContentType ContentType { get; set; }
public List<KeyValue> CustomHeaders { get; set; }
#endregion
#region Public Constuctors
public RESTFulRequest()
{
this.CustomHeaders = new List<KeyValue>();
}
#endregion
}
public class RESTFulResponseInternal
{
#region Public Constructors
/// <summary>
/// Initializes the class with the specified status code and content.
/// </summary>
/// <param name="statusCode">The http status code.</param>
/// <param name="isSuccessStatusCode">A boolean value indicating if the http response was successful.</param>
/// <param name="content">The http response content.</param>
public RESTFulResponseInternal (HttpStatusCode statusCode, bool isSuccessStatusCode, string content)
{
StatusCode = statusCode;
IsSuccessStatusCode = isSuccessStatusCode;
Content = content;
}
#endregion
#region Public Properties
/// <summary>
/// Gets http status code.
/// </summary>
public HttpStatusCode StatusCode { get; private set; }
/// <summary>
/// Gets a value indicating if the http response was successful.
/// </summary>
public bool IsSuccessStatusCode { get; private set; }
/// <summary>
/// Gets the http response content.
/// </summary>
public string Content { get; private set; }
#endregion
}
Next I have an extension method for every class that inherits the Request class
public static TResult POST<TResult>(this RESTFulRequest obj, string accessToken = "")
where TResult : RESTFulResponse, new()
{
if (obj == null) return default(TResult);
var url = obj.Url;
var content = ContentProvider.GetContent(obj);
var contentType = obj.ContentType.GetDisplayName();
var headers = HeaderProvider.GetHeaders(accessToken, obj.CustomHeaders.ToArray());
var result = RESTFul.PostInternal(obj.Url, content, contentType, headers);
return RESTFul.ResponseProcessor<TResult>(result);
}
and after I get the response I have this method to populate the Reponse method
private static TResult ResponseProcessor<TResult>(RESTFulResponseInternal result)
where TResult : RESTFulResponse
{
if (result.IsSuccessStatusCode)
{
var response = ContentProvider.Deserialize<TResult>(result.Content);
response.Response = result;
response.Map();
return response;
}
else
{
throw new InvalidOperationException($"RESTful Exception: {result.StatusCode}\nError: {result.Content}");
}
}
Everything works great! To the point where the response is just a list (like this one: https://jsonplaceholder.typicode.com/posts) it will fail with the following response class:
public class TypiCodePostResponse : RESTFulResponse
{
public Post[] Posts { get; set; }
public class Post
{
public int userId { get; set; }
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
}
}
The goal here is to have a Response class which contains the list of the posts.
I need a class with a List/Array of Posts inside. I dont want to make Posts Inheriting the RESTfulResponse class, because then all the posts will have the same big response.
The question here is how to achieve serialization of that response (https://jsonplaceholder.typicode.com/posts) into the TypiCodePostResponse so I dont loose my response, logic and the flow i am going with.
Thanks in advance,
Martin
Continue reading...
We have plenty of API tests and each one of them requires some very long and complicated call, since they are hard to memorize I was thinking of a way to do that with classes. You create two classes with Request and Response and fill up the needed properties and serialize that into XML, JSON or FORM and get the results populated in the Response class.
To make this happen I have two abstract classes - RESTfulRequest and RESTfulResponse.
These two classes are to be inherited by any class that is going to be used for RESTful call.
public abstract class RESTFulRequest
{
#region Public Fields
public string Url { get; set; }
public ContentType ContentType { get; set; }
public List<KeyValue> CustomHeaders { get; set; }
#endregion
#region Public Constuctors
public RESTFulRequest()
{
this.CustomHeaders = new List<KeyValue>();
}
#endregion
}
public class RESTFulResponseInternal
{
#region Public Constructors
/// <summary>
/// Initializes the class with the specified status code and content.
/// </summary>
/// <param name="statusCode">The http status code.</param>
/// <param name="isSuccessStatusCode">A boolean value indicating if the http response was successful.</param>
/// <param name="content">The http response content.</param>
public RESTFulResponseInternal (HttpStatusCode statusCode, bool isSuccessStatusCode, string content)
{
StatusCode = statusCode;
IsSuccessStatusCode = isSuccessStatusCode;
Content = content;
}
#endregion
#region Public Properties
/// <summary>
/// Gets http status code.
/// </summary>
public HttpStatusCode StatusCode { get; private set; }
/// <summary>
/// Gets a value indicating if the http response was successful.
/// </summary>
public bool IsSuccessStatusCode { get; private set; }
/// <summary>
/// Gets the http response content.
/// </summary>
public string Content { get; private set; }
#endregion
}
Next I have an extension method for every class that inherits the Request class
public static TResult POST<TResult>(this RESTFulRequest obj, string accessToken = "")
where TResult : RESTFulResponse, new()
{
if (obj == null) return default(TResult);
var url = obj.Url;
var content = ContentProvider.GetContent(obj);
var contentType = obj.ContentType.GetDisplayName();
var headers = HeaderProvider.GetHeaders(accessToken, obj.CustomHeaders.ToArray());
var result = RESTFul.PostInternal(obj.Url, content, contentType, headers);
return RESTFul.ResponseProcessor<TResult>(result);
}
and after I get the response I have this method to populate the Reponse method
private static TResult ResponseProcessor<TResult>(RESTFulResponseInternal result)
where TResult : RESTFulResponse
{
if (result.IsSuccessStatusCode)
{
var response = ContentProvider.Deserialize<TResult>(result.Content);
response.Response = result;
response.Map();
return response;
}
else
{
throw new InvalidOperationException($"RESTful Exception: {result.StatusCode}\nError: {result.Content}");
}
}
Everything works great! To the point where the response is just a list (like this one: https://jsonplaceholder.typicode.com/posts) it will fail with the following response class:
public class TypiCodePostResponse : RESTFulResponse
{
public Post[] Posts { get; set; }
public class Post
{
public int userId { get; set; }
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
}
}
The goal here is to have a Response class which contains the list of the posts.
I need a class with a List/Array of Posts inside. I dont want to make Posts Inheriting the RESTfulResponse class, because then all the posts will have the same big response.
The question here is how to achieve serialization of that response (https://jsonplaceholder.typicode.com/posts) into the TypiCodePostResponse so I dont loose my response, logic and the flow i am going with.
Thanks in advance,
Martin
Continue reading...