How to parse a json in MVC view - asp.net-mvc

I am getting the values of some datatypes in umbraco to my MVC view in cshtml I am getting a result in JSON how will I parse the JSON to bind it to a drop down list. What are the possible methods to do this. I have installed NetonSoft JSON in project also
if (home.GetProperty("residentsLogin") != null && !string.IsNullOrEmpty(home.GetPropertyValue("residentsLogin")))
{
var residentslog = home.GetPropertyValue("residentsLogin");
}
My JSON is in the corresponding format
[
{
"name": "Property1",
"url": "http://www.google.com",
"target": "_blank",
"icon": "icon-link"
},
{
"name": "Property2",
"url": "http://www.google.com",
"target": "_blank",
"icon": "icon-link"
}
]

Working code should look like this:
public class MyJsonObject
{
public string name{get;set;}
public string url { get; set; }
public string target { get; set; }
public string icon { get; set; }
}
var residentslog = #"[
{
'name': 'Property1',
'url': 'http://www.google.com',
'target': '_blank',
'icon': 'icon-link'
},
{
'name': 'Property2',
'url': 'http://www.google.com',
'target': '_blank',
'icon': 'icon-link'
}
]";
List<MyJsonObject> myJsonObjectList = JsonConvert.DeserializeObject<List<MyJsonObject>>(residentslog);
ViewBag.MySelectList = new SelectList(myJsonObjectList, "name", "url");

Related

How to stop .net core 6 webapp with Odata query from inlining dictionary?

