Formatting JSON in ASP.NET MVC - asp.net

I want to return a JSON from ASP.NET MVC ActionResult type method that looks something like this:
{
success: true,
users: [
{id: 1, FileName: 'Text22'},
{id: 2, FileName: 'Text23'}
]
}
How would I format it? Right now I have something like this
Return Json(New With {Key .success = "true", Key .users = responseJsonString}, JsonRequestBehavior.AllowGet)
Edit: I am using VB.NET but answers in C# are fine too.

I prefer using ViewModels, rather than manually constructing complex JSON responses. It ensures consistency against all methods that return the data, and is easier to work with strongly typed properties IMHO.
public class Response
{
public bool Success { get; set; }
public IEnumerable<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
and then just:
Response response = new Response();
response.Success = true;
// populate the rest of the data
return Json(response);
This also has the advantage of letting you use a base class for every response, if there's common data like a success status, or error messages.
public class ResponseBase
{
public bool Success { get; set; }
public string Message { get; set; }
}
public class UserResponse : ResponseBase
{
IENumerable<User> Users { get; set }
}
Now, if you have an error:
return Json(new ResponseBase() { Success = false, Message = "your error" });
or if it succeeds
return Json(new UserResponse() { Success = true, Users = users });
If you want to manually craft the JSON, then just:
return Json(new { success = true, users = new[] { new { id = 1, Name = "Alice"}, new { id = 2, Name = "Bob"} } });

in C#
return Json(new
{
success = true,
users = new[]
{
new {id = 1, FileName = "Text22"}, new {id = 2, FileName = "Text23"}
}
}, JsonRequestBehavior.AllowGet);
returns
{"success":true,"users":[{"id":1,"FileName":"Text22"},{"id":2,"FileName":"Text23"}]}

Related

Syncfusion TreeView doesnt show data

I have a list that matches the requirements that I get through the request from js.
Data from the request comes filled in, but the list is not displayed
< ejs-treeview id="treedata" created="created">
< e-treeview-fields dataSource="#Model.Items" id="LevelCode" parentId="ParentLevelCode" text="Name" hasChildren="HasChild"></e-treeview-fields>
< /ejs-treeview>
function created()
{
getCategories();
}
function getCategories() {
let treedata = document.getElementById('treedata').ej2_instances[0];
let request = new ej.base.Ajax(`/Category/GetAll`, 'GET');
request.send();
request.onSuccess = data => {
if (treedata.element !== undefined) {
let final = JSON.parse(data);
treedata.fields.dataSource = final.Categories;
treedata.dataBind();
treedata.refresh();
}
};
}
public class GetAllCategoriesHandlerResponseItem
{
public string Id { get; set; }
public string Name { get; set; }
public bool HasChild { get; set; }
public string LevelCode { get; set; }
public string ParentLevelCode { get; set; }
}
In TreeView component, the fields property has been provided to set or get the data source and other data-related information. You can use this property to dynamically change the TreeView component data source. But you need to specify the properties in its predefined structure to update the TreeView data source.
Check the below code snippet.
function getCategories() {
let treedata = document.getElementById('treedata').ej2_instances[0];
let request = new ej.base.Ajax(`/Category/GetAll`, 'GET');
request.send();
request.onSuccess = data => {
if (treedata.element !== undefined) {
let final = JSON.parse(data);
treedata.fields = {datasource: final.Categories, id:"LevelCode", parentId:"ParentLevelCode", text:"Name", hasChildren:"HasChild" };
treedata.dataBind();
treedata.refresh();
}
};
}
You can refer to the below link to know about the details.
https://www.syncfusion.com/kb/10135/how-to-refresh-the-data-in-ej2-treeview

Consuming web api with RestSharp basic authentication return null

I am trying to consume an endpoint with RestSharp with Basic authentication.
I followed the instructions on the documentation https://restsharp.dev/getting-started/getting-started.html
The request was successful but I think the request body was malformed.
How can I get this to work
internal BalanceInquiryResponse BalanceInquiryRest(BalanceInquiryRequest BalanceInquiryRequest, Settings Settings)
{
// BalanceInquiryResponse BalanceInquiryResponse = new BalanceInquiryResponse();
var client = new RestClient(Settings.BaseUrl + "All/Inquiry");
client.Authenticator = new HttpBasicAuthenticator(Settings.Username, Settings.Password);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(new
{
Acc = BalanceInquiryRequest.Acc
});
IRestResponse response = client.Execute(request);
IRestResponse<BalanceInquiryResponse> res = client.Execute<BalanceInquiryResponse>(request);
if (response.IsSuccessful)
{
BalanceInquiryResponse = new BalanceInquiryResponse
{
responseInquiry = res.Data.responseInquiry,
ResponseDescription = res.Data.ResponseDescription,
ResponseMessage = res.Data.ResponseMessage
};
return BalanceInquiryResponse;
}
else
{
BalanceInquiryResponse = new BalanceInquiryResponse
{
ResponseDescription = responseses.ErrorMessage,
};
return BalanceInquiryResponse;
}
}
This is my response body
{
"responseMessage": "Successful",
"responseDescription": "Request Successful",
"responseInquiry": null
}
When I tried with postman I got
{
"ResponseMessage": "Successful",
"ResponseDescription": "Request Successful",
"response": {
"AvalBal": 586324.42,
"ReverAmt": 0,
"AccCurrency": "US "
}
}
IRestResponse<BalanceInquiryResponse> res = client.Execute<BalanceInquiryResponse>(request);
So there is a specific reason...you are putting BalanceInquiryResponse in the generic IRestResponse above.
With the above call, this should automatically hydrate the BalanceInquiryResponse object, and you shouldn't need to hand map.
Aka, you should ~not~ need this below code:
BalanceInquiryResponse = new BalanceInquiryResponse
{
responseInquiry = res.Data.responseInquiry,
ResponseDescription = res.Data.ResponseDescription,
ResponseMessage = res.Data.ResponseMessage
};
I think your issue is that your POCO object (BalanceInquiryResponse) should perfectly match the "structure" of the JSON.
Change your BalanceInquiryResponse to PERFECTLY match the json "properties".
and recognize you have a nested object.
I think it it would be:
public class ResponsePoco {
public double AvalBal { get; set; }
public int ReverAmt { get; set; }
public string AccCurrency { get; set; }
}
public class BalanceInquiryResponse{
public string ResponseMessage { get; set; }
public string ResponseDescription { get; set; }
public ResponsePoco response { get; set; }
}
Pay attention the to "ResponsePoco response"..note the variable name is LOWERCASE .. because...the json has a lowercase "response" in it.
I have called the (child) object "ResponsePoco" to highlight the difference between the object name and the variable name.
If you cannot "perfectly" match the Poco properties. you can use attributes to "massage" the discrepencies. As seen here:
https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm
public class Videogame
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("release_date")]
public DateTime ReleaseDate { get; set; }
}

