How to post complex Json data (body) using restsharp? - restsharp

I hope you are doing well !!
I need to do a post request using restsharp, the body to be added to request is given below. This is bit complicated than the post request I have done before.
Complex Post for which I request assistance:
{
"contextInfoId": "string",
"userId": "string",
"specificOs": "string",
"buildPlatform": "string",
"deviceName": "string",
"deviceId": "string",
"token": "string",
"loginInfo": {
"loginInfoId": "string",
"loginDate": "2019-03-14T06:21:39.693Z"
}
}
This issue for me here is the way 'loginInfo:' has to be provided
I have added basic post body to request using below code:
//Add json data/body
request.AddJsonBody(new { buProfileId ="1", divisionNames = "IDC", businessUnitNames = "XYZ", processGroupNames = "ABC", systemOrProjectName = "Test", customername = "User" });
The above C# code work fine for a body like below.
{
"buProfileId": "string",
"divisionNames": "string",
"businessUnitNames": "string",
"processGroupNames": "string",
"systemOrProjectName": "string",
"customername": "string"
}
Could someone please let me know how to achieve the complex post operation.

You can create an json object and assign your value to it, then you can serialize the json and send in the body
public class LoginInfo
{
public string loginInfoId { get; set; }
public DateTime loginDate { get; set; }
}
public class Context
{
public string contextInfoId { get; set; }
public string userId { get; set; }
public string specificOs { get; set; }
public string buildPlatform { get; set; }
public string deviceName { get; set; }
public string deviceId { get; set; }
public string token { get; set; }
public LoginInfo loginInfo { get; set; }
}
public IRestResponse Post_New_RequestType(string context, string user_ID, string Specific_Os, string Build_Platfrom, string Device_Name, string device_Id, string Token_Value, string login_infoId, DateTime Login_Date)
{
Context tmp = new Context();
tmp.contextInfoId = context;
tmp.userId = user_ID;
tmp.specificOs = Specific_Os;
tmp.buildPlatform = Build_Platfrom;
tmp.deviceName = Device_Name;
tmp.deviceId = device_Id;
tmp.token = Token_Value;
tmp.loginInfo.loginInfoId = login_infoId;
tmp.loginInfo.loginDate = Login_Date;
string json = JsonConvert.SerializeObject(tmp);
var Client = new RestClient(HostUrl);
var request = new RestRequest(Method.POST);
request.Resource = string.Format("/api/example");
request.AddParameter("application/json", json, ParameterType.RequestBody);
IRestResponse response = Client.Execute(request);
return response;
}

Related

ASP.NET Core Web API working with Foreign Keys

I'm developing Web Api operations for User Controller and I don't understand why I'm getting the error in the POST method :
The "PK_Section" of the PRIMARY KEY constraint was violated. Unable to insert duplicate key into dbo.Section object. Duplicate key value: (3fa85f64-5717-4562-b3fc-2c963f66afa4).
My IdentityUser model:
public string MiddleName { get; set; }
[Required]
public string Surname { get; set; }
public DateTime BirthDate { get; set; }
public string Address { get; set; }
[Required]
public string UserType { get; set; }
public bool ParentsAgreement { get; set; }
public Section BelongSection { get; set; }
Section Model:
[Required]
public Guid Id { get; set; }
public string Name { get; set; }
public string CoachName { get; set; }
public string SportComplexTitle { get; set; }
[IgnoreDataMember]
public ICollection<User> UsersList { get; set; }
DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//section
modelBuilder.Entity<User>()
.HasOne(s => s.BelongSection)
.WithMany(a => a.UsersList);
modelBuilder.Entity<Section>()
.HasMany(s => s.UsersList)
.WithOne(a => a.BelongSection);
}
And my POST Method:
[HttpPost]
public async Task<ActionResult<User>> Add(User user)
{
try
{
if (user == null)
{
return BadRequest();
}
myDbContext.Users.Add(user);
await myDbContext.SaveChangesAsync();
var result = await myDbContext.Users.Include(o => o.BelongSection).FirstOrDefaultAsync(o
=> o.Id == user.Id);
return result;
}
catch (Exception)
{
throw;
}
}
So, I'm getting the error, that I can't use the Id of the existing already Section in creating User.
My Post method body is:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"userName": "string",
"normalizedUserName": "string",
"email": "string",
"normalizedEmail": "string",
"emailConfirmed": true,
"passwordHash": "string",
"securityStamp": "string",
"concurrencyStamp": "string",
"phoneNumber": "string",
"phoneNumberConfirmed": true,
"twoFactorEnabled": true,
"lockoutEnd": "2021-04-15T08:31:12.271Z",
"lockoutEnabled": true,
"accessFailedCount": 0,
"name": "string",
"middleName": "string",
"surname": "string",
"birthDate": "2021-04-15T08:31:12.271Z",
"address": "string",
"userType": "string",
"parentsAgreement": true,
"belongSection": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa4"
}
}
You could use two ways to add existing child to parent like below:
_context.Section.Attach(user.BelongSection);
Or:
_context.Entry(user.BelongSection).State = EntityState.Unchanged;
Be sure add AsNoTracking() to display the result.
Here is the whole working demo:
[HttpPost]
public async Task<ActionResult<User>> Add(User user)
{
try
{
if (user == null)
{
return BadRequest();
}
//_context.Section.Attach(user.BelongSection);
_context.Entry(user.BelongSection).State = EntityState.Unchanged;
_context.Users.Add(user);
await _context.SaveChangesAsync();
var result = await _context.Users.Include(o => o.BelongSection)
.AsNoTracking()
.FirstOrDefaultAsync(o=> o.Id == user.Id);
return result;
}
catch (Exception)
{
throw;
}
}
Note:
Not sure what is your asp.net core version, remember to add ReferenceLoopHandling.Ignore.
In asp.net core 3.x, System.Text.Json only supports serialization by value and throws an exception for circular references. So you need add Newtonsoft support like below:
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
In .Net 5.0,you could also add Newtonsoft support. Besides,System.Text.Json allows seting ReferenceHandler to Preserve:
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-preserve-references?pivots=dotnet-5-0

