PostAsync request with Array parameter on MVC Web API - asp.net-mvc-4

I have Xamarin application that has POST request with array list of parameter and on my MVC WEB API we used code first Entity framework. Both was separated project solutions (.sln).
On my Xamarin project, I have PostAsync request which supplies List of array values.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
var data = JsonConvert.SerializeObject(parameters);
var content = new StringContent(data, Encoding.UTF8, "application/json");
using (var response = await client.PostAsync(url, content))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}
Then In my Web API controller I have same parameter with my client side also.
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpPost]
[Route("type={type}&param={param}")]
public BasicResponse applog([FromUri] ProfilingType type , List<string> param)
{
if (ModelState.IsValid == false)
{
throw new ModelValidationException("Model state is invalid.");
}
try
{
if(type == ProfilingType.Login)
{
var command = new SendDataProfilingCommand(param);
CommandHandler.Execute(command);
}
else
{
var command = new UpdateDataProfilingCommand(type,param);
CommandHandler.Execute(command);
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return new BasicResponse
{
Status = true,
Message = Ok().ToString()
};
}
Since I'm not with the API, I want to test it first on Postman or even in the URL. but my problem was when i Try to test it using this url below
http://localhost:59828/api/users/applog?type=1&param=[1,Caloocan,Metro Manila,Philippines,0,0]
I received this message : No HTTP resource was found that matches the request URI ......
My Question is, How can I test my Web API with List Parameter on URL or in the Postman ? and What Format I can use when sending a post request into my Xamarin PostAsync request?

You don't need to send as Content.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
url = url + "?" + Parameter;
using (var response = await client.PostAsync(url))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}

Related

Asp.Net Core - Making API calls from backend

I have an application which is calling API's from a backend cs class, using IHostedService. With basic API calls ("http://httpbin.org/ip") it is working fine and returning the correct value, however I now need to call a Siemens API which requires me to set an Authorization header, and place "grant_type=client_credentials" in the body.
public async Task<string> GetResult()
{
string data = "";
string baseUrl = "https://<space-name>.mindsphere.io/oauth/token";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", {ServiceCredentialID: ServiceCredentialSecret});
using (HttpResponseMessage res = await client.GetAsync(baseUrl))
{
using (HttpContent content = res.Content)
{
data = await content.ReadAsStringAsync();
}
}
}
I think I have the header set up correctly but I won't know for sure until the full request gets formatted. Is it even possible to set the the body of the request to "grant_type=client_credentials"?
As far as I can see from Siemens API documentation they expect Form data, so it should be like:
public async Task<string> GetResult()
{
string data = "";
string baseUrl = "https://<space-name>.mindsphere.io/oauth/token";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", {ServiceCredentialID: ServiceCredentialSecret});
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
});
using (HttpResponseMessage res = await client.PostAsync(baseUrl, formContent))
{
using (HttpContent content = res.Content)
{
data = await content.ReadAsStringAsync();
}
}
}
}

How to use the continuationtoken in TFS 2015 Object Model: GetBuildsAsync?