I can't bind additional parameters to AngularJS call

I have ASP.NET application with the form handled by AngularJS. There are 2 date-time pickers (fromDate and toDate variables) and check box that indicate if open dates are included (isOpenDatesIncluded).
The code looks as following:
1) In first AngularJS module:
SearchActionsApp.controller("ListController", function($scope, $location,$q, Actions, ActionDates, CounterAgents,Counteragents, AsyncTask) {
...
$scope.actionsQuery = {
searchText: "",
fromDate: new Date(moment().format("MM/DD/YYYY")),
toDate: new Date(moment().add('d', 3).format("MM/DD/YYYY")),
isOpenDatesIncluded: false,
...
ActionDates.query({ actionId: action.Id, isOpenDatesIncluded: $scope.actionsQuery.isOpenDatesIncluded, fromDate: $scope.actionsQuery.fromDate, toDate: $scope.actionsQuery.toDate }, task.success, task.error);
...
}
2) In service.js:
.factory('ActionDates', function ($resource) {
return $resource('/RestApi/api/ActionDates', {});
})
3) On server side:
[HttpGet]
public IEnumerable<ActionDateItem> GetByQuery([FromUri]ActionDateQuery query)
{
return _service.QueryActionDates(query);
}
public IEnumerable<ActionDateItem> QueryActionDates(ActionDateQuery query)
{
var sql = query.BuildSql();
using (var cn = CreateSqlConnection())
{
return cn.Query<ActionDateItem>(sql, new
{
query.ActionId,
query.IsOpenDatesIncluded,
BeginDate = query.FromDate,
EndDate = query.ToDate
});
}
}
public class ActionDateQuery
{
public ActionDateQuery()
{
ActionId = -1;
IsOpenDatesIncluded = false;
FromDate = new DateTime(1980, 1, 1);
ToDate = DateTime.Now.AddYears(1);
}
public long ActionId { get; set; }
public bool IsOpenDatesIncluded { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; }
}
The issue is the query returns the set of data from: 1980, 1, 1 to DateTime.Now.AddYears(1), but I need to return the data in range: fromDate - toDate, which I get from the client side.
The parameters from client side attached to RestApi URL are correct, but I only get the first parameter - ActionId on server side. I don't get 3 others - IsOpenDatesIncluded, FromDate and ToDate.
I'm not sure how to bind them in service.js file.
How to do that?

