How to Consume an API in ASP.NET Core? - json

I need to consume an API in my MVC project. the actions in API are secured, So you need to access a token (JWT) to consume it. I face an error every time I try to deserialize the response into the model (Player). It says *Could not cast or convert from System.String to MyMVC.Models.Player*
When I run a debugger, the piece of code including deserialization is in red in the internal server error page.
Here is the action in API
[HttpGet]
[Authorize]
public ActionResult<List<Player>> GetAllPlayers()
{
var players = _applicationDbContext.Players.OrderBy(p => p.Name).Select(p=> p.Name).ToList();
return Ok(players);
}
This is the action in the MVC project
public async Task<IActionResult> GetPlayers()
{
var token = HttpContext.Session.GetString("Token");
List<Player> players = new List<Player>();
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:53217/api/player");
var client = _clientFactory.CreateClient();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if(response.StatusCode == System.Net.HttpStatusCode.OK)
{
var strResponse = await response.Content.ReadAsStringAsync();
players = JsonConvert.DeserializeObject<List<Player>>(strResponse);
}
return View(players);
}

Sami Kuhmonen 's comment is right.
var players = _applicationDbContext.Players.OrderBy(p => p.Name).Select(p=> p.Name).ToList();
From here we can get name list not player list.
Name list contain string name. Player list contain object player1 {name="xx",age="xx"}
But
List<Player> players = new List<Player>();
var strResponse = await response.Content.ReadAsStringAsync();
players = JsonConvert.DeserializeObject<List<Player>>(strResponse);
here we need player list contain object players .
You can use below code in your API to get the playerlist.
var players = _applicationDbContext.Players.ToList();
I reproduce your problem. Then I use that method to solve it.
Update
Create a new class User contain the property that you want.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
Then use the below code
var players = _applicationDbContext.Players.Select (P=>new User { Name=P.Name, Id=P.Id} ).ToList();
In mvc change List<Player> players = new List<Player>(); to
List<User> players = new List<User>();
Result:

Related

Returning a user object in json after after consuming the login api that uses basic authentication

I'm quite new in Web API, so I have a Web API controller that has to return a user object in json so that I can use that json data in my xamarin forms client. I have a validite method that reads or gets data from the database then I call that validate method on BasicAuthenticationAttribute OnAuthorization method which uses Generic Identity and Generic Principal which I don't fully understand how they work. I need to pass my user object which is returned in the validate method of which I'm puzzled I need help here is what I did:
//This method is used to check the user credentials
public static bool Login(string username, string password)
{
string hashedPassword = Util.HashPassword(password);
IEmployee obj = new EmployeeBL();
var userData = obj.GetByUserName(username);
return (!string.IsNullOrEmpty(userData.UserName) &&
string.CompareOrdinal(userData.Pass, hashedPassword) == 0);
}
The code below is in my BasicAuthenticationAttribute class OnAuthorization method of which I dont want to use GenericIdentity since it only takes name I want to pass my user object which I can't figure out since I'm new :
if (UserValidate.Login(username, password))
{
var identity = new GenericIdentity(username);
IPrincipal principal = new GenericPrincipal(identity, null);
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
}
Then here is my API Controller which I need to return a json object:
[BasicAuthentication]
public HttpResponseMessage GetEmployee()
{
//string username = Thread.CurrentPrincipal.Identity.Name;
var response = Request.CreateResponse<string>
(System.Net.HttpStatusCode.Created, "Success!");
return response;
}
2 ways:
let web api serialize it for you:
var jObject = JObject.Parse("success!");
return jObject;
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jObject.ToString(),Encoding.UTF8,"application/json");
return response;

Why are PostAsJsonAsync's parameters not included in the post as JSON content?