How to define the name of the data for the ajax.datatable column name? I keep getting the unknow parameter error for ajax.datatable

JobProg.js
var dataTable;
$(document).ready(function () {
loadDataTable();
});
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": {
"url": "/Admin/CMJobProg/GetAll"
},
"columns": [
{ "data": "jobnumber", "width": "35%" },
{ "data": "assignfrom", "width": "35%" },
{ "data": "assignto", "width": "35%" },
{ "data": "dateassign", "width": "35%" },
{ "data": "jobaction", "width": "35%" },
{ "data": "remarks", "width": "35%" },
{ "data": "type", "width": "35%" },
{ "data": "division" ,"width": "35%" }
]
})
}
CMJobProg.cs
namespace LXG.Models
{
[Table("CMJOBPROG", Schema = "LASIS")]
public class CMJobProg
{
[Required]
[MaxLength(8)]
[Display(Name = "Job Number")]
[Column("JOB_NUMBER")]
public string JobNumber { get; set; }
[Display(Name = "Assign From")]
[MaxLength(22)]
[Column("ASSIGN_FROM")]
public string AssignFrom { get; set; }
[Display(Name = "Assign To")]
[MaxLength(22)]
[Column("ASSIGN_TO")]
public string AssignTo { get; set; }
[Column("DATE_ASSIGN")]
public DateTime DateAssign { get; set; }
[Display(Name = "Job Action")]
[Range(0, 999)]
[Column("JOB_ACTION")]
public int? JobAction { get; set; }
[Display(Name = "Remarks")]
[MaxLength(500)]
[Column("REMARKS")]
public string Remarks { get; set; }
[Display(Name = "Job Type")]
[Required]
[MaxLength(2)]
[Column("TYPE")]
public string Type { get; set; }
[MaxLength(2)]
[Column("DIVISION")]
public string Division { get; set; }
}
}
DataTables warning: table id=tblData - Requested unknown parameter 'jobnumber' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4
I keep getting this error, how to fix this? I able to get the data remarks, type and division, but i cant get others data. Acutally how to define the name for the data name?
As far as I know, asp.net core returned json will has a special format. Like this : JobNumber to jobNumber. To solve this issue. I suggest you could set a JsonPropertyName attribute for each model property.
More details, you could refer to below codes:
[Table("CMJOBPROG", Schema = "LASIS")]
public class CMJobProgress
{
[Required]
[MaxLength(8)]
[Display(Name = "Job Number")]
[Column("JOB_NUMBER")]
[JsonPropertyName("jobnumber")]
public string JobNumber { get; set; }
[Display(Name = "Assign From")]
[MaxLength(22)]
[Column("ASSIGN_FROM")]
[JsonPropertyName("assignfrom")]
public string AssignFrom { get; set; }
[Display(Name = "Assign To")]
[MaxLength(22)]
[Column("ASSIGN_TO")]
[JsonPropertyName("assignto")]
public string AssignTo { get; set; }
[Column("DATE_ASSIGN")]
[JsonPropertyName("dateassign")]
public DateTime DateAssign { get; set; }
[Display(Name = "Job Action")]
[Range(0, 999)]
[Column("JOB_ACTION")]
[JsonPropertyName("jobaction")]
public string JobAction { get; set; }
[Display(Name = "Remarks")]
[MaxLength(500)]
[Column("REMARKS")]
[JsonPropertyName("remarks")]
public string Remarks { get; set; }
[Display(Name = "Job Type")]
[Required]
[MaxLength(2)]
[Column("TYPE")]
[JsonPropertyName("type")]
public string Type { get; set; }
[MaxLength(2)]
[Column("DIVISION")]
[JsonPropertyName("division")]
public string Division { get; set; }
}
Result:
Follow case-sensitive column name in your model/entity class. For example,
"data": "jobnumber"
to
"data": "JobNumber"
Add this "AddNewtonsoftJson" in Startup.cs
services.AddControllersWithViews().AddRazorRuntimeCompilation().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});

