Linq to Json MVC 5 not formatting as expected - c#

might seem really simple however I can't get my json to be correctly formatted from my MVC 5 controller.
My output is showing as;
[
{
"result":{
"account_color":"B43104",
"account_desc":"Welcome to XYZ",
"account_name":"XYZ",
"account_zone":1
}
},
{
"result":{
"account_color":"FF0000",
"account_desc":"Test Company",
"account_name":"Test",
"account_zone":2
}
}
]
So as you can see the level above result does not show any text so it seems like the 'result' section is getting added to a blank node
My controller is;
public IEnumerable<dynamic> Get()
{
return db.tblAccounts.Select(o => new
{
result = new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
});
}
My json formatter is;
config.Formatters.Clear();
//config.Formatters.Add(new XmlMediaTypeFormatter());
var json = new JsonMediaTypeFormatter();
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
config.Formatters.Add(json);
so it just appears that the 'result' is at a sub level it needs to be a level higher, any help would be great.

Try changing your code to look like this:
public IEnumerable<dynamic> Get()
{
return db.tblAccounts.Select(o =>
new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
);
}
This will produce an array of results instead of the nested JSON that you provided. you don't actually need the result node label do you?
EDIT:
based on your response is this what you are looking for?
public dynamic Get()
{
var accountsNode = new {
accounts = db.tblAccounts.Select(o =>
new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
).ToList()
};
return accountsNode;
}

Related

How can I use begins_with method on sort key using c# in DynamoDB

If I was to use the high level model, I might try something like this:
public async void GetBooksData()
{
GetItemRequest request = new GetItemRequest
{
TableName = "Customer",
Key = new Dictionary<string, AttributeValue>
{
{"UserName", new AttributeValue{S="a"} },
{"BookNum", new AttributeValue { S = starts_with(queryTerm)} }
}
};
try
{
var response = await client.GetItemAsync(request);
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
if (response.Item.Count > 0)
{
foreach (var item in response.Item)
{
MessageBox.Show("Value : \n" + item.Value.S);
}
}
}
}
catch (InternalServerErrorException iee)
{
MessageBox.Show(iee);
}
}
I need to use the method 'begins_with' for getting 2 items what UserName is 'a' and the BookNum are book_1 and book_2. This is possible in the high level interface in Java. As an example as to what can be done on the range key in Java:
public List<Comment> allForItemWithMinRating(String itemId, int minRating) {
Comment comment = new Comment();
comment.setItemId(itemId);
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.GE)
.withAttributeValueList(
new AttributeValue()
.withN(Integer.toString(minRating)));
DynamoDBQueryExpression<Comment> queryExpression
= new DynamoDBQueryExpression<Comment>()
.withHashKeyValues(comment)
.withRangeKeyCondition(
"rating",
condition
)
.withScanIndexForward(false);
return mapper.query(Comment.class, queryExpression);
}
In the low level interface for C# you can achieve this as so:
var requestDynamodb = new QueryRequest
{
TableName = "GroupEdEntries",
KeyConditionExpression = "partition_key = :s_Id and begins_with(sort_key, :sort)",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":s_Id", new AttributeValue { S = my_id }},
{":sort", new AttributeValue { S = sort_key_starts_with }}
},
ConsistentRead = true
};
var results = await client.QueryAsync(requestDynamodb);
where the keys are called partition_key and sort_key. However, this returns the results as attribute values, which then need to be converted into POCOs one property at a time. It requires using reflection and is made more complicated using converters. It seems strange that this fundamental functionality (as well as other functionality) isn't supported in the C# SDK.
I ended up using reflection to create the tables based on the attributes, when this is also supported by default in Java. Am I missing a high level API for C#?
It's a bit of a different syntax and I can't find it documented anywhere (other than in code comments), but this works for me:
string partition_key = "123";
string sort_key_starts_with = "#type"
List<object> queryVal = new List<object>();
queryVal.Add(sort_key_starts_with);
var myQuery = context.QueryAsync<GroupEdEntry>(partition_key, QueryOperator.BeginsWith, queryVal);
var queryResult = await myQuery.GetRemainingAsync();

