How can i get a single response using linq - json

I have the following API code to get a single result response but i get error json.net complaining
when i remove this line var Product = prdList .FirstOrDefault(a => a.ID == productID); and return Json(prdList); it works fine but return every row in a table. how can i get a single record?
Here is the code
[HttpGet("{productID}")]
public async Task<IActionResult> Getproduct(int productID)
{
var prdList = (await rpsService.Getrps(productID)).ToList();
var Product = prdList .FirstOrDefault(a => a.ID == productID);
return Json(Product);
}
Here is the error im getting, i retrive the right information but i get error when i load the page
JsonSerializationException: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1
Project name' because the type requires a JSON array (e.g. [1,2,3]) to
deserialize correctly. To fix this error either change the JSON to a
JSON array (e.g. [1,2,3]) or change the deserialized type so that it
is a normal .NET type (e.g. not a primitive type like integer, not a
collection type like an array or List) that can be deserialized
from a JSON object. JsonObjectAttribute can also be added to the type
to force it to deserialize from a JSON object. Path 'productID', line
1, position 13.
I tried this working fine but display all rows
[HttpGet("{productID}")]
public async Task<IActionResult> GetProduct(int productID)
{
var prdList = (await rpsService.Getrps(productID)).ToList();
return Json(prdList );
}

you can directly apply condition while fetching list as mention below.
var prdList = (await rpsService.Getrps(productID)).ToList().FirstOrDefault();

Try this
var Product = prdList.Where(a => a.ID == productID).FirstOrDefault();
or
var prdList = (await rpsService.Getrps(productID)).ToList().FirstOrDefault();
return Json(prdList);

Related

Unable to parse data from firebase in flutter

Here is the model I am using for the data.
Here is the Future I am using to extract the data.
Future<List<Topic>> getTopics(String subjectid) async {
var ref = db.collection('topics')
.where(
'subject',
isEqualTo: subjectid
);
var snapshot = await ref.get();
var data = snapshot.docs.map((s) => s.data());
var topics = data.map((d) => Topic.fromJson(d));
return topics.toList();
}
Here is how I have the data in firebase.
I am getting a error in the type cast:
type 'InternalLinkedHashMap<string, dynamic>' is not a subtype of type 'List<dynamic>?
When I try to print the topics.toList(), the print returns nothing.
I played around with my model, made sure all the columns are mapped correctly. My call for another collection works fine. But this one just won't work.

Why is one way of json to object working and the other throwing null error? Dart/Flutter null safety trouble

I'm learning how to use json, not used to Dart null safety & I don't like it so far. But I will have no choice but to adapt to it. I'm trying to parse my json object list into a list of objects. I was able to work out the basics in my main, but when I attempt to create an actual method in a class using the same structure I'm getting a null error. As far as I can tell I'm doing the exact same thing in both with addition of the loop for iterating the entire json list.
Note: I of course did try inserting the optional ? where it asks but the IDE will not allow this.
Can someone help with explaining what I'm doing wrong here?
Error for class method jsonToDatabaseSyncItem()
lib/services/remote_database_services.dart:52:43: Error: Property 'length' cannot be accessed on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
Try accessing using ?. instead.
final jsonListLength = jsonObjectList.length;
^^^^^^
lib/services/remote_database_services.dart:55:38: Error: Operator '[]' cannot be called on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
Class method (class- RemoteDatabaseService)
// This method will get server database
Future<List<dynamic>?> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success && apiResponse.result != null) {
return apiResponse.results;
} else {
return [];
}
}
// Method to parse json result list back to objects
Future<List<dynamic>?> jsonToDatabaseSyncItem() async {
final remoteDatabaseList = await getRemoteDatabase();
final jsonObjectList = await Future.value(remoteDatabaseList); /// This method throws the above
final jsonListLength = jsonObjectList.length; /// error when run in main
for (var index = 0; index == jsonListLength; index++) {
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
print(jsonObject);
}
}
Main file working code
Future<void> main(List<String> arguments) async {
final test = remoteDatabaseServices.getRemoteDatabase();
Future<List<dynamic>?> getList() {
return Future.value(test);
}
var list = await getList();
print(list?.length);
var jsonObject = list![0]['DatabaseSyncItem'];
print(jsonObject);
var toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}
Your problem with null-safety seems to be a missing understanding about the feature. I will recommend you to read through the documentation here and read all the chapters: https://dart.dev/null-safety
About your code, you should consider when something can be null and when you can check the null and handle that case. In your example, it seems like getRemoteDatabase() should just return an empty List if an error happens or no result is returned. So we don't need to have the return type of this method as Future<List<dynamic>?> if we rewrite the method a bit:
Future<List<dynamic>> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success) {
return apiResponse.results ?? <dynamic>[];
} else {
return <dynamic>[];
}
}
(the ?? operator will here test if apiResponse.results is null, if that is the case, we return <dynamic>[]. If not, we use the value of apiResponse.results).
Since this method is now guarantee to never return null, we can use that to simplify the next method. I have also rewritten it to use a for-each loop since we don't really need the index of each element.
Future<void> jsonToDatabaseSyncItem() async {
final jsonObjectList = await getRemoteDatabase();
for (final jsonObject in jsonObjectList) {
print(jsonObject['DatabaseSyncItem']);
}
}
I have also removed this line since it does nothing at all. If remoteDatabaseList is a Future you should just await on that instead of creating a new Future.
final jsonObjectList = await Future.value(remoteDatabaseList);
Also, the return type of jsonToDatabaseSyncItem() have been changed to Future<void> since we are never returning any value.
I am a little confused about your main but I think this is where it is most clear that you got a confused about Future and null-safety. I have tried to rewrite it so it is much cleaner but should still do the same:
Future<void> main(List<String> arguments) async {
final list = await getRemoteDatabase();
print(list.length);
final dynamic jsonObject = list[0]['DatabaseSyncItem'];
print(jsonObject);
final toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}