Cannot deserialize the current JSON object Cannot deserialize the current JSON object with group column

I am calling the API and trying to store the Jsonresult into a IEnumerable model class. The json result has group header column consolidated_weather.
when I run the program the following error is coming
JsonSerializationException: Cannot deserialize the current JSON object into type 'System.Collections.Generic.IEnumerable`.
How can I call the given json result into the IEnumerable model class after avoiding group header from json result.
I am using the following two model.
public class Weather
{
[Key]
public long id { get; set; }
public string weather_state_name { get; set; }
public string weather_state_abbr { get; set; }
public string wind_direction_compass { get; set; }
public DateTime created { get; set; }
public DateTime applicable_date { get; set; }
public decimal min_temp { get; set; }
public decimal max_temp { get; set; }
public decimal the_temp { get; set; }
public double wind_speed { get; set; }
public decimal wind_direction { get; set; }
public decimal air_pressure { get; set; }
public decimal Humidity { get; set; }
public string Visibllity { get; set; }
public decimal Predictability { get; set; }
}
public class WeatherList
{
public IEnumerable<Weather> consolidated_weather { get; set; }
}
public async Task<IEnumerable<Weather>> GetWeatherAsync(string woied)
{
var url = SD.APIBaseUrl + woied;
var request = new HttpRequestMessage(HttpMethod.Get, url);
var client = _clientFactory.CreateClient();
HttpResponseMessage response = await client.SendAsync(request);
IEnumerable<Weather> weather = new List<Weather>();
WeatherList weatherList = new WeatherList();
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var jsonString = await response.Content.ReadAsStringAsync();
weatherList = JsonConvert.DeserializeObject<WeatherList>(jsonString);
return weatherList;
}
return null;
}
The API result is coming as
<!-- language: lang-html -->
{
"consolidated_weather": [
{
"id": 4577625064341504,
"weather_state_name": "Heavy Rain",
"weather_state_abbr": "hr",
"wind_direction_compass": "WSW",
"created": "2020-07-14T19:35:14.577740Z",
"applicable_date": "2020-07-14",
"min_temp": 11.11,
"max_temp": 15.05,
"the_temp": 14.32,
"wind_speed": 6.570953330777592,
"wind_direction": 254.13274105640758,
"air_pressure": 1016.5,
"humidity": 85,
"visibility": 7.654361031575599,
"predictability": 77
},
{
"id": 4896540210495488,
"weather_state_name": "Showers",
"weather_state_abbr": "s",
"wind_direction_compass": "WNW",
"created": "2020-07-14T19:35:17.569534Z",
"applicable_date": "2020-07-15",
"min_temp": 12.31,
"max_temp": 17.03,
"the_temp": 16.509999999999998,
"wind_speed": 7.600821124862802,
"wind_direction": 284.49357944800784,
"air_pressure": 1015.5,
"humidity": 82,
"visibility": 13.558008729022509,
"predictability": 73
},
]
"title": "Texas",
"location_type": "City",
"timezone": "US"
<!-- end snippet -->
From your json string, we can see that there is a list of weather object in object consolidated_weather.
So you need to parse json to WeatherList.
public class WeatherList {
public IEnumerable<Weather> consolidated_weather { get; set; }
}
[HttpPost("/weather")]
public async Task<IEnumerable<Weather>> GetWeatherAsync()
{
string jsonString = "{\"consolidated_weather\":[{\"id\":4577625064341504,\"weather_state_name\":\"Heavy Rain\",\"weather_state_abbr\":\"hr\",\"wind_direction_compass\":\"WSW\",\"created\":\"2020-07-14T19:35:14.577740Z\",\"applicable_date\":\"2020-07-14\",\"min_temp\":11.11,\"max_temp\":15.05,\"the_temp\":14.32,\"wind_speed\":6.570953330777592,\"wind_direction\":254.13274105640758,\"air_pressure\":1016.5,\"humidity\":85,\"visibility\":7.654361031575599,\"predictability\":77},{\"id\":4896540210495488,\"weather_state_name\":\"Showers\",\"weather_state_abbr\":\"s\",\"wind_direction_compass\":\"WNW\",\"created\":\"2020-07-14T19:35:17.569534Z\",\"applicable_date\":\"2020-07-15\",\"min_temp\":12.31,\"max_temp\":17.03,\"the_temp\":16.509999999999998,\"wind_speed\":7.600821124862802,\"wind_direction\":284.49357944800784,\"air_pressure\":1015.5,\"humidity\":82,\"visibility\":13.558008729022509,\"predictability\":73}]}";
IEnumerable<Weather> weather = new List<Weather>();
WeatherList weatherList = new WeatherList();
weatherList = JsonConvert.DeserializeObject<WeatherList>(jsonString);
return weatherList.consolidated_weather;
}
Test Result
UPDATE
public class WeatherList
{
public IEnumerable<Weather> consolidated_weather { get; set; }
public string title { get; set; }
public string location_type { get; set; }
public string timezone { get; set; }
}
There are two missings in your json string:
<!-- language: lang-html -->
{
"consolidated_weather": [
{
"id": 4577625064341504,
...
},
{
"id": 4896540210495488,
...
},
] <!-- missing , -->
"title": "Texas",
"location_type": "City",
"timezone": "US"
<!-- missing } -->
<!-- end snippet -->
Assuming that you cannot change the content of the Json, you can create a ConsolidatedWeather class that contains the List of Weathers
public class ConsolidatedWeather
{
public List<Weather> Consolidated_Weather { get; set; }
}
and in your deserialize part
return JsonConvert.DeserializeObject<ConsolidatedWeather>(jsonString).Consolidated_Weather;

Setting analyzer from plugin in ElasticSearch with NEST

my first SO post !
I'm trying to set a Stempel Analyzer (ES analyzer for polish language) for a string field. I can do it through PUT request:
{
"doc": {
"_source": {
"enabled": false
},
"properties": {
"file": {
"type": "attachment",
**"analyzer": "polish"**,
"fields": {
"content": {
"type": "string",
"term_vector": "with_positions_offsets"
}
}
}
}
}
}
and it works fine. Trying to do the same thing through NEST.
[ElasticProperty(Name = "_content", TermVector = TermVectorOption.WithPositionsOffsets, Analyzer = "polish")]
public string Content { get; set; }
is not working neither do:
client.CreateIndex(index, b => b.AddMapping<DocInES>(m => m
.MapFromAttributes()
.Properties(props => props
.String(s => s
.Name(p => p.File.Content)
.Analyzer("polish")
))));
When I'm using
var result = client.Analyze(a => a.Index("doc").Analyzer("polish").Text("...text..."));
It works fine, so .NET is detecting this analyzer.
I'm using ES 2.1.1. &
NEST 1.7.1
EDIT:
from what I inspected it seems that NEST is not doing Mapping of Attributes of Attachment class created in .NET. It does Map Attributes of Document class
[ElasticType(Name = "docInES")]
public class DocInES {
public int InstitutionId { get; set;}
public int DocumentId { get; set; }
[ElasticProperty(Store = true, Analyzer = "polish")]
public string Title { get; set; }
[ElasticProperty(Type = FieldType.Attachment)]
public Attachment File { get; set; }
}
But not the Attachment class:
public class Attachment {
[ElasticProperty(Name = "content2", Store = true)]
public string Content { get; set; }
[ElasticProperty(Name = "content_type2")]
public string ContentType { get; set; }
[ElasticProperty(Name = "name2", Analyzer = "english")]
public string Name { get; set; }
}
You should probably check the compatibility matrix on Github.
Nest 1.7.1 is not compatible with ES 2.1.1

Box V2 API - Where is lock/unlock?

There is a note in the developer road map from December of 2013 saying, "Lock/Unlock – We’ve added support for locking and unlocking files into the V2 API."
I've been all through the V2 API (for c#) and cannot find it anywhere. I expected to find something in the BoxFilesManager class or as something you would pass to UpdateInformationAsync within the BoxFileRequest class.
So is there a way to lock/unlock a file?
Great question. In order to see the current lock status of a file do a
GET https://api.box.com/2.0/files/7435988481/?fields=lock
If there is no lock on the file, you'll get something like this back:
{
"type": "file",
"id": "7435988481",
"etag": "0",
"lock": null
}
If you want to lock a file, you need to do a PUT (update) on the /files/ endpoint with a body that tells us what type of lock, and when to release it. Like this:
PUT https://api.box.com/2.0/files/7435988481/?fields=lock
{"lock": {
"expires_at" : "2014-05-29T19:03:04-07:00",
"is_download_prevented": true
}
}
You'll get a response confirming your lock was created:
{
"type": "file",
"id": "7435988481",
"etag": "1",
"lock": {
"type": "lock",
"id": "14516545",
"created_by": {
"type": "user",
"id": "13130406",
"name": "Peter Rexer gmail",
"login": "prexer#gmail.com"
},
"created_at": "2014-05-29T18:03:04-07:00",
"expires_at": "2014-05-29T19:03:04-07:00",
"is_download_prevented": true
}
}
Since there isn't a lock/unlock yet, I created a Lock Manager based on the existing managers:
class BoxCloudLockManager : BoxResourceManager
{
#region Lock/Unlock Classes
[DataContract]
internal class BoxLockRequestInfo
{
[DataMember(Name = "status")]
public string Status { get; set; }
//[DataMember(Name = "expires_at")]
//public string ExpiresAt { get; set; }
[DataMember(Name = "is_download_prevented")]
public bool IsDownloadPrevented { get; set; }
}
[DataContract]
internal class BoxLockRequest
{
[DataMember(Name = "lock")]
public BoxLockRequestInfo Lock { get; set; }
}
#endregion
const string LockFileString = "{0}/?fields=lock";
public BoxCloudLockManager(IBoxConfig config, IBoxService service, IBoxConverter converter, IAuthRepository auth)
: base(config, service, converter, auth)
{
}
public async Task<BoxLockInfo> LockAsync(string documentId,bool isDownloadPrevented = true)
{
var lockRequest = new BoxLockRequest { Lock = new BoxLockRequestInfo { Status = "lock", IsDownloadPrevented = isDownloadPrevented } };
BoxRequest request = new BoxRequest(_config.FilesEndpointUri, string.Format(LockFileString, documentId))
.Method(RequestMethod.Put)
.Payload(_converter.Serialize(lockRequest));
IBoxResponse<BoxLockInfo> response = await ToResponseAsync<BoxLockInfo>(request).ConfigureAwait(false);
return response.ResponseObject;
}
public async Task<BoxLockInfo> UnlockAsync(string documentId)
{
BoxRequest request = new BoxRequest(_config.FilesEndpointUri, string.Format(LockFileString, documentId))
.Method(RequestMethod.Put)
.Payload("{\"lock\":null}");
IBoxResponse<BoxLockInfo> response = await ToResponseAsync<BoxLockInfo>(request).ConfigureAwait(false);
return response.ResponseObject;
}
public async Task<BoxLockInfo> GetLockInfoAsync(string documentId)
{
BoxRequest request = new BoxRequest(_config.FilesEndpointUri, string.Format(LockFileString, documentId))
.Method(RequestMethod.Get);
IBoxResponse<BoxLockInfo> response = await ToResponseAsync<BoxLockInfo>(request).ConfigureAwait(false);
return response.ResponseObject;
}
}
I derived a class from BoxClient, adding a LockManager and instantiate it within the Constructor.
Here is the Lock Info:
[DataContract]
public class BoxLockedBy
{
[DataMember(Name = "type")]
public string Type { get; set; }
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "login")]
public string Login { get; set; }
}
[DataContract]
public class BoxLockDetails
{
[DataMember(Name = "type")]
public string Type { get; set; }
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "created_by")]
public BoxLockedBy CreatedBy { get; set; }
[DataMember(Name = "created_at")]
public string CreatedAt { get; set; }
[DataMember(Name = "expires_at")]
public string ExpiresAt { get; set; }
[DataMember(Name = "is_download_prevented")]
public bool IsDownloadPrevented { get; set; }
}
[DataContract]
public class BoxLockInfo
{
[DataMember(Name = "type")]
public string Type { get; set; }
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "etag")]
public string Etag { get; set; }
[DataMember(Name = "lock")]
public BoxLockDetails LockDetails { get; set; }
}