Hardcoded JsonpResult values - c#

I have the following controller action:
[HttpGet]
public JsonpResult getTestValues(int? entityId, int? id)
{
return JsonpResult(WebResult.Success());
}
I have a AJAX call that invokes this controller and has to parse the data object returned. How can I modify the above to return the following?
{"data":[{"T1":"t1#test.com","T11":"1234-1234-1234-1234"},
{"T2":"t2#test.com","T22":"1234-1234-1234-1234"}]}
I need this for testing the UI framework that I am working on. Any suggestions on how to return the above hardcoded data?

Yes, you can do this using an anonymous type:
return JsonpResult {
Data = new {
data = new List<object> {
new { T1 = "t1#test.com", T11 = "1234-1234-1234-1234" },
new { T2 = "t2#test.com", T22 = "1234-1234-1234-1234" },
}
}
};

Related

Dynamic Query Builder for ASP.Net-MVC - Using jQuery QueryBuilder, DataTables, and dynamic-linq-query-builder

I'm trying to accomplish the following Tasks:
Create a visual expression/ query builder for ASP.NET-MVC.
Pass the resulting query to DataTables.
This question is about Task 1 as that's where I'm stuck. I have posted Task 2 to provide more background information.
To achieve Task 1 I'm using the jQuery QueryBuilder - a jQuery plugin to create user friendly queries. On the QueryBuilder website there is a listing for .NET under the Backends section (https://querybuilder.js.org/#backends). They recommend to use the dynamic-linq-query-builder by Castle-it (https://github.com/castle-it/dynamic-linq-query-builder).
Here is my issue:
The dynamic-linq-query-builder all seems to be built with static classes. I want to retrieve the data from my database but from my research online I'm not able to initiate a dbcontext within a static class.
Dynamic-linq-query provides a PersonBuilder class to deserialize a JSON data and they include a TestData string:
public static class PersonBuilder
{
public static List<PersonRecord> GetPeople()
{
var result = new List<PersonRecord>();
var testData = TestData;
var personRecords = JsonConvert.DeserializeObject<List<PersonRecord>>(testData);
return personRecords;
}
private static string TestData
{
get
{
return #"
[
{
""FirstName"": ""Jane"",
""LastName"": ""Hansen"",
""Birthday"": ""1969-12-31T16:00:00-08:00"",
""Address"": ""P.O. Box 492, 4607 Tempus, Rd."",
""City"": ""Polatlı"",
""State"": ""Ankara"",
...
...
...
Then in the HomeController they are using the following to filter the query:
[HttpPost]
public JsonResult Index(FilterRule obj)
{
var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var people = PersonBuilder.GetPeople().BuildQuery(obj).ToList();
return Json(people);
}
And here is their QueryBuilder implementation and jQuery logic to read out the results.
<script type="text/javascript">
$(function() {
// Handler for .ready() called.
var tableData = [];
var filterDefinition = #Html.Raw(ViewBag.FilterDefinition);
var customFilters = {
condition: 'AND',
rules: []
};
var jqueryQueryBuilder = $('#jquery-query-builder');
var jqueryQueryBuilderDom = jqueryQueryBuilder.queryBuilder({
plugins: ['bt-tooltip-errors', 'filter-description'],
//allow_groups: 0,
allow_empty: true,
filters: filterDefinition,
rules: customFilters,
icons: {
add_group: 'fa fa-plus-square',
add_rule: 'fa fa-plus-circle',
remove_group: 'fa fa-minus-square',
remove_rule: 'fa fa-minus-circle',
error: 'fa fa-exclamation-triangle',
sortable: 'fa fa-exclamation-triangle'
}
});
var convertArraysToCommaDelimited = function(obj) {
if (obj != null) {
if (obj.hasOwnProperty("value")) {
if( Object.prototype.toString.call( obj.value ) === '[object Array]' ) {
obj.value = obj.value.join(", ");
}
}
if (obj.hasOwnProperty("rules") && obj.rules != null) {
for (var i = 0; i < obj.rules.length; i++) {
convertArraysToCommaDelimited(obj.rules[i]);
}
}
}
}
var getRules = function() {
try {
var res = jqueryQueryBuilder.queryBuilder('getRules');
convertArraysToCommaDelimited(res);
return res;
} catch (ex) {
//console.log(ex);
return null;
}
}
var buildTable;
var filterData = function() {
$.ajax({
type: 'POST',
url: "../Home/Index",
data: JSON.stringify(getRules()),
success: function (returnPayload) {
tableData = returnPayload;
buildTable();
console && console.log ("request succeeded");
},
error: function (xhr, ajaxOptions, thrownError) {
console && console.log ("request failed");
},
dataType: "json",
contentType: "application/json",
processData: false,
async: true
});
}
$('#applyFilter').on('click', function() {
filterData();
});
buildTable = function() {
var tbody = $('#data-table tbody'),
props = ["FirstName", "LastName", "Birthday", "Age", "Address", "City", "State", "ZipCode"];
tbody.empty();
$.each(tableData, function(i, reservation) {
var tr = $('<tr>');
$.each(props, function(i, prop) {
$('<td>').html(reservation[prop]).appendTo(tr);
});
tbody.append(tr);
});
};
filterData();
});
</script>
You'll notice that they've created a buildTable function. Later I would like to replace this with a DataTable implementation.
What I've tried:
I have tried to initiate a dbcontext with LINQ in the PersonBuilder class. The issue is that this class was static. I simply removed the static definition of the PersonBuilder class. Here is my implementation:
public List<PersonRecord> GetPeople()
{
IQueryable<PersonRecord> query = DbContext.PersonRecord;
var data = query.Select(asset => new Asset
{
data1 = PersonRecord.data1,
data2 = PersonRecord.data2,
...
...
}).ToList();
return data;
}
The issue I'm experiencing is that the HomeController is now throwing the following error:
CS0120: An object reference is required for the nonstatic field,
method, or property 'member'
At the following line:
var people = PersonBuilder.GetPeople().BuildQuery(obj).ToList();
Not quite sure how to get around this since it seems the entire library is built with static classes?
What do you guys think?
The main problem is that you're defining GetPeople() as non-static method inside PersonBuilder class which marked as static. As noted in MSDN documentation, static classes must contain only static members, including static methods (see the reason here).
The CS0120 error indicates that you should use either static class with static method, or non-static class' instantiated constructor as object. If you want to use non-static method, the class should not marked as static, also the class constructor must be instantiated first before the method can be accessed:
public class PersonBuilder
{
public List<PersonRecord> GetPeople()
{
IQueryable<PersonRecord> query = DbContext.PersonRecord;
var data = query.Select(asset => new Asset
{
data1 = PersonRecord.data1,
data2 = PersonRecord.data2,
// other stuff
}).ToList();
return data;
}
}
Usage
[HttpPost]
public JsonResult Index(FilterRule obj)
{
var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var personBuilder = new PersonBuilder(); // add constructor initialization first
var people = personBuilder.GetPeople().BuildQuery(obj).ToList();
return Json(people);
}
Related issue:
How shouldi avoid the CS0120 error in my code?

How do I pass anonymous lists to calling method from static method?

public JsonResult GetReport(string reportSelected, string firstDateGiven)
{
_context = new ReportDB();
var theResults =
miPolicyTransactions.Select(
x =>
new
{
PolicyReference = x.PolicyReference,
TransactionType = x.TransactionType
...
}).ToList();
var theadColumns = new[]
{
new {columnName = "Policy Reference"},
new {columnName = "Transaction Code"}
...
}.ToList();
return Json(new { data = theResults, columns= theadColumns }, JsonRequestBehavior.AllowGet);
}
Above is what I started with which works, but I have used a dictionary func to simplify the calls and create other content.
private Dictionary<string, Func<IReportDB, string, JsonResult>> functions = new Dictionary<string, Func<IReportDB, string, JsonResult>>
{
{ "New Business by Agent last 3 Months(set)", NewBusinessAgentLast3Month},
{ "New Business by Agent last 7 days (set)", SomeOtherMethodName}
};
private static JsonResult NewBusinessAgentLast3Month(IReportDB context, string parameters)
{
_context = new ReportDB();
var theResults =
miPolicyTransactions.Select(
x =>
new
{
PolicyReference = x.PolicyReference,
TransactionType = x.TransactionType
...
}).ToList();
var theadColumns = new[]
{
new {columnName = "Policy Reference"},
new {columnName = "Transaction Code"}
...
}.ToList();
return ??????????????????????????
I cant return a Json object as I get an error
An object reference is required for the non static field, method,
property. Cannot access non-static Json in static context.
Can I avoid creating a concrete type with a concrete type lists for each , but still pass both anonymous lists to the calling method to in turn by returned as a JsonResult which is used in my Jquery file? Would you use List or is there another way??
You should change your functions (like NewBusinessAgentLast3Month) to return object. You should then pass this value to the Controller.Json method which will create a JsonResult that you can return from the controller.
The question marks in your code should be replaced with the same anonymous type you used before your refactoring.

Using JArray for serializing data from database in WebAPI (C#)

I want to achieve the following JSON data:
[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
Currently I'm getting this result of JSON data:
{
"groups":[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
}
Here is the code of the Controller:
public dynamic GetGroups()
{
JObject o = JObject.FromObject(new
{
groups = from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}
});
return o;
/*Here I've tried to get JSON data as array without the Property "groups"*/
//JArray a = new JArray(
// from g in db.QR_Groups
// select new JValue(g));
//return a;
}
Can anyone tell me how to retrieve the JSON data as per the first JSON example above?
And is the type "dynamic" good practice for the method?
First of all there is no need to do serialization manually. ASP.Net WebApi MediaFormatters are going to take care of it based on the Request Content-Type. So Create a class as shown below.
public class Group
{
public string name { get; set; }
public string code { get; set; }
}
Then your Web API endpoint should be -
[HttpGet]
public HttpResponseMessage GetCountries()
{
List<Group> groups = (from g in db.QR_Groups
select new Group
{
name = g.name,
code = g.code
}).ToList();
return Request.CreateResponse(HttpStatusCode.OK, groups);
}
And when I make a Fiddler request, I was able to get the output which you are interested -
Try this one:
var json = JsonConvert.SerializeObject(from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
});
And is the type "dynamic" good practice for the method?
no, it's not best practise. Better one is to create new class

Lose MongoDB ObjectId value when passing through Actions

In my MVC Controller, I have this code (after adding an object, I redirect user to edit that object):
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Add()
{
MongoDataContext dc = new MongoDataContext();
var model = new ModelObj();
dc.Models.Insert(model);
return this.RedirectToAction("Edit", new { pId = model.Id, });
}
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Edit(ObjectId? pId)
{
MongoDataContext dc = new MongoDataContext();
var model = dc.Models.FindOneById(pId);
if (model == null)
{
Session["error"] = "No model with this ID found.";
return this.RedirectToAction("");
}
return this.View(model);
}
However, pId is always null, making the FindOneById always return null. I have debugged and made sure that the Id had value when passing from Add Action. Moreover, I tried adding a testing parameter:
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Add()
{
MongoDataContext dc = new MongoDataContext();
var model = new ModelObj();
dc.Models.Insert(model);
return this.RedirectToAction("Edit", new { pId = model.Id, test = 10 });
}
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Edit(ObjectId? pId, int? test)
{
MongoDataContext dc = new MongoDataContext();
var model = dc.Models.FindOneById(pId);
if (model == null)
{
Session["error"] = "No model with this ID found.";
return this.RedirectToAction("");
}
return this.View(model);
}
When I debug, I received the test parameter in Edit Action with value of 10 correctly, but pId is null. Please tell me what I did wrong, and how to solve this problem?
I would suspect that the ObjectId is not serializing/deserializing correctly. Given that it doesn't make for a great WebAPI anyway, I generally use a string and convert within the method to an ObjectId via the Parse method (or use TryParse):
public ActionResult Edit(string id, int? test)
{
// might need some error handling here .... :)
var oId = ObjectId.Parse(id);
}
You can use ToString on the ObjectId to convert it to a string for calling:
var pId = model.Id.ToString();

Json serialization in asp.net mvc c#

public ActionResult About()
{
List listStores = new List();
listStores = this.GetResults(“param”);
return Json(listStores, “Stores”, JsonRequestBehavior.AllowGet);
}
Using the above code I am able to get the below result :
[{"id":"1","name":"Store1","cust_name":"custname1","telephone":"1233455555",
"email":"abc#ac.com","geo":{"latitude":"12.9876","longitude":"122.376237"}},
{"id":"2","name":"Store2","cust_name":"custname2","telephone":"1556454",
"email":"nfnf#ac.com","geo":{"latitude":"12.9876","longitude":"122.376237"}},
how would I able to get the result in below format? Would need stores at the beginning of the result.
{
"stores" : [
{"id":"1","name":"Store1","cust_name":"custname1","telephone":"1233455555",
"email":"abc#ac.com",
"geo":{"latitude":"12.9876","longitude":"122.376237"}},
{"id":"2","name":"Store2","cust_name":"custname2","telephone":"1556454",
"email":"nfnf#ac.com","geo":{"latitude":"12.9876","longitude":"122.376237"
}} ] }
Try
return Json(new { stores = listStores }, JsonRequestBehavior.AllowGet);
In the above statement, you're creating a new object with a property named "stores", which is then populated with the array of items from the list.
You could also use a class, something defined like so:
[DataContract]
public class StoreListJsonDTO
{
[DataMember(Name = "stores")]
public List Stores { get; set; }
public StoreListJsonDTO(List storeList)
{
this.Stores = storeList;
}
}
Then in your code, you'd do:
var result = new StoreListJsonDTO(listStores);
return Json(result, JsonRequestBehavior.AllowGet);

Categories