Angular HttpClient returns string data instead of parsed JSON

I've been in the process of migrating a code base from Angular 4.x to 5.x, and I'm running into a strange issue. I have a service function, that is intended to return a list of objects to the front end, which I then massage into a specific data format. I know I'll need to keep the mapping, but I'm a little miffed that it's returning just plain string data.
The original function is this: (using Http from #angular/http just renamed to HttpClient)
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: URLSearchParams = new URLSearchParams();
params.set('showAll', showAll.toString());
params.set('screenArea', screenArea.toString());
let requestOptions = new RequestOptions();
requestOptions.search = params;
return this.httpClient.get(link, requestOptions).map(response => {
let result = JSON.parse(response.json());
let list = new Array<SelectModel>();
let vendors: Array<any> = result;
vendors.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
and after ripping out ALL of the Http code, here's the function again using HttpClient from #angular/common/http
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: HttpParams = new HttpParams()
.set('showAll', showAll.toString())
.set('screenArea', screenArea.toString());
return this.httpClient.get<Array<any>>(link, {params}).map(response => {
let list = new Array<SelectModel>();
response.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
The issue with this is it kind of defeats the purpose of the new client parsing json for me. The response object is a string representing the JSON of the data I requested, but it's still in a string form, and not the type defined in the get<>() call.
What am I doing wrong here? shouldn't it be parsed already?
Sample Response Data A'la Network Tools in Chrome Dev Tools:
Sample Response Body:
Dev Tools Screenshot with Value of response
The backend (C#) responds with this:
[HttpGet]
public JsonResult Vendors(bool showAll = false, int screenArea = 0)
{
var vendors = _commonBL.GetVendorsSlimForUser(UserModel, UserModel.CustomerId, showAll, screenArea);
return GetJson(vendors);
}
this is how it worked before the Http => HttpClient migration, and it worked with ONE JSON.parse() The data in the return line is simply a standard List<T>
This is what the raw response for your data should look like:
[{"Id":1234,"Name":"Chris Rutherford"}]
But this is what it actually looks like:
"[{\"Id\":1234,\"Name\":\"Chris Rutherford\"}]"
So somewhere in your server code, you have applied JSON encoding twice. Once you correct that, HttpClient will do the right thing.
I'd quote an answer from this thread. Hope it will shed some light on how things work, read it thoroughly it enlightened me tough its not easy to find.
TypeScript only verifies the object interface at compile time. Any object that the code fetches at runtime cannot be verified by
TypeScript.
If this is the case, then things like HttpClient.Get should not
return Observable of type T. It should return Observable of type Object because
that's what is actually returned. Trying to state that it returns T
when it returns Object is misleading.
In the documentation the client's return section says this:
#return an Observable of the body as
type T.
In reality, the documentation should say:
#return an Observable of the body which
might be T. You do not get T back. If you got T back, it would
actually be T, but it's not.

JSON - Newtonsoft Access Value

How do I get the binary data of the buffer in C#?
item = {[_buffer, JVBERi0xLjMKJeLjz9MKMiAwIG9iago8PAovQ3JlYXRpb25EYXR]}
I tried this but get an error:
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var dataStream = response.Content.ReadAsStringAsync().Result;
var parsed = JObject.Parse(dataStream);
if (dataStream == null)
return HttpNotFound();
foreach (dynamic item in parsed)
{
// If user decides to save the file, this will help...
Response.AddHeader("content-disposition", "filename=" + Path.GetFileName(fileDoc));
return File(item._buffer, "application/pdf");
}
}
Assuming your raw JSON looks something like this:
{
"_buffer": "JVBERi0xLjMKJeLjz9MKMiAwIG9iago8PAovQ3JlYXRpb25EYXRlIChEOjIwMTgwMTI2MjI0ODI1LTA1JzAwJykKL01vZERhdGUgKEQ6MjAxODAxMjYyMjQ4MjUtMDUnMDAnKQovUHJvZHVjZXIgKEJDTCBlYXN5UERGIDcuMDAgXCgwMzU1XCkpCi9DcmVhdG9yIChlYXN5UERGIFNESyA3IDcuMCkKPj4KZW5kb2JqCgo4"
}
Then the value of the "_buffer" property would appear to be Base64 encoded binary. As documented in its serialization guide Json.NET supports automatically deserializing Base64 strings to byte []. Thus you can do:
var _buffer = JsonConvert.DeserializeAnonymousType(dataStream, new { _buffer = (byte[])null })._buffer;
Then pass the returned byte array to Controller.File(Byte[], String).
By using JsonConvert.DeserializeAnonymousType() you avoid the need to load your (possibly large) response into an intermediate JToken hierarchy, and also avoid the need to create an explicit, concrete type just to deserialize a single byte [] property.

accessing dynamic property when calling Action....MVC

I have an Action method that returns JSON, for brevity, I excluded code. :
public ActionResult SetMasterLocation(string masterValue)
{
json = new JavaScriptSerializer().Serialize(masterLocation);
return Json(json, JsonRequestBehavior.AllowGet);
}
I need to call this method and access the JSON string that gets returned:
var jVendors = SetMasterLocation(masterValue);
When I run it and inspect the output, I see the JSON string in a dynamic property called Data:
But if I try to access data like this, the app will not compile because the compiler says Cannot resolve symbol 'Data':
var jVendors = SetMasterLocation(masterValue);
var data = jVendors.Data;
How do I access the Data property at runtime?
Return JsonResult
return new JsonResult()
{
Data = someData,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
Then, you can access Data property of the result