Converting the content of HttpResponseMessage to object - c#

My Question: How do I do this?
So, I hadn't touched anything .Net in about 6 years until this week. There's a lot that I've forgotten and even more that I never knew and while I love the idea of the async/await keywords, I'm having a slight problem implementing the following requirements for a client's API implementation:
The ServerAPI class has a method for each of the API methods, taking appropriate input parameters (e.g. the method Login takes in an id and a password, makes the API call and returns the result to the caller).
I want to abstract away the JSON so that my API methods return the actual object you're fetching (e.g. the Login method above returns a User object with your auth token, uid, etc.)
Some API methods return a 204 on success or no meaningful content (not meaningful in my usecase maybe I only care about success/failure), for these I'd like to return either a bool (true = success) or the status code.
I'd like to keep the async/await (or equivalent) design, because it seems to really work well so far.
For some methods, I might need to just return the HttpResponseMessage object and let the caller deal with it.
This is roughly what I have so far and I'm not sure how to make it compliant with the above OR whether I'm even doing this right. Any guidance is appreciated (flaming, however, is not).
// 200 (+User JSON) = success, otherwise APIError JSON
internal async Task<User> Login (string id, string password)
{
LoginPayload payload = new LoginPayload() { LoginId = id, Password = password};
var request = NewRequest(HttpMethod.Post, "login");
JsonPayload<LoginPayload>(payload, ref request);
return await Execute<Account>(request, false);
}
// 204: success, anything else failure
internal async Task<Boolean> LogOut ()
{
return await Execute<Boolean>(NewRequest(HttpMethod.Delete, "login"), true);
}
internal async Task<HttpResponseMessage> GetRawResponse ()
{
return await Execute<HttpResponseMessage>(NewRequest(HttpMethod.Get, "raw/something"), true);
}
internal async Task<Int32> GetMeStatusCode ()
{
return await Execute<Int32>(NewRequest(HttpMethod.Get, "some/intstatus"), true);
}
private async Task<RESULT> Execute<RESULT>(HttpRequestMessage request, bool authenticate)
{
if (authenticate)
AuthenticateRequest(ref request); // add auth token to request
var tcs = new TaskCompletionSource<RESULT>();
var response = await client.SendAsync(request);
// TODO: If the RESULT is just HTTPResponseMessage, the rest is unnecessary
if (response.IsSuccessStatusCode)
{
try
{
// TryParse needs to handle Boolean differently than other types
RESULT result = await TryParse<RESULT>(response);
tcs.SetResult(result);
}
catch (Exception e)
{
tcs.SetException(e);
}
}
else
{
try
{
APIError error = await TryParse<APIError>(response);
tcs.SetException(new APIException(error));
}
catch (Exception e)
{
tcs.SetException(new APIException("Unknown error"));
}
}
return tcs.Task.Result;
}
This is the APIError JSON structure (it's the status code + a custom error code).
{
"status": 404,
"code":216,
"msg":"User not found"
}
I would prefer to stay with System.Net, but that's mostly because I don't want to switch all my code over. If what I want is easier done in other ways then it's obviously worth the extra work.
Thanks.

Here is an example of how I've done it using MVC API 2 as backend. My backend returns a json result if the credentials are correct. UserCredentials class is the exact same model as the json result. You will have to use System.Net.Http.Formatting which can be found in the Microsoft.AspNet.WebApi.Client NugetPackage
public static async Task<UserCredentials> Login(string username, string password)
{
string baseAddress = "127.0.0.1/";
HttpClient client = new HttpClient();
var authorizationHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes("xyz:secretKey"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationHeader);
var form = new Dictionary<string, string>
{
{ "grant_type", "password" },
{ "username", username },
{ "password", password },
};
var Response = await client.PostAsync(baseAddress + "oauth/token", new FormUrlEncodedContent(form));
if (Response.StatusCode == HttpStatusCode.OK)
{
return await Response.Content.ReadAsAsync<UserCredentials>(new[] { new JsonMediaTypeFormatter() });
}
else
{
return null;
}
}
and you also need Newtonsoft.Json package.
public class UserCredentials
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
//more properties...
}