IT is very disapointing that after one week i cannot solve a simple problem of posting a JSON content to a Web Server's API. I think I will quit this attempt to use Xamarin.
I am trying to post the JSON parameters below using PostAsJsonAsync in a Xamarin app. The program does post the site but the parameters are not encoded as JSON content. Does anyone know why?
public async void Login()
{
var formcontent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("email","marcio#netopen.com.br"),
new KeyValuePair<string, string>("password","Xy345")
});
var FlyVIPAPI = new HttpClient();
var request = await FlyVIPAPI.PostAsJsonAsync("http://www.ik.com.br/app/api/LoginUser.php", formcontent);
var response = await request.Content.ReadAsStringAsync();
//var res = JsonConvert.DeserializeObject(response);
var RepostaJson = Newtonsoft.Json.Linq.JObject.Parse(response);
System.Diagnostics.Debug.WriteLine(RepostaJson["success"]);
System.Diagnostics.Debug.WriteLine(RepostaJson["error"]);
return;
}
public class LoginRequest
{
public string email { get; set; }
public string password { get; set; }
}
public async void Login()
{
using (var FlyVIPAPI = new HttpClient())
{
// Create Request object
var requestObj = new LoginRequest { email = "marcio#netopen.com.br", password = "Xy345" };
// Serialize to JSON string
var formcontent = JsonConvert.SerializeObject(requestObj);
// Create HTTP content
var content = new StringContent(formcontent, Encoding.UTF8, "application/json");
// POST Request
var request = await FlyVIPAPI.PostAsync("http://www.ik.com.br/app/api/LoginUser.php", content);
// Read Response
var response = await request.Content.ReadAsStringAsync();
....
}
}
Additionally, I would suggest wrapping your HttpClient in a using statement so that is will be disposed of once your code block is done. Freeing up resources.

Signalr Return Model Object

The story is that, I have ROOM Model class. I want to return json with using Signalr. Is it possible ? If it is, how can i use it ?
PS: And I know that I dont return room objet to clients.
public List<RoomModel> GetRooms()
{
GameUser user = _gameService.GetUserByClientId(Context.ConnectionId);
var room = _gameService.GetAllowedRooms(user).Select(r => new RoomModel
{
Name = r.Name,
Count = 0,
Private = r.Private,
Closed = r.Closed,
}).ToList();
return room;
}
SignalR will automatically serialize your objects when you are sending them over to client. (I assume your client is javascript.)
As you can see in this example They are sending ShapeModel complex object to be processed in javascript. The serialization is all automated.
If your method from your example is a hub method, I suggest you end it differently. Instead of returning value, you would probably call a client event. So:
public class RoomHub : Hub {
public void GetRooms() {
List<Room> rooms = new List<Room>();
rooms.Add( new Room{ Name = "Room1", Count = 12, Closed = true, Private = false});
rooms.Add( new Room{ Name = "Room2", Count = 20, Closed = false, Private = true});
// sending a list of room objects
Clients.Client(Context.ConnectionId).roomInfo(rooms);
}
}
// Room class (your complex object)
public class Room
{
public string Name { get; set; }
public int Count { get; set; }
public bool Private { get; set; }
public bool Closed { get; set; }
}
See details about calling from hub methods here.
Then javascript client:
var roomHub = $.connection.roomHub;
roomHub.client.roomInfo = function (rooms) {
// the parameter rooms is a serialized List<Room>
// which here will be an array of room objects.
console.log(rooms);
// You can read the room properties as well
for (i=0; i<rooms.length; ++i) {
console.log(rooms[i].Name);
console.log(rooms[i].Count);
}
}
$.connection.hub.start().done(function () {
console.log("You are connected");
roomHub.server.getRooms();
});
On my browser console:

http client in windows 8 app

