I am looking at trying to use a Linq query to determine if the following JSON is true if it contains a product that has a SKU of 12345 OR a TypeCode of "C".
"[{\"SKU\":\"12345\",\"Description\":\"Test Part 12345\",\"TypeCode\":\"A\",\"Cost\":24.99},{\"SKU\":\"54567\",\"Description\":\"Test Part 54567\",\"TypeCode\":\"B\",\"Cost\":9.99},{\"SKU\":\"QWZ2342\",\"Description\":\"Test Part QWZ2342\",\"TypeCode\":\"C\",\"Cost\":19.99}]"
I have been working with the Json.net (http://james.newtonking.com/projects/json-net.aspx)
At first, you have to deserialize the JSON into a C# object, lets say Product.
class Product
{
public int SKU { get; set; }
public string Desc { get; set; }
public string TypeCode { get; set; }
public decimal Cost { get; set; }
}
then, using .NET's JavaScriptSerializer (System.Web.Script.Serialization), convert the json string to become List of your custom objects.
string json = "[{\"SKU\":\"12345\",\"Description\":\"Test Part 12345\",\"TypeCode\":\"A\",\"Cost\":24.99},{\"SKU\":\"54567\",\"Description\":\"Test Part 54567\",\"TypeCode\":\"B\",\"Cost\":9.99},{\"SKU\":\"QWZ2342\",\"Description\":\"Test Part QWZ2342\",\"TypeCode\":\"C\",\"Cost\":19.99}]"
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
List<Product> productList = new List<Product>();
productList = jsonSerializer.Deserialize<List<Product>>(json);
the last step, using simple linq query, you cant check whether your product exist on the list:
var Found = from o in productList
where o.SKU == 12345
select o.SKU;
if (Found.Count() > 0)
return true;
else
return false;
Related
I have this data class for storing data parsed from JSON formatted web data (using Json.NET library):
[Serializable()]
public class MovieData
{
public string FilePath { get; set; }
public string OrigName { get; set; }
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "year")]
public int Year { get; set; }
[JsonProperty(PropertyName = "genres")]
public string[] Genres { get; set; }
}
The next class is for to be able serialize collection of MovieData objects:
[Serializable()]
[XmlRoot("MovieCollection")]
public class MovieCollection
{
[XmlArray("Movies")]
[XmlArrayItem("Movie", typeof(Movie))]
public List<Movie> movies = new List<MovieData>();
}
Finally, I need to bind such a collection of MovieData to DataGridView (or single MovieData object to DataGridViewRow), like:
dgvMovies.DataSource = movieCollection.movies;
Is it possible to bind it without hard-setting of DataGridViewColumn collection before? Native data types are not problem, problem is string[] Genres array, which I need to format it in DataGridView in some way, like:
"genres[0] / genres[0] / ... genres[n]"
At this moment, while simply setting DataSource to collectin, this array is ignored (is not displayed anyway).
In MovieData class, you can add the following property :
public string GenresAsString
{
get { return String.Join("/", Genres); }
set { Genres = value.Split('/'); }
}
You will surely have to improve the setter to make it more resilient (triming, removing empty genres) if you plan to let the user modify this value.
Else you can remove the setter.
I managed to create an ApiController retrieving data from my repositories, and populating a grid in my view through Bootgrid with Ajax. This is an example of request data sent to Api's Action, given by their Docs here (look for POST Body Request tab):
current=1&rowCount=10&sort[sender]=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
Here is an example URL:
http://localhost/api/SomeController?current=1&rowCount=10&sort%5BName%5D=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
I created two Helper classes to handle data I must return as response, and sort data (as it's an array):
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
public class BootgridResponseData<T> where T: class
{
public int current { get; set; } // current page
public int rowCount { get; set; } // rows per page
public IEnumerable<T> rows { get; set; } // items
public int total { get; set; } // total rows for whole query
}
Therefore, my action is as follow:
public BootgridResponseData<SomeViewModel> Get(int current, int rowCount, List<SortData> sort, string searchPhrase, string id)
{
// get items and return a bootgrid response data with them...
}
The method is invoked and all parameters come with data properly, except sort, which is always null.
What kind of parameter should I expect for this? I also tried to put object but it comes null anyway.
After learning a bit more, I saw Bootgrid has a requestHandler setting which allows you to manipulate data sent to server.
I did it in my javascript like this:
var grid = $("#my-grid").bootgrid({
ajax: true,
rowCount: 10,
ajaxSettings: {
method: "POST",
cache: true
},
requestHandler: function (request) {
// Scan the original sort object from Bootgrid...
// and populate an array of "SortData"...
request.sortItems = [];
if (request.sort == null)
return request;
for (var property in request.sort) {
if (request.sort.hasOwnProperty(property)) {
request.sortItems.push({ Field: property, Type: request.sort[property] });
}
}
return request;
},
url: "/api/FooApi"
});
Then I created my post action in API like this:
public class FooApiController : ApiController
{
[HttpPost]
public BootgridResponseData<FooModel> Get(BootgridRequestData model)
{
// This would come from some data store, using the request params...
// I use PagedList to make pagination easier...
IPagedList<FooModel> itemsPaged = store.GetPagedFoo();
// Then return the response with data...
return new BootgridResponseData<FooModel>()
{
current = model.current,
rowCount = model.rowCount,
rows = itemsPaged,
total = itemsPaged.TotalItemCount
};
}
}
The BootgridResponseData has already been shown in my question. I just added a BootgridRequestData which the following structure:
public class BootgridRequestData
{
public int current { get; set; }
public int rowCount { get; set; }
public string searchPhrase { get; set; }
public IEnumerable<SortData> sortItems { get; set; }
}
Then I could even use my original SortData helper class:
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
I've struggled with this as well. You are overthinking it. It's nice to create simple models to handle the post call from jquery-bootgrid, but you can also just use simple parameters in the post method. As for the sort, it looks like a Key-Value pair, but that doesn't serialize properly.
I ended up trying a Dictionary object and it works.
Here is my signature:
[HttpPost]
public async Task<ActionResult> GetActiveDogs(int? current, int? rowCount,
Dictionary<string, string> sort, string searchPhrase = null)
I had the same problem passing the sort options to my webservice. The Dictionary object did not solve my problem either.
To solve it, I created a class holding string properties for each field I wanted to pass through the bootgrid sort options. See code excerpt
class TestSort
{
public string field1 { get; set; }
public string field2 { get; set; }
...
}
I use this class as the sort options parameter in my webservice. All fields in this class that are referred to by the bootgrid options are set to "ASC" or "DESC". The others remain null.
I added an 'orderBy' property to this class that returns an orderby clause for the fields that are not null.
Approch1.
consider you have table with columns "col1, col2, col3, ...".
you can use:
public ActionType Get(int current, int rowCount, Sort sort, string searchPhrase) {
//sort.col1 == 'asc' (consider sorted by col1 in ascending order)
}
public class Sort
{
public string col1 { get; set; }
public string col2 { get; set; }
public string col3 { get; set; }
//... other columns
}
Approach 2.
You can use remove you parameters and parse request data manually. i used post here instead of get.
[HttpPost]
public object Post(){
string jsonContent = Request.Content.ReadAsStringAsync().Result;
Dictionary<string, string> keyvalues = new Dictionary<string, string>();
string[] keyvalue_strings = jsonContent.Split('&');
string sort_column = "";
string sort_direction = "";
for (var i = 0; i< keyvalue_strings.Length; i++)
{
var a = keyvalue_strings[i].Split('=');
a[0] = a[0].Replace("%5B", "[").Replace("%5D", "]");
keyvalues.Add(a[0], (a[1]));
if (a[0].Contains("sort"))
{
sort_column = a[0].Replace("sort[", "").Replace("]", "");
sort_direction = a[1];
}
}
//now you have keyvalues, sort_column, sort_direction.
//...
}
I have a class as below
public class Person
{
public string Name { get; set; }
[DisplayName ("Please Enter Your Age")]
public int Age { get; set; }
public string Sex { get; set; }
}
I serialized this object to Json using json() of MVC3, but the DisplayName attribute is ignored. I get the json as
"*{"Name":"Person Name","**Age**":28,"Sex":"Male"}*"
Actually i was expecting
"*{"Name":"Person Name","**Please Enter Your Age**":28,"Sex":"Male"}*"
Code converts the object to json
[HttpGet]
public JsonResult JsonTest()
{
Person person = new Person();
person.Age = 28;
person.Name = "Person Name";
person.Sex = "Male";
return (Json(person, JsonRequestBehavior.AllowGet));
}
Any help would be appreciated!!!
You can use the DataContractJsonSerializer to give different names to your properties by using the [DataMember(Name = "myOwnName")] data annotation. Or write your own serializer.
Example can be found here.
Internally the Json method uses the JavaScriptSerializer class to serialize the class into a JSON string. It doesn't allow you to change property names. I guess you will have to roll your own JSON serialization routine. The question is: why do you need that?
In my test vb.net MVC web app, I have this json....
Public Class Person
Public Property Name As String
Public Property Age As Byte
Public Sub New(name As String, age As Byte)
Me.Name = name
Me.Age = age
End Sub
End Class
Function GetPerson() As JsonResult
Dim p As New Person("John Doe", 50)
Return Json(p, JsonRequestBehavior.AllowGet)
End Function
And in Monotouch I've got this...
JsonObject j;
Uri address = new Uri("http://mysite/home/GetPerson");
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create (address);
using (HttpWebResponse httpRes = (HttpWebResponse)httpReq.GetResponse ()) {
Stream s = httpRes.GetResponseStream ();
j = (JsonObject)JsonObject.Load (s);
}
And this class...
Public Class Person {
Public string Name { get; set; }
Public byte Age { get; set; }
}
How do I parse the JsonObject j into class of Person? .. I hoped for something like Person p = (Person)j.value;
Thanks!
Mojo
First, I would use int for Age. But assuming a JSON Structure like:
{
"Name" : "John Doe",
"Age" : 100,
}
If you wanted to use the baked in System.Json stuff:
var person = new Person()
var obj = JsonObject.Parse(json);
person.Name = obj["Name"].ToString();
person.Age = (int)obj["Age"];
I would HIGHLY recommend using ServiceStack.Text though, it's a highly optimized extremely fast library for consuming JSON with compatibility with both MonoTouch and Mono for Android...out of the box!
You can check out the the API for consuming JSON with ServiceStack here.
Even if this question is now old, here is the solution I use.
With MonoTouch, you can use .net Json serialization mechanism based on DataContract.
[DataContract]
Public Class Person {
[DataMember]
Public string Name { get; set; }
[DataMember]
Public byte Age { get; set; }
}
and use the DataContractJsonSerializer (found in System.Runtime.Serialization.Json)
Stream stream = httpRes.GetResponseStream ();
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(Person));
Person person = (Person)jsSerializer.ReadObject(stream);
This way, the code is WCF compliant and work flawless on ms.net platform, mono and monotouch.
it will give me error Unable to cast object of type.
public class CusInfomration
{
public string CustomerName { get; set; }
public string CustomerID { get; set; }
public string OrderDate { get; set; }
public string OrderId { get; set; }
}
var CustomerFromWash = from p in _NorthWindDataContext.Customers
join q in _NorthWindDataContext.Orders
on p.CustomerID equals q.CustomerID
where p.Region == "WA"
select new
{
CustomerName =Convert.ToString(p.CompanyName),
CustomerID = Convert.ToString(p.CustomerID),
OrderId = Convert.ToString(q.OrderID),
OrderDate = Convert.ToString(q.OrderDate),
};
List<cusinfomration> lstCust = (List<cusinfomration>)CustomerFromWash;
That LINQ query returns an IQueryable<T>. IQueryable<T> is an interface and List<T> does not implement it, so there is no way that the underlying, concrete implementation is a List<T> (it does however implement IEnumerable<T>, so a cast to that would be valid). Even if it were it would not be a safe cast to make as the .NET folks may want to change out the underlying implementation someday and your cast would be broken. Not a good idea even if it did work initially.
You can call ToList() on the return value of the LINQ query:
var CustomerFromWash = (from p in _NorthWindDataContext.Customers
join q in _NorthWindDataContext.Orders
on p.CustomerID equals q.CustomerID
where p.Region == "WA"
select new
{
CustomerName =Convert.ToString(p.CompanyName),
CustomerID = Convert.ToString(p.CustomerID),
OrderId = Convert.ToString(q.OrderID),
OrderDate = Convert.ToString(q.OrderDate),
}).ToList();
Even then though you are selecting a collection of anonymous types, not CustInformation objects. If you want CustInformation objects to be returned then you will need to:
select new CustInformation
{
// set properties here
}