i would use a Deserializer.
HttpResponseMessage response = await client.GetAsync("your http here");
var responseString = await response.Content.ReadAsStringAsync();
[Your Class] object= JsonConvert.DeserializeObject<[Your Class]>(responseString.Body.ToString());

So, first to address the you need Newtonsoft.Json comments, I really haven't felt the need yet. I've found the built in support to work well so far (using the APIError Json in my original question:
[DataContract]
internal class APIError
{
[DataMember (Name = "status")]
public int StatusCode { get; set; }
[DataMember (Name = "code")]
public int ErrorCode { get; set; }
}
I have also defined a JsonHelper class to (de)serialize:
public class JsonHelper
{
public static T fromJson<T> (string json)
{
var bytes = Encoding.Unicode.GetBytes (json);
using (MemoryStream mst = new MemoryStream(bytes))
{
var serializer = new DataContractJsonSerializer (typeof (T));
return (T)serializer.ReadObject (mst);
}
}
public static string toJson (object instance)
{
using (MemoryStream mst = new MemoryStream())
{
var serializer = new DataContractJsonSerializer (instance.GetType());
serializer.WriteObject (mst, instance);
mst.Position = 0;
using (StreamReader r = new StreamReader(mst))
{
return r.ReadToEnd();
}
}
}
}
The above bits I already had working. As for a single method that would handle each request execution based on the type of result expected while it makes it easier to change how I handle things (like errors, etc), it also adds to the complexity and thus readability of my code. I ended up creating separate methods (all variants of the Execute method in the original question:
// execute and return response.StatusCode
private static async Task<HttpStatusCode> ExecuteForStatusCode (HttpRequestMessage request, bool authenticate = true)
// execute and return response without processing
private static async Task<HttpResponseMessage> ExecuteForRawResponse(HttpRequestMessage request, bool authenticate = true)
// execute and return response.IsSuccessStatusCode
private static async Task<Boolean> ExecuteForBoolean (HttpRequestMessage request, bool authenticate = true)
// execute and extract JSON payload from response content and convert to RESULT
private static async Task<RESULT> Execute<RESULT>(HttpRequestMessage request, bool authenticate = true)
I can move the unauthorized responses (which my current code isn't handling right now anyway) into a new method CheckResponse that will (for example) log the user out if a 401 is received.

Related

How can I use a token from a request for other requests after responding to the first request?

I have a scenario where I need to respond to a request that it's been received and send a response (request?) to another endpoint once internal api calls and logic has completed. The flow looks like this:
External request to my endpoint > endpoint responds to request with accepted > endpoint passes the request on internally > internal logic fetches and handles data from DB > internal logic uses data from DB to send a request back to a different endpoint from the same integration as the first call came from.
I have managed to get it to work using Queued Background Tasks to send the request to the correct internal handler with Mediatr. However in order for it to work I need to add the barer token from the request header to the request object and then use that barer token to validate against the internal API's. I'd like to avoid this since I might run into the issue of the token expiring or not being valid for the internal Api etc.
Request object example:
public class ExampleRequest : IRequest, IRequest<ExampleResponse>
{
public string? Token { get; set; } //Added for functioning version, want to get rid
//of it
public CommonData Data { get; set; }
public string RequestId { get; set; }
public string OperationId { get; set; }
public List<string> ObjectIdentifiers { get; set; }
}
public class CommonData
{
public string MessageId { get; set; }
public DateTime Timestamp { get; set; }
}
Response object example (response to the call):
public class ExampleResponseForCall
{
public CommonData Data { get; set; }
public string ResponseStatus { get; set; } //Will be accepted/acknowledged
}
Example response object (for final response)
public class ExampleResponse
{
public CommonData Data{ get; set; }
public string ResponseStatus { get; set; }
public string ErrorCode { get; set; }
public string ErrorDescription { get; set; }
public string RequestId { get; set; }
public string OperationId { get; set; }
}
My current working version looks something like this:
**Endpoint:**
public IActionResult Post(ExampleRequest request)
{
var authorization = Request.Headers[HeaderNames.Authorization];
if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
{
var scheme = headerValue.Scheme;
var parameter = headerValue.Parameter;
}
var token = headerValue?.Parameter;
request.Token = token; //I added token as a nullable string on the request obj
_backgroundTaskQueue.StartTask(request);
return Ok(new ExampleResponseForCall
{
Data = request.Data,
ResponseStatus = HttpStatusCode.Accepted.ToString()
});
}
**Background Task queue:**
public void StartTask(IRequest request)
{
_logger.LogInformation("Task is starting.");
_request = request;
Task.Run(async () => await AddTaskAsync(), _cancellationToken);
}
private async ValueTask AddTaskAsync()
{
await _taskQueue.QueueBackgroundWorkItemAsync(BuildWorkItem);
}
private async ValueTask BuildWorkItem(CancellationToken token)
{
var guid = Guid.NewGuid().ToString();
_logger.LogInformation("Task {Guid} is starting.", guid);
if (_request == null)
{
_logger.LogWarning("Request for task {Guid} is null.", guid);
return;
}
await _mediator.Send(_request, token);
_logger.LogInformation("Task {Guid} is complete.", guid);
}
I also have Handlers that can handle the request and Clients for sending requests internally and back to the caller. All of that works when awaiting the internal logic to be handled. However when I'm using the background task queue the internal client fails on the when getting the token here
protected async Task<HttpClient> CreateBaseClient()
{
var client = _clientFactory.CreateClient(HttpClientName);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept",
$"application/json");
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", await GetToken());
return client;
}
public async Task<string> GetToken()
{
if (_httpContextAccessor.HttpContext == null)
throw new Exception("No HttpContext available when trying to
get Token.");
_httpContextAccessor.HttpContext.Items.TryGetValue(Constants.AuthenticationSchemeKey,
out var scheme);
if (scheme?.ToString() == Constants.Bearer)
return GetTokenFromRequest();
throw new MissingAccessTokenException("Unknown authentication type");
}
My workaround (that I want to get away from) looks like this:
protected async Task<HttpClient> CreateBaseClient(string version, string token)
{
var client = _clientFactory.CreateClient(HttpClientName);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept",
$"application/json");
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", token); //token from requst.Token
return client;
}
I've tried to pass in the a lot of different things to the Background Task queue (and changing the parameter type to match ofc) but nothing works. I want to have the background task queue generic since I'll be implementing this for other end points as well.
That's a lot of text so TL:DR, I respond to a request but need to use the token from the request for other calls after responding.
We decided to go with the working solution provided in the question itself.
Due to how our infrastructure is set up we won't be able to get a refresh token (as suggested by #GHDevOps and #TheWallrus) since we won't be able to get the login/id and password/secret of the user in a safe and reasonable way.
However, the working solution in the question has some drawback which should be analyzed on a case-to-case basis. We know that the Api sending us the requests will fetch a new (relevant) token approximately 10 minutes before the current (relevant) token expires and use the new token for all coming requests. Since the logic we apply before passing on the request to our backend is very simple (just simple remapping) we should rarely run into issues with the token expiring before the request has been sent, and in the rare cases that is has, we will send that information in the request back to the external Api, giving them a chance to resend the original request. If the external Api isn't fetching a new token before the expiration of the current token that might cause the token to expire before reaching the internal Api more often which might be a good thing to look after if you're implementing a similar solution.
The code changes that I made for this to function are just minor refactoring (see below). Hope this help anyone else running into a similar issue!
//Endpoint
public IActionResult Post(ExampleRequest request)//Before
{
var authorization = Request.Headers[HeaderNames.Authorization];
if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
{
var scheme = headerValue.Scheme;
var parameter = headerValue.Parameter;
}
var token = headerValue?.Parameter;
request.Token = token; //I added token as a nullable string on the request obj
_backgroundTaskQueue.StartTask(request);
return Ok(new ExampleResponseForCall
{
Data = request.Data,
ResponseStatus = HttpStatusCode.Accepted.ToString()
});
}
public IActionResult Post(ExampleRequest request)
{
request.Token = GetToken(Request);//Made into a separate function in the inherited class
_backgroundTaskQueue.StartTask(request);
return Ok(new ExampleResponseForCall
{
Data = request.Data,
ResponseStatus = HttpStatusCode.Accepted.ToString()
});
}
protected string GetToken(HttpRequest request)
{
var authorization = request.Headers[HeaderNames.Authorization];
_ = AuthenticationHeaderValue.TryParse(authorization, out var headerValue);
if (headerValue == null)
{
return "";
}
return string.Equals(headerValue.Scheme, "Bearer", StringComparison.InvariantCultureIgnoreCase) ?
headerValue.Parameter : "";
}
//Client
protected async Task<HttpClient> CreateBaseClient()//before
{
var client = _clientFactory.CreateClient(HttpClientName);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept",
$"application/json");
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", await GetToken());
return client;
}
protected async Task<HttpClient> CreateBaseClient(string token = "")
{
var client = _clientFactory.CreateClient(HttpClientName);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", $"application/json");
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", string.IsNullOrEmpty(token) ?
await GetToken() : token); //We will only send in a token if we are async
return client;
}