i made an app in windows phone successfully & now i want to make it for windows 8 store app but i stuck on a point where i want to my web service in store app.
I use webclient in WP but i don't know anything about how to access web service in Windows 8 store app. My web service return data in json format i deserialize & store in a variable in WP & i use post method . but how it would be done in Windows 8 store app.
what would i use for windows 8 in place of Webclient.
i post my windows phone code
private void PostData()
{
Uri uri = new Uri(my web service url);
string data = "device_id=" + val + "&quiz_type=all";
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += wc_UploadComplete;
}
public void wc_UploadComplete(object sender, UploadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
}
You see that i store all the data in rootObject.
How these thing can be done in windows 8 app?
1st Method: Parsing and Reusing JSON Objects
Step1: Go to Json2Csharp site and paste either your entire JSON string or URL to the JSON and click on Generate button. This creates all the required classes for your JSON response.
For example, this JSON dataset:
{"MyBlogList":[{"ID":9,"TYPE":"WindowsPhone","TITLE":"XYZ","PRICE":"0","IMAGE":"Post1.jpg"}],"success":3}
The generated class object is:
public class MyBlogList
{
public int ID { get; set; }
public string TYPE { get; set; }
public string TITLE { get; set; }
public string PRICE { get; set; }
public string IMAGE { get; set; }
}
public class RootObject
{
public List<MyBlogList> MyBlogList { get; set; }
public int success { get; set; }
}
Now place this class somewhere in your project, so that it will be available in the required locations.
Step 2: (i.e. assuming that you get your JSON from a web service), Make a web request to get the JSON response
You will have to use the WebClient class as well as enabling the DownloadStringCompleted Event handler which returns the response to be manipulated.
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(http://somedomain.com/xyz/myjson.aspx));
And then in the response handler, use the following code to parse the data and convert into classes:
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
foreach (var blog in rootObject.MyBlogList)
{
Console.WriteLine(blog.TITLE);
}
}
2nd Method: One Time JSON Parse
Here as your requirement is one time parsing and one time usage, instead of storing them in unnecessary classes, we just wisely parse the data and get the task done.
Consider the exact same sample JSON dataset provided above, and we want to get the blog title so here is the code snippet for that:
JObject obj = JObject.Parse(jsonData);
JArray jarr = (JArray)obj["MyBlogList"];
string blogTitle = (string)jarr[0]["TITLE"]; //To get the title of the blog
or
foreach(var item in jarr)
Console.WriteLine(item["TITLE"]); //Gets the title of each book in the list
There you go, you can play with the response and bind the data with the UI elements.
You have to use HttpClient.
private async Task UploadData()
{
HttpClient httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 256000;
httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; WIndows NT 6.2; WOW64; Trident/6.0)");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
string data = "device_id=" + val + "&quiz_type=all";
HttpContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("payloadData", data)
});
HttpResponseMessage response = await httpClient.PostAsync(new Uri(my web service url), content);
response.EnsureSuccessStatusCode();
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
// This is your responce data.
string result = await response.Content.ReadAsStringAsync();
var rootObject = JsonConvert.DeserializeObject<RootObject>(result);
}

Detecting when a web service post has occured

I just wrote a simple windows 8 form that post to web service api. It works fine. But my challenge is been able to determine when the post operation was a success and a failure. I dont know how to return a value cos aysnc Task is not allowing a return type.
//This class does the post to web service
public class B2cMobileuserService : IB2cMobileuserService
{
private string RegisterUserUrl = RestfulUrl.RegisterMobileUser;
private readonly HttpClient _client = new HttpClient();
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
}
}
//This class calls the one above
public class WebserviceProcessor
{
//declaring all the service objects that would be used
IB2cMobileuserService mobileuserService = null;
public WebserviceProcessor() {
mobileuserService = new B2cMobileuserService();
}
//This method is going to post values to the web serever
public async void RegisterUser(B2cMobileuserView mobileuser) {
mobileuserService.RegisterMobileUser(mobileuser);
}
}
//Then the code below is from my .xaml user interface that calls the class that sends to webservice
private void Button_Click(object sender, RoutedEventArgs e)
{
B2cMobileuserView user = new B2cMobileuserView();
user.Name = name.Text;
user.Email = email.Text;
user.PhoneType = "Windows Mobile";
user.BrowserType = "None";
user.CountryName = "Nigeria";
user.UserPhoneID = phone.Text;
Serviceprocessor.RegisterUser(user);
progressBar.Visibility = Visibility.Visible;
}
Please I dont know how to return a value cos when I try I get the error that says async method must be void.
I need to set a way to know when the post was a success based on the return value from the web service.
To ensure the POST was successful, call HttpResponseMessage.EnsureSuccessStatusCode:
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
result.EnsureSuccessStatusCode();
}
If you want to return a value, use a Task<T> return type instead of Task.
On a side note, avoid async void; use async Task instead of async void unless the compiler forces you to write async void:
//This method is going to post values to the web serever
public Task RegisterUser(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUser(mobileuser);
}
Also, you should name your asynchronous methods ending in *Async:
//This method is going to post values to the web serever
public Task RegisterUserAsync(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUserAsync(mobileuser);
}
You may find my async intro and MSDN article on async best practices helpful.