I have a rather simple(for now) Odata controller that does not work in the way I expect.
Backend store is a Mongo database, but I don't think that is relevant.
Model class:
public class EventModel
{
[Key]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string EventName { get; set; }
public DateTime EventTime { get; set; }
// Fields omitted to shorten sample
public IDictionary<string,object?> Data { get; set; }
}
OData controller is added like so:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Repository.Model.EventModel>("Events");
services.AddControllers()
.AddOData(options => options
.Select()
.Filter()
.OrderBy()
.Expand()
.Count()
.SetMaxTop(null)
.AddRouteComponents("eventservice/odata", builder.GetEdmModel()));
And this is the controller:
public class EventODataController : ODataController
{
private readonly IEventRepository _repository;
public EventODataController(IEventRepository repository)
{
_repository = repository;
}
[HttpGet("eventservice/odata/Events")]
[EnableQuery]
public ActionResult Get()
{
var data = _repository.GetAsQueryable();
return Ok(data);
}
Expected result when doing a HTTP get to eventservice/odata/Events$top=100 should be along the lines of this:
{
"#odata.context": "http://127.0.0.1:7125/eventservice/odata/$metadata#Events",
"#odata.count": 1080302,
"value": [
{
"Id": "63dbbcc9920829279f559025",
"EventName": "Asset",
"EventTime": "2022-09-27T09:14:15.398+02:00",
// Omitted field data here
"Data": {
"Data1":"Foo",
"Data2":"Bar",
"SomeMore":4
}
}
But it turns out that OData somehow flattens/inlines the dictionary, so the result is this:
"#odata.context": "http://127.0.0.1:7125/eventservice/odata/$metadata#Events",
"#odata.count": 1080302,
"value": [
{
"Id": "63dbbcc9920829279f559025",
"EventName": "Asset",
"EventTime": "2022-09-27T09:14:15.398+02:00",
"AssetId#odata.type": "#Int64",
"AssetId": 1258,
"UniqueCode": "9404120007",
"DbId#odata.type": "#Int64",
"DbId": 1038118,
"SomeData": "ABC",
"MoreData": "108",
"AreaName": "Area51,
...
},
Simple question: How do I stop OData from behaving like this, and do what I expect?

index percolate queries using spring data jpa

Here is my Dto for percolator query class.
#Data
#Document(indexName = "#{#es.indexName}")
#Builder(builderClassName = "RuleBuilder")
public class Rule {
#Id
private String id = UUID.randomUUID().toString();
private QueryBuilder query;
private RuleDataDto data;
public static class RuleBuilder {
private String id = UUID.randomUUID().toString();
}
}
Index Mapping
{
"mappings": {
"properties": {
"query": {
"type": "percolator"
},
"data": {
"properties": {
"subType": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"content": {
"type": "text"
}
}
}
}
based on criteria I am generating queries and trying to index those to percolator. but getting below exception
query malformed, no start_object after query name
what should be the query field Type? can someone help me on this
You are trying to store an Elasticsearch object (QueryBuilder) in Elasticsearch without specifying the mapping type.
You will need to annotate your query property as percolator type and might change the type of your property to a String:
#Document(indexName = "#{#es.indexName}")
public class Rule {
#Id
private String _id;
#Field(type = FieldType.Percolator)
private String query;
// ...
}
Or, if you want to have some other class for the query property you'll need a custom converter that will convert your object into a valid JSON query - see the documentation for the percolator mapping.

Wiremock match request POST by params

I have a simple POST request sending params using application/x-www-form-urlencoded encoding.
Looking in the wiremock docs I can't find a way to match the request by the params values, something like the querystring match I mean.
Furthermore it seems also impossible to contains for the body, nor to match the entire body in clear (just as base64).
Is there a way to match this kind of requests?
Another option that I found was to use contains for Stubbing Content-Type: application/x-www-form-urlencoded
{
"request": {
"method": "POST",
"url": "/oauth/token",
"basicAuthCredentials": {
...
},
"bodyPatterns": [
{
"contains": "username=someuser"
}
]
},
"response": {
....
}
}
With classic wiremock you can use bodyPatterns' matchers and regular expressions:
for example:
...
"request": {
"method": "POST",
"url": "/api/v1/auth/login",
"bodyPatterns": [
{
"matches": "(.*&|^)username=test($|&.*)"
},
{
"matches": "(.*&|^)password=123($|&.*)"
}
]
},
I had a similar problem - I wanted to check the exact parameters , but without patterm magic (so easier to maintain). As a workaround, I created a helper class :
import java.util.Iterator;
import java.util.LinkedHashMap;
public class WireMockUtil {
public static String toFormUrlEncoded(LinkedHashMap<String, String> map) {
if (map == null) {
return "";
}
StringBuilder sb = new StringBuilder();
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
String value = map.get(key);
appendFormUrlEncoded(key,value,sb);
if (it.hasNext()) {
sb.append('&');
}
}
return sb.toString();
}
public static String toFormUrlEncoded(String key, String value) {
StringBuilder sb = new StringBuilder();
appendFormUrlEncoded(key, value,sb);
return sb.toString();
}
public static void appendFormUrlEncoded(String key, String value, StringBuilder sb) {
sb.append(key).append('=');
if (value != null) {
sb.append(value);
}
}
}
Inside the Wiremock test you can use it via:
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
...
withRequestBody(equalTo(WireMockUtil.toFormUrlEncoded(map))).
Or check only dedicated parts by containing:
withRequestBody(containing(WireMockUtil.toFormUrlEncoded("key","value1"))).
You could try https://github.com/WireMock-Net/WireMock.Net
Matching query parameters and body can be done with this example json:
{
"Guid": "dae02a0d-8a33-46ed-aab0-afbecc8643e3",
"Request": {
"Url": "/testabc",
"Methods": [
"put"
],
"Params": [
{
"Name": "start",
"Values": [ "1000", "1001" ]
},
{
"Name": "end",
"Values": [ "42" ]
}
],
"Body": {
"Matcher": {
"Name": "WildcardMatcher",
"Pattern": "test*test"
}
}
}
}

MultiField mapping using spring-data-elasticsearch annotations

I am trying to use spring-data-elasticsearch to set up mappings for a type that is equivalent to the json configuration below and I am running into issues.
{
"_id" : {
"type" : "string",
"path" : "id"
},
"properties":{
"addressName":{
"type":"multi_field",
"fields":{
"addressName":{
"type":"string"
},
"edge":{
"analyzer":"edge_search_analyzer",
"type":"string"
}
}
},
"companyName":{
"type":"multi_field",
"fields":{
"companyName":{
"type":"string"
},
"edge":{
"analyzer":"edge_search_analyzer",
"type":"string"
}
}
}
}
}
Here is the entity class as it stands now:
#Document(indexName = "test", type="address")
#Setting(settingPath="/config/elasticsearch/test.json") // Used to configure custom analyzer/filter
public class Address {
#Id
private Integer id;
#MultiField(
mainField = #Field(type = FieldType.String),
otherFields = {
#NestedField(dotSuffix = "edge", type = FieldType.String, indexAnalyzer = "edge_search_analyzer")
}
)
private String addressName;
#MultiField(
mainField = #Field(type = FieldType.String),
otherFields = {
#NestedField(dotSuffix = "edge", type = FieldType.String, indexAnalyzer = "edge_search_analyzer")
}
)
private String companyName;
public Address() {}
public Address(AddressDTO dto) {
id = dto.getId();
addressName = dto.getAddressName();
companyName = dto.getCompanyName();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
Preconditions.checkNotNull(id);
this.id = id;
}
public String getAddressName() {
return addressName;
}
public void setAddressName(String addressName) {
this.addressName = addressName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
}
What I am finding is that this results in a mapping like:
"address" : {
"properties" : {
"addressName" : {
"type" : "string",
"fields" : {
"addressName.edge" : {
"type" : "string",
"index_analyzer" : "edge_search_analyzer"
}
}
},
"companyName" : {
"type" : "string",
"fields" : {
"companyName.edge" : {
"type" : "string",
"index_analyzer" : "edge_search_analyzer"
}
}
}
}
}
Which results in two issues:
Id mapping is not done so Elasticsearch generates the ids
Searches on the properties with the custom analyzer do not work properly
If I add the following to override the use of the annotations everything works fine:
#Mapping(mappingPath="/config/elasticsearch/address.json")
Where "address.json" contains the mapping configuration from the top of this post.
So, can anyone point out where I might be going wrong with what I'm trying to achieve?
Is is possible using available annotations or am I going to have to stick with json configuration?
Also, is there a "correct" way to setup index-level configuration via spring-data-elasticsearch, or is that not a supported approach? Currently, I am using the #Setting annotation for this purpose

A circular reference was detected while serializing an object of type?

DB MetersTree TABLE
id text parentId state
0 root 0 open
1 level 1 1 open
2 level 1 1 open
...
CONTROLLER
public ActionResult GetDemoTree()
{
OsosPlus2DbEntities entity = new OsosPlus2DbEntities();
MetersTree meterTree = entity.MetersTree.FirstOrDefault();
return Json(meterTree, JsonRequestBehavior.AllowGet);
}
DATA FORMAT THAT SHOULD BE (for example)
[{
"id": 1,
"text": "Node 1",
"state": "closed",
"children": [{
"id": 11,
"text": "Node 11"
},{
"id": 12,
"text": "Node 12"
}]
},{
"id": 2,
"text": "Node 2",
"state": "closed"
}]
How can I create tree Json Data? If I write MetersTree with its relationships I get the error that is defined in the title.
You need to break the circular reference that is being picked up because of the navigational property in your EF class.
You can map the results into an anonymous type like this, although this is untested:
public ActionResult GetDemoTree()
{
OsosPlus2DbEntities entity = new OsosPlus2DbEntities();
MetersTree meterTree = entity.MetersTree.FirstOrDefault();
var result = from x in meterTree
select new
{
x.id,
x.text,
x.state,
children = x.children.Select({
c => new {
c.id,
c.text
})
};
return Json(result, JsonRequestBehavior.AllowGet);
}
I solved it like this:
VIEW MODEL
public class MetersTreeViewModel
{
public int id { get; set; }
public string text { get; set; }
public string state { get; set; }
public bool #checked { get; set; }
public string attributes { get; set; }
public List<MetersTreeViewModel> children { get; set; }
}
CONTROLLER
public ActionResult GetMetersTree()
{
MetersTree meterTreeFromDb = entity.MetersTree.SingleOrDefault(x => x.sno == 5); //in my db this is the root.
List<MetersTreeViewModel> metersTreeToView = buildTree(meterTreeFromDb.Children).ToList();
return Json(metersTreeToView, JsonRequestBehavior.AllowGet);
}
BuildTree Method
private List<MetersTreeViewModel> BuildTree(IEnumerable<MetersTree> treeFromDb)
{
List<MetersTreeViewModel> metersTreeNodes = new List<MetersTreeViewModel>();
foreach (var node in treeFromDb)
{
if (node.Children.Any())
{
metersTreeNodes.Add(new MetersTreeViewModel
{
id = node.sno,
text = node.Text,
state = node.Text,
children = BuildTree(node.Children)
});
}
else {
metersTreeNodes.Add(new MetersTreeViewModel
{
id = node.sno,
text = node.Text,
state = node.Text
});
}
}
return metersTreeNodes;
}
Thanks to all who are interested in ...

Resources