HttpClient Async Method return value

I studied over the Internet regarding Task Async method but cannot seem to find an approach to assign my return value in Task Async to another object. The first method is to prepare HTTP Request header and Uri.
public static async Task MainAsync()
{
string token = await AuthHelper.AcquireToken(tenantId, clientId, clientSecret);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("https://foo.net");
await GetValue(client);
}
}
The second method is to use GetAsync to call to an API to get the JSON and the two last lines I extract only value from the "Value" field in the JSON body.
public static async Task<String> GetValue(HttpClient client)
{
string url = $"/mykey/key01";
using (var httpResponse = await client.GetAsync(url))
{
httpResponse.EnsureSuccessStatusCode();
string responsContent = await httpResponse.Content.ReadAsStringAsync();
JObject json = JObject.Parse(responsContent);
string value = json["value"].ToString();
return value;
}
}
Now I would like to use this value to assign to another object, but not sure how to do so. I managed to return the valid value. Is it possible to retrieve the value from another method or even different class?
[Updated] The main function is:
static void Main(string[] args)
{
try
{
MainAsync().Wait();
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException().Message);
}
}
Update
To be more clear. The HTTP response message is a JSON format and I can return the value from Value property in this JSON. Now how I can to reuse the value from an external method or class
I'm not sure exactly what you are trying to achieve. And there would be thorough debates about your architecture, you can do something like this..
Update
Because your MainAsync is static it can be called form anywhere.
You just need to modify it a bit to return your result as follows :
public static async Task<string> MainAsync()
{
...
return await GetValue(client);
...
And somewhere else
public class MyAwesomeClass
{
public async Task DoMagic()
{
var newValueOfSomething = await MainAsync();
// hilarity ensues
}
}
You can Make it more generic and useful, something like below :
Your initial method can be changes to :
public async Task<T> GetContentAsync<T>(HttpClient client)
{
string url = $"/mykey/key01";
using (var httpResponse = await client.GetAsync(url))
{
httpResponse.EnsureSuccessStatusCode();
string responsContent = await httpResponse.Content.ReadAsStringAsync();
return Deserialize<T>(json);
}
}
private T Deserialize<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, SerializationSettings);
}
You can now call method like :
var person = await GetContentAsync<Person>(/*http client*/)