how to form comma separated string from bson array using asp.net core 2.2?

I have an api based on asp.net core 2.2 in which i am building up an array of ips(strings type) like this
[HttpGet ("{nsp}/geolocation")]
[ResponseCache (Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public async Task<dynamic> getLocation (string nsp) {
nsp = "/"+nsp;
// string ipInfoBaseUrl = "http://ip-api.com/json/";
string baseUrl = "http://ip-api.com/batch";
// string userIpAddress = "197.157.194.90";
// string ipUrl = ipInfoBaseUrl + userIpAddress;
// var client = _httpClientFactory.CreateClient();
// var result = await client.PostAsync(baseUrl,new StringContent(JsonConvert.SerializeObject(finals), System.Text.Encoding.UTF8, "application/json"));
// // var final = Newtonsoft.Json.JsonConvert.DeserializeObject<UserLocation>(result);
// Console.WriteLine(finals+" --result-----");
// return Ok(result);
var match = new BsonDocument ();
var group = new BsonDocument ();
var project = new BsonDocument ();
var sort = new BsonDocument ();
var addFields = new BsonDocument ();
var pipeline = new [] { new BsonDocument () };
/* #Aggregation : Stage-1 */
match = new BsonDocument ("$match",
new BsonDocument {
{
"nsp" , nsp
}
});
/* #Aggregation : Stage-2 */
group = new BsonDocument("$group",
new BsonDocument
{ {
"_id", "null"
},
{ "geoLocations",
new BsonDocument("$addToSet", "$visitor.ip")
}
});
/* #Aggregation : Stage-3 */
project = new BsonDocument ("$project", new BsonDocument { { "_id", 0 }});
pipeline = new [] { match, group,project};
var list = await DbService.tickets.AggregateAsync<BsonDocument> (pipeline, new AggregateOptions { UseCursor = true, BatchSize = batchCount });
while (await list.MoveNextAsync ()) {
var list_real = new List<BsonValue> ();
foreach (var data in list.Current.ToArray ()) {
list_real.Add (data);
}
return list_real.ToJson ();
}
return new BsonArray ().ToJson ();
}
It is returning result like this
[
{
" geoLocations": [
"122.8.208.9",
"196.62.107.243",
"182.188.38.219",
"39.50.244.198",
"39.51.40.251",
"103.20.134.56",
"103.228.156.83",
"202.143.125.21",
"196.62.151.47",
"45.116.232.50",
"39.57.128.75",
"103.18.8.60",
"202.143.125.20",
"182.190.252.96",
"119.153.56.2",
"46.101.89.227",
"196.194.172.211",
"192.168.20.186",
"64.233.173.146",
"104.236.195.147",
"39.50.156.242",
"103.255.5.58"
]
}
]
How can i get comma separated string from this result like
"111.92.158.82","202.142.168.162","122.8.157.172",.....
From very first i am getting all ips from all documents from my collection and forming an array of ips.But my ultimate goal is to form a comma separated string from that array because i have to pass that comma separated string of ips into an api to get ips locations.
I am using asp.net core and c#. How can i achieve this?
Assuming you want a single comma-separated result string containing all IP addresses, replace the method signature with IEnumerable<string>, and replace the bottom of the method with. Just use whatever you need for your result and get rid of the rest.
var list = await DbService.tickets.AggregateAsync<BsonDocument> (pipeline,
new AggregateOptions
{
UseCursor = true,
BatchSize = batchCount
});
var result = new List<string>();
while (await list.MoveNextAsync())
result.AddRange(list.Current.Cast<string>());
return string.Join(',', result);
I'm not sure why you're doing everything with BsonDocuments, you can just iterate over the data directly and return strings.
Also, consider upgrading to .NET Core 3, which you can then use C# 8's async enumerable. You'll also be able to use the new JSON functionality built-in .NET Core 3.
This will return:
"122.8.208.9,196.62.107.243,182.188.38.219,<all the rest>"

how to build and return a result from a webapi controler

So I have put together a group of stored procedure calls in my web api controller. Now I need to return the combined results. Javascript is as simple as something like this:
var result = [{
objectResult: value
},{
arryResult1:[value]
},{
arryResult2:[value]
}]
but it c# it would require a class that contains 2 lists and a object? then return that as a list? this is where i am kind of lost.
[HttpPost]
[Route("builderContact")]
public List<usp_get_builder_contact_data_Result> GetBuilderContact(parameter parameter)
{
object[] parameters = { parameter.company_id, parameter.subdivision_id };
var builderContact = db.Database.SqlQuery<usp_get_builder_contact_data_Result>("sandbox.usp_get_builder_contact_data {0},{1}",
parameters).First();
var floorplanDataResult = db.Database.SqlQuery<usp_get_floorplan_data_Result>("sandbox.usp_get_floorplan_data {0},{1}",
parameters).ToList();
var floorplanRelatedResult = db.Database.SqlQuery<usp_get_floorplan_related_sections_Result>("sandbox.usp_get_floorplan_related_sections {0},{1}",
parameters).ToList();
return ?;
}
update for answer
[HttpPost]
[Route("bigEnchilada")]
public List<object> GetBuilderContact(parameter parameter)
{
object[] parameters = { parameter.company_id, parameter.subdivision_id };
var builderContact = db.Database.SqlQuery<usp_get_builder_contact_data_Result>("sandbox.usp_get_builder_contact_data {0},{1}",
parameters).First();
var floorplanDataResult = db.Database.SqlQuery<usp_get_floorplan_data_Result>("sandbox.usp_get_floorplan_data {0},{1}",
parameters).ToList();
var floorplanRelatedResult = db.Database.SqlQuery<usp_get_floorplan_related_sections_Result>("sandbox.usp_get_floorplan_related_sections {0},{1}",
parameters).ToList();
return (new object[] {
new object { builderContact = builderContact },
new object { floorplanDataResult = floorplanDataResult },
new object { floorplanRelatedResult = floorplanRelatedResult }
}).ToList();
}
If you want it to match exactly what you have in Javascript, then change the return type to List<object> and return:
return new List<object> {
new { objectResult = builderContact },
new { arryResult1 = floorplanDataResult },
new { arryResult2 = floorplanRelatedResult }
};
IMHO in this context the following model would be much more suited (if you can change it, that is):
var result = {
objectResult: value,
arryResult1: [value],
arryResult2: [value]
}
In which case you would set the return type to object and return:
return new {
objectResult = builderContact,
arryResult1 = floorplanDataResult,
arryResult2 = floorplanRelatedResult
};
A tiny bit nicer, no?
You can simply concat them all ?
List<object> allItems = (
from x in floorplanDataResult.ToList() select new object()
).ToList().Concat(
from y in floorplanRelatedResult.ToList() select new object()
).ToList();
return allItems;
I don't know if your client expects them in the same payload though...

Testing JSON Results from MVC 4 C# Controller

So I have a controller that returns json to my views that I need to test. I have tried using reflection with a dynamic data type to access a sub property of a list but I keep getting something similar to 'unable to cast' errors. Basically I have a list within a list that I want to access and verify things about but I can't access it. Has anyone tested json returned from their controller before in MVC4 and have advice?
Code:
// arrange
var repositoryMock = new Mock<IEdwConsoleRepository>();
var date = -1;
var fromDate = DateTime.Today.AddDays(date);
EtlTableHistory[] tableHistories =
{
new EtlTableHistory
{
Table = new Table(),
RelatedStatus = new BatchStatus(),
BatchId = 1
}
};
EtlBatchHistory[] batchHistories = { new EtlBatchHistory
{
Status = new BatchStatus(),
TableHistories = tableHistories
} };
repositoryMock.Setup(repository => repository.GetBatchHistories(fromDate)).Returns((IEnumerable<EtlBatchHistory>)batchHistories);
var controller = new EdwController(new Mock<IEdwSecurityService>().Object, repositoryMock.Object);
// act
ActionResult result = controller.BatchHistories(1);
// assert
Assert.IsInstanceOfType(result, typeof(JsonResult), "Result type was incorrect");
var jsonResult = (JsonResult)result;
var resultData = (dynamic)jsonResult.Data;
var returnedHistories = resultData.GetType().GetProperty("batchHistories").GetValue(resultData, null);
var returnedTableHistoriesType = returnedHistories.GetType();
Assert.AreEqual(1, returnedTableHistoriesType.GetProperty("Count").GetValue(returnedHistories, null), "Wrong number of logs in result data");
Here's an example:
Controller:
[HttpPost]
public JsonResult AddNewImage(string buildingID, string desc)
{
ReturnArgs r = new ReturnArgs();
if (Request.Files.Count == 0)
{
r.Status = 102;
r.Message = "Oops! That image did not seem to make it!";
return Json(r);
}
if (!repo.BuildingExists(buildingID))
{
r.Status = 101;
r.Message = "Oops! That building can't be found!";
return Json(r);
}
SaveImages(buildingID, desc);
r.Status = 200;
r.Message = repo.GetBuildingByID(buildingID).images.Last().ImageID;
return Json(r);
}
public class ReturnArgs
{
public int Status { get; set; }
public string Message { get; set; }
}
Test:
[TestMethod]
public void AddNewImage_Returns_Error_On_No_File()
{
// Arrange
ExtendedBuilding bld = repo.GetBuildings()[0];
string ID = bld.Id;
var fakeContext = new Mock<HttpContextBase>();
var fakeRequest = new Mock<HttpRequestBase>();
fakeContext.Setup(cont => cont.Request).Returns(fakeRequest.Object);
fakeRequest.Setup(req => req.Files.Count).Returns(0);
BuildingController noFileController = new BuildingController(repo);
noFileController.ControllerContext = new ControllerContext(fakeContext.Object, new System.Web.Routing.RouteData(), noFileController);
// Act
var result = noFileController.AddNewImage(ID, "empty");
ReturnArgs data = (ReturnArgs)(result as JsonResult).Data;
// Assert
Assert.IsTrue(data.Status == 102);
}
In your example it looks to me that the problem is here:
var resultData = (dynamic)jsonResult.Data;
var returnedHistories = resultData.GetType().GetProperty("batchHistories").GetValue(resultData, null);
The resultData object would be the exact type of the object that you returned in your action. So if you did something like:
List<String> list = repo.GetList();
return Json(list);
Then your resultData would be of type:
List<String>
Try making sure that you are returning your Object using the Json(obj) function.
You can deserialize your Json into a dynamic object and then ask for the property you want
Example:
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var propertyValue = obj.MyProperty; //Ask for the right property
You can add Json serializer from Nuget Json.Net package.

How to set the static text into JsonResult?

I found the following code example (from Telerik ) that I'm trying to understand.
What I need to do is somehow to set static text into JsonResult (e.g.Text ="Abc" and Value="123")
public ActionResult _AjaxLoading(string text)
{
Thread.Sleep(1000);
using ( var nw = new NorthwindDataContext() )
{
var products = nw.Products.AsQueryable();
if ( text.HasValue() )
{
products = products.Where((p) => p.ProductName.StartsWith(text));
}
return new JsonResult { Data = new SelectList(products.ToList(), "ProductID", "ProductName") };
}
}
public ActionResult _AjaxLoading(string text
{
var data = new { Text= "123", Value= "Abc"};
return Json(data, JsonRequestBehavior.AllowGet);
}
If it is an HTTPGet method, You should specify JsonRequestBehavior.AllowGet as second parameter to return JSon data from a GET method
It looks like you are in need of this:
return new JsonResult { Data = new { Text="Abc", Value="123", Produtcs= new SelectList(products.ToList(), "ProductID", "ProductName") }};
Is this what you are looking for
return new JsonResult { Text = "Abc", Value="123" };
If you want to add a new element to the drop down at start then
var editedProducts = new SelectList(products.ToList(), "ProductID","ProductName" ).ToList();
editedProducts.insert(0, new SelectListItem() { Value = "123", Text = "Abc" });
return new JsonResult { Data = editedProducts };

Categories

Resources