Web API & entitiy framework how to work with posted json array

I try to write a post method for my asp.net web API.
The method shoulde be
1. receive Json formated datastring with have single objects and one sub array.
2. write it in my database in two tables with have a 1:n relation.
It would be wonderfull if anyone can help me.
I've no more idea how i can realise it
Example of the Json data:
[
{
"User":"testuser",
"CPGRP":21321321,
"Sex":"men",
"Name": "test",
"PointList":[
{
"Cost_I_Rea":"22202771.01",
"Cost_TV":"213213210.0" ,
"GRP":10,
"ID":0,
"ReichweiteID_F":1,
"RW_TV":"9.603",
"RW_Zuwgs":"9.603",
},
{
"Cost_I_Rea":"22202771.01",
"Cost_TV":"213213210.0" ,
"GRP":10,
"ID":0,
"ReichweiteID_F":1,
"RW_TV":"9.61103",
"RW_Zuwgs":"9.6043",
}
]
"Potenzial":213213,
"ReichweiteID":0,
"ZielGRP":21321321
}
]
This is my Post Method now, but it's generate a 500 Error:
// POST api/TVKurve
[ResponseType(typeof(Points))]
public async Task<IHttpActionResult> PostPoints(Points points)
{
//if (!ModelState.IsValid)
//{
// return BadRequest(ModelState);
//}
db.Points.Add(points);
await db.SaveChangesAsync();
db.Entry(points).Reference(x => x.Reichweite).Load();
var dto = new ReichweitePointsDto()
{
ReichweiteID = points.ReichweiteId,
Sex = points.Reichweite.Geschlecht,
Name = points.Reichweite.Name,
CPGRP = points.Reichweite.CpGRP,
Potenzial = points.Reichweite.Potenzial,
ZielGRP = points.Reichweite.ZielGRP,
User = points.Reichweite.Benutzer,
PointList = new List<PointListDto>(),
};
return CreatedAtRoute("DefaultApi", new { id = points.Id }, points);
}
and my data annotation Model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace xms_ef_vers1.Models
{
public class PointListDto
{
public PointListDto() { }
public PointListDto(Points item)
{
ID = item.Id;
GRP = item.GRP;
RW_TV = item.RW_TV;
Cost_TV = item.Cost_TV;
RW_Zuwgs = item.Rw_ZuWGS;
Cost_I_Rea = item.Cost_I_Rea;
ReichweiteID_F = item.ReichweiteId;
}
[Key]
public int ID { get; set;}
[Required]
public int GRP { get; set; }
public decimal RW_TV { get; set; }
public double Cost_TV { get; set; }
public decimal RW_Zuwgs { get; set; }
public decimal Cost_I_Rea { get; set; }
public int ReichweiteID_F { get; set; }
public Points ToEntity()
{
return new Points
{
Id = ID,
GRP = GRP,
RW_TV = RW_TV,
Cost_TV = Cost_TV,
Rw_ZuWGS = RW_Zuwgs,
Cost_I_Rea = Cost_I_Rea,
ReichweiteId = ReichweiteID_F,
};
}
}
}
Thank you for your answer.
I ve got it.
Look here:
public HttpResponseMessage PostReicheite(ReichweitePointsDto reichw)
{
if (ModelState.IsValid)
{
var reichwe = new Reichweite()
{
Geschlecht = reichw.Geschlecht,
Name = reichw.Name,
CpGRP = reichw.CPGRP,
Potenzial = reichw.Potenzial,
ZielGRP = reichw.ZielGRP,
Benutzer = reichw.Benutzer,
PointListe = (from item in reichw.PointListe
select new Points()
{
GRP = item.GRP,
RW_TV = item.RW_TV,
Cost_TV = item.Cost_TV,
Rw_ZuWGS = item.RW_Zuwgs,
Cost_I_Rea = item.Cost_I_Rea,
}).ToList()
};
db.Reichweites.Add(reichwe);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, reichwe);
response.Headers.Location = new Uri(Url.Link("DefaultAPI", new { id = reichwe.Id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
Now the Post Method do exactly what i need.
Only one bug, i've got an 500 status back can you say me why?
Best

MVC to WebApi calls losing session

I am using MVC and WebApi in same project, not using Session in WebApi.
In MVC BaseController I have something along these line
protected const string HOME = "HOME";
protected SessionDataStore SessionDataStore
{
get
{
if ((Session[HOME] != null) && (Session[HOME] is SessionDataStore))
{
return (SessionDataStore)Session[HOME];
}
}
set
{
Session[HOME] = value;
}
}
public class SessionDataStore
{
public Request CurrentRequest { get; set; }
public Customer CurrentCustomer { get; set; }
public List<Salutation> Salutations { get; set; }
public WebServiceConfiguration CurrentConfiguration { get; set; }
public List<int> CurrentConfigurationIds { get; set; }
public List<int> CurrentAttributeIds { get; set; }
public SessionDataStore()
{
CurrentRequest = new Request();
CurrentCustomer = new Customer();
Salutations = new List<Salutation>()
{
new Salutation() { Id = 1, Name = "Mr", },
new Salutation() { Id = 2, Name = "Mrs", },
new Salutation() { Id = 3, Name = "Miss", },
new Salutation() { Id = 4, Name = "Ms", },
new Salutation() { Id = 5, Name = "Dr", },
new Salutation() { Id = 6, Name = "Prof", },
new Salutation() { Id = 7, Name = "Other", }
};
CurrentConfiguration = new WebServiceConfiguration();
CurrentConfigurationIds= new List<int>();
CurrentAttributeIds = new List<int>();
}
}
In my MVC project, I call the web API and update the Session object like this.
I initialise SessionDataStore in the index page to a new object
var client = new HttpClient(_handler);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(string.Concat(GetBaseUrl().AbsoluteUri + "api/request/", requestId)).Result;
SessionDataStore.CurrentRequest = response.IsSuccessStatusCode ? response.Content.ReadAsAsync<Request>().Result : null;
The status code is Success but then I am losing the session.
Not sure why this is happening. I am using inProc session
Web API is REST-compliant, and REST is stateless. In other words, no session. You cannot access the session in a Web API action. If you need to interact with the session via an AJAX call, you will need to simply create an MVC Controller action to handle it instead of a Web API ApiController action.
If you didn't find the answer yet, this is how you can enable session usage inside web api request. You have to write the Application_PostAuthorizeRequest inside the Global.asax.cs like this:
protected void Application_PostAuthorizeRequest()
{
if(IsWebApiRequest())
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
private bool IsWebApiRequest()
{
return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Contains("/api/");
}

Resources