How to Return HTTP Status Codes from Azure Queue's in C# ASP.NET Web API 2

I have a web api (written in c# on ASP.NET Web API 2). One of the methods takes a HTTP POST and adds it to an Azure Queue.
I'd like to know how I can get hold of a http status code (or whatever is available) from the Azure Queue so that I can return an appropriate http status code from my method.
The code so far is similar to this:
[Route("api/v1/somewhere/")]
[ResponseType(typeof(Thingy))]
public async Task<IHttpActionResult> Post(Thingy thingy)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureWebJobsStorage"].ToString());
var queueClient = storageAccount.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("thingys");
var msg = new CloudQueueMessage(JsonConvert.SerializeObject(thingy));
await queue.AddMessageAsync(msg);
return Json(thingy);
}
I'd like to swap out the return Json(thingy); line and return a http status code 202 if all goes well with the await queue.AddMessageAsync(msg); and another appropriate code if something goes wrong.
Any ideas?
You should make use of LastResult property of OperationContext object. It has a HttpStatusCode property which will return the status code from Storage Service. Here's an example of the same:
static void QueueTest1()
{
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var queueClient = account.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("my-queue");
queue.CreateIfNotExists();
var messageContents = "This is a test message";
var opContext = new OperationContext();
var msg = new CloudQueueMessage(messageContents);
queue.AddMessage(msg, null, null, null, opContext);
var statusCode = opContext.LastResult.HttpStatusCode;
Console.WriteLine("Status Code = " + statusCode);//Prints 201 as status code
queue.DeleteIfExists();
}
Check out this page:
http://bitoftech.net/2014/03/05/new-asp-net-web-api-2-ihttpactionresult-cors-tutorial/
I think you should wrapp the response you want in your own class, something like that:
public class MyResponse : IHttpActionResult
{
public string Message { get; private set; }
public HttpRequestMessage Request { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(ExecuteResult());
}
public HttpResponseMessage ExecuteResult()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Accepted);
response.Content = new StringContent(Message);
response.RequestMessage = Request;
return response;
}
}