I am using the following code
BuildHttpClient service = new BuildHttpClient(tfsCollectionUri,
new Microsoft.VisualStudio.Services.Common.VssCredentials(true));
var asyncResult = service.GetBuildsAsync(project: tfsTeamProject);
var queryResult = asyncResult.Result;
This returns only the first 199 builds.
Looks like in need to use the continuationtoken but am not sure how to do this. The docs say that the REST API will return the token. I am using the Object Model, and am looking for how to retrieve the token!
I am using Microsoft.TeamFoundationServer.Client v 14.102.0; Microsoft.TeamFoundationServer.ExtendedClient v 14.102.0, Microsoft.VisualStudio.Service.Client v 14.102.0 and Microsoft.VisualStudio.Services.InteractiveClient v 14.102.0
Question
How do I use the continuation token **when using the TFS Object model?
The continuationToken is in the response header after the first call to the API:
x-ms-continuationtoken: xxxx
It can not be retrieved from .net client library. You have to use the rest api to retrieve the header information. Here is an example for your reference:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace GetBuilds
{
class Program
{
public static void Main()
{
Task t = GetBuilds();
Task.WaitAll(new Task[] { t });
}
private static async Task GetBuilds()
{
try
{
var username = "xxxxx";
var password = "******";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
using (HttpResponseMessage response = client.GetAsync(
"http://tfs2015:8080/tfs/DefaultCollection/teamproject/_apis/build/builds?api-version=2.2").Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
You have to use 'GetBuildsAsync2', which returns an IPagedList. You can retrieve the ContinuationToken from the IPagedList:
// Iterate to get the full set of builds
string continuationToken = null;
List<Build> builds = new List<Build>();
do
{
IPagedList<Build> buildsPage = service.GetBuildsAsync2(tfsTeamProject, continuationToken: continuationToken).Result;
//add the builds
builds.AddRange(buildsPage);
//get the continuationToken for the next loop
continuationToken = buildsPage.ContinuationToken;
}
while (continuationToken != null);

How do I get the model state from a HTTPRequestResponse from within a console application

I have an APS.NET Core 2.0 API that I am writing a test client for. The test client is a console application. I want to be able to read and display any errors returned from may API call that would be in the model state.
In my API, if the model is not valid, I return the model along with a status 422 as follows;
if (!ModelState.IsValid)
{
return new UnprocessableEntityObjectResult(ModelState);
}
The UnprocessableEntityObjectResult is just a helper class, as shown below;
public class UnprocessableEntityObjectResult : ObjectResult
{
public UnprocessableEntityObjectResult(ModelStateDictionary modelState)
: base(new SerializableError(modelState))
{
if (modelState == null)
{
throw new ArgumentNullException(nameof(modelState));
}
StatusCode = 422;
}
}
My intent is to return the modelstate to the client, on error.
My test client is a console application and I am looking for a way to examine the model state and list out any errors.
In my console application, I have the following method that is called from Main;
static async Task CreateUploadRecordAsync()
{
httpClient.BaseAddress = new Uri("https://localhost:44369");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string relativeUrl = "/api/upload";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, relativeUrl);
HttpResponseMessage response = new HttpResponseMessage();
using (var content = new MultipartFormDataContent())
{
//Add content values here...
request.Content = content;
response = await httpClient.SendAsync(request);
}
if (response.IsSuccessStatusCode)
{
string result = response.Headers.Location.ToString();
Console.WriteLine("Success:\n");
Console.WriteLine($"New Record Link: [{result}]\n");
}
else
{
//Add code here to get model state from response
Console.WriteLine($"Failed to create new upload record. Error: {response.ReasonPhrase}\n");
}
}
I am looking for an example of how to extract the model state that would exist after the "/Add code here to get model state from response" comment.
Any ideas?

How to implement the await keyword?

I have written a code to get the projects from the TFS 2013 server using the tfs web api. As the methord is taking too long to execute i.e like 1.5 minutes, so i wanted to make this methord as async. So i added the async and task in the return type. When i see in visual studio is shows a message that the methord does not have await keyword. where should i add the await keyword. I am very new to async programming.
public override async Task<List<Project>> GetProjects()
{
List<Project> retunResult = new List<Project>();
using (var http = new HttpClient(GetHttpHandler()))
{
var response = http.GetAsync(_baseUrl + "_apis/projectCollections?" + tfsWebApiVersionSring).Result;
if (response.IsSuccessStatusCode)
{
response.EnsureSuccessStatusCode();
TFS2013TeamProjectCollection.Rootobject obj = JsonConvert.DeserializeObject<TFS2013TeamProjectCollection.Rootobject>(response.Content.ReadAsStringAsync().Result);
if (obj != null)
{
foreach (TFS2013TeamProjectCollection.Value projColl in obj.value)
{
if (projColl.state == "Started")
{
var responseProj = http.GetAsync(_baseUrl + projColl.name + "/_apis/projects?" + tfsWebApiVersionSring).Result;
if (responseProj.IsSuccessStatusCode)
{
responseProj.EnsureSuccessStatusCode();
TFS2013TeamProject.Rootobject obj1 = JsonConvert.DeserializeObject<TFS2013TeamProject.Rootobject>(responseProj.Content.ReadAsStringAsync().Result);
if (obj1 != null)
{
Project p;
foreach (TFS2013TeamProject.Value TeamProj in obj1.value)
{
p = new Project();
p.collectionName = TeamProj.collection.name;
p.description = TeamProj.description;
p.id = TeamProj.id;
p.name = TeamProj.name;
p.collectionName = TeamProj.collection.name;
p.url = TeamProj.url;
retunResult.Add(p);
}
}
}
}
}
return retunResult;
}
}
}
return null;
}
You could refer to this code snippet about using TFS REST API to get something in async way.
public static async void RESTAPIMethod()
{
HttpClientHandler authtHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials
};
using (HttpClient client = new HttpClient(authtHandler))
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
using (HttpResponseMessage response = client.GetAsync(
"Put the REST API URL here").Result)
{
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
}
}
}
Another method about using TFS REST API:
You could also install this Nuget package for your project. Then using these assemblies in this package to run a REST API with C#. This is different with the method above, it's much more convenient. Here is an example about get a build information using Microsoft.TeamFoundation.Build.WebApi assembly in Async method.
Example:
What object returns from TFS2015 RestAPI
You shouldn't use Result at all. Every place in your code where you have:
var resp = http.GetAsync(url).Result;
you should have:
var resp = await http.GetAsync(url);

How to receive a response package from GET request for OneNote API

I'm getting a acknowledgement but no response message (details) i.e. list of notebooks from the OneNote API. Below is my code. I am able to receive the header and JSON details from a POST message but not the GET. I have tried to convert the POST code in order to submit a GET request.
private async void getRequestClick(object sender, RoutedEventArgs e)
{
await GetRequests(true, "test");
}
async public Task<StandardResponse> GetRequests(bool debug, string sectionName)
{
Uri PagesEndPoint1 = new Uri("https://www.onenote.com/api/v1.0/notebooks");
var client = new HttpClient();
//// Note: API only supports JSON return type.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//// This allows you to see what happens when an unauthenticated call is made.
if (IsAuthenticated)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authClient.Session.AccessToken);
}
HttpResponseMessage response;
HttpRequestMessage createMessage = new HttpRequestMessage(HttpMethod.Get, PagesEndPoint1);
response = await client.SendAsync(createMessage);
tbResponse.Text = response.ToString();
return await TranslateResponse(response);
}
private async static Task<StandardResponse> TranslateResponse(HttpResponseMessage response)
{
StandardResponse standardResponse;
if (response.StatusCode == HttpStatusCode.Created)
{
dynamic responseObject = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
standardResponse = new CreateSuccessResponse
{
StatusCode = response.StatusCode,
OneNoteClientUrl = responseObject.links.oneNoteClientUrl.href,
OneNoteWebUrl = responseObject.links.oneNoteWebUrl.href
};
}
else
{
standardResponse = new StandardErrorResponse
{
StatusCode = response.StatusCode,
Message = await response.Content.ReadAsStringAsync()
};
}
// Extract the correlation id. Apps should log this if they want to collcet the data to diagnose failures with Microsoft support
IEnumerable<string> correlationValues;
if (response.Headers.TryGetValues("X-CorrelationId", out correlationValues))
{
standardResponse.CorrelationId = correlationValues.FirstOrDefault();
}
return standardResponse;
}
My POST messages are working OK. I can create a new page etc.
I think you need to change the expected status code from HttpStatusCode.Created to HttpStatusCode.OK for Get requests, since they return a 200 and not a 201. Try doing that in your TranslateResponse method.