WebApi 2 return types

I'm looking at the documentation of WebAPI 2, and i'm severely disappointed with the way the action results are architected. I really hope there is a better way.
So documentation says I can return these:
**void** Return empty 204 (No Content)
**HttpResponseMessage** Convert directly to an HTTP response message.
**IHttpActionResult** Call ExecuteAsync to create an HttpResponseMessage, then convert to an HTTP response message.
**Other type** Write the serialized return value into the response body; return 200 (OK).
I don't see a clean way to return an array of items with custom HTTP status code, custom headers and with auto negotiated content though.
What I would like to see is something like
public HttpResult<Item> Post()
{
var item = new Item();
var result = new HttpResult<Item>(item, HttpStatusCode.Created);
result.Headers.Add("header", "header value");
return result;
}
This way I can glance over a method and immediately see whats being returned, and modify status code and headers.
The closest thing I found is NegotiatedContentResult<T>, with weird signature (why does it need an instance of controller?), but there's no way to set custom headers?
Is there a better way ?
The following code should give you everything you want:
[ResponseType(typeof(Item))]
public IHttpActionResult Post()
{
var item = new Item();
HttpContext.Current.Response.AddHeader("Header-Name", "Header Value");
return Content(HttpStatusCode.Created, item);
}
... if you really need to return an array of items ...
[ResponseType(typeof(List<Item>))]
public IHttpActionResult Post()
{
var items = new List<Item>();
// Do something to fill items here...
HttpContext.Current.Response.AddHeader("Item-Count", items.Count.ToString());
return Content(HttpStatusCode.Created, items);
}
I don't think the designers of the web-api intended for controller methods to be fiddling with the headers.
The design pattern seems to be to use DelegatingHandler, ActionFilterAttribute and the ExecuteAsync overridable method of ApiController to handle authentication and response formatting.
So perhaps your logic for message content negotiation should be handled there ?
However if you definitely need to control headers from within your controller method you can do a little set-up to make it work.
To do so you can create your own DelegationHandler that forwards selected headers from your "Inner" response headers:
public class MessageHandlerBranding : DelegatingHandler {
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
//If we want to forward headers from inner content we can do this:
if (response.Content != null && response.Content.Headers.Any())
{
foreach (var hdr in response.Content.Headers)
{
var keyUpr = hdr.Key.ToUpper(); //Response will not tolerate setting of some header values
if ( keyUpr != "CONTENT-TYPE" && keyUpr != "CONTENT-LENGTH")
{
string val = hdr.Value.Any() ? hdr.Value.FirstOrDefault() : "";
response.Headers.Add(hdr.Key, val);
}
}
}
//Add our branding header to each response
response.Headers.Add("X-Powered-By", "My product");
return response;
}
}
Then you register this handler in your web-api configuration, this is usually in the GlobalConfig.cs file.
config.MessageHandlers.Add(new MessageHandlerBranding());
You could also write your own custom class for the response object like this:
public class ApiQueryResult<T> : IHttpActionResult where T : class
{
public ApiQueryResult(HttpRequestMessage request)
{
this.StatusCode = HttpStatusCode.OK; ;
this.HeadersToAdd = new List<MyStringPair>();
this.Request = request;
}
public HttpStatusCode StatusCode { get; set; }
private List<MyStringPair> HeadersToAdd { get; set; }
public T Content { get; set; }
private HttpRequestMessage Request { get; set; }
public void AddHeaders(string headerKey, string headerValue)
{
this.HeadersToAdd.Add(new MyStringPair(headerKey, headerValue));
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = this.Request.CreateResponse<T>(this.StatusCode, this.Content);
foreach (var hdr in this.HeadersToAdd)
{
response.Content.Headers.Add(hdr.key, hdr.value);
}
return Task.FromResult(response);
}
private class MyStringPair
{
public MyStringPair(string key, string value)
{
this.key = key;
this.value = value;
}
public string key;
public string value;
}
}
And use it like this in your controller:
[HttpGet]
public ApiQueryResult<CustomersView> CustomersViewsRow(int id)
{
var ret = new ApiQueryResult<CustomersView>(this.Request);
ret.Content = this.BLL.GetOneCustomer(id);
ret.AddHeaders("myCustomHkey","myCustomValue");
return ret;
}

HttpResponseMessage from HttpClient to User Defined Object C#

I have seen similar questions asked but none that seem to help me with my issue so please bear with me.
I have a WebAPI controller method that is defined as such:
[HttpPost]
[Route("")]
public HttpResponseMessage CreateMyObject(MyObjectRequest myObject)
{
MyObject o;
try
{
o = _serviceFactory.GetInstance().CreateMyObject(myObject);
}
catch (Exception ex)
{
ex.WriteToLog();
throw ApiHelper.CreateResponseException(HttpStatusCode.InternalServerError, ex);
}
var response = Request.CreateResponse(HttpStatusCode.Created, o);
var uri = Url.Link("GetMyObjectById", new { myObjectId = o.MyObjectId.ToString() });
response.Headers.Location = new Uri(uri);
return response;
}
Say, MyObject contains two properties,
public MyObject
{
public Guid MyObjectId;
public string MyObjectName
}
A client was written to call these controller methods in a WPF application. Here is the client method that is being used:
public HttpResponseMessage CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
return response;
}
protected async Task<HttpResponseMessage> GetResponse(string path, Hashtable parameters)
{
var response = await GetAsync(BuildRequestUri(path, parameters)).ConfigureAwait(false);
return response.IsSuccessStatusCode ? response : new HttpResponseMessage();
}
protected async Task<HttpResponseMessage> GetResponse(string path)
{
return await GetResponse(path, null);
}
The controller and supporting client code was not written by me and was already in the system. I am just consuming this in the WPF application. Now, I am trying to call the controller method via the client in the application and get the MyObject from the response so that I can access the MyObjectId that has been created and set. I have tried some of the other responses to similar questions but have not even seen some of the methods that are called on the response in order to get the information. Here is the first part of the call to the client that I have in the application:
var httpResponse = ApplicationService.CreateMyObject(myObjectRequest);
The application service simply injects the client into the constructor and allows me to call the CreateMyObject method. Is there any insight that can be given to me on how I should be getting the MyObject object out of the response?
I'm still a little new to web api as well, but I'm currently working with it on a project. Give the following code a try:
MyObject myObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
myObject = response.Content.ReadAsAsync<MyObject>().Result;
}
So you could theoretically change your method like this (may not be exactly what you want):
public MyObject CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
MyObject newObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
newObject= response.Content.ReadAsAsync<MyObject>().Result;
}
return newObject; // instead of response
}

Categories

Resources