How to receive JSON data in Dictionary using FromData in Web api? - c#

Below is JSON example which client will send to my API named as 'GetQuestion'
{
"lstQuestions": [{
"QuestionCategory": 1,
"QuestionText": "what is m in mvc",
"OptionA": "model",
"OptionB": "view",
"OptionC": "controller",
"OptionD": "razor",
"CorrectOption": "A"
},
{
"QuestionCategory": 2,
"QuestionText": "How are you",
"OptionA": "fine",
"OptionB": "not fine",
"OptionC": "ok",
"OptionD": "not ok",
"CorrectOption": "A"
}],
"Status" : 1
}
Below is my controller API code:
public class QuestionDetails
{
public List<Questions> lstQuestions { get; set; }
public int Status { get; set; }
}
public class Questions
{
public string QuestionCategory { get; set; }
public string QuestionText { get; set; }
public string OptionA { get; set; }
public string OptionB { get; set; }
public string OptionC { get; set; }
public string OptionD { get; set; }
public string CorrectOption { get; set; }
}
[Route("GetQuestions")]
[HttpPost]
public HttpResponseMessage SendQuestionDetails([FromBody] QuestionDetails UserDetailInput)
{
HttpResponseMessage mesage = Request.CreateResponse(HttpStatusCode.OK, "Demo"); ;
if (ModelState.IsValid)
{
//in progress
}
return mesage;
}
What I want to do is how to create a class with Dictionary and pass as parameter, I don't want to use List because its heavy and Dictionary is much faster than List.
For example:
public class QuestionDetails
{
public Dictionary<string, Questions> lstQuestions { get; set; }
public int Status { get; set; }
}
public HttpResponseMessage SendQuestionDetails([FromBody] Dictionary<string, QuestionDetails> UserDetailInput)
{
HttpResponseMessage mesage = Request.CreateResponse(HttpStatusCode.OK, "Demo"); ;
if (ModelState.IsValid)
{
//in progress
}
return mesage;
}

Don't know what are you talking about with Dictionary is much faster than List but you just need to send the JSON as
{
"A": {
"lstQuestions": {
"A": {
"QuestionCategory": 1,
"QuestionText": "what is m in mvc",
"OptionA": "model",
"OptionB": "view",
"OptionC": "controller",
"OptionD": "razor",
"CorrectOption": "A"
},
"V": {
"QuestionCategory": 2,
"QuestionText": "How are you",
"OptionA": "fine",
"OptionB": "not fine",
"OptionC": "ok",
"OptionD": "not ok",
"CorrectOption": "A"
}
},
"Status": 1
}
}

Hope below code will clear your query.
public HttpResponseMessage SendQuestionDetails([FromBody] Dictionary<string, QuestionDetails> UserDetailInput)
{
List<Questions> list = new List<Questions> { };
list.Add(new Questions
{
CorrectOption = "CorrectOption1",
OptionA = "OptionA1",
OptionB = "OptionB1",
OptionC = "OptionC1",
OptionD = "OptionD1",
QuestionCategory = "QuestionCategory1",
QuestionText = "QuestionText1"
});
list.Add(new Questions
{
CorrectOption = "CorrectOption2",
OptionA = "OptionA2",
OptionB = "OptionB2",
OptionC = "OptionC2",
OptionD = "OptionD2",
QuestionCategory = "QuestionCategory2",
QuestionText = "QuestionText2"
});
Dictionary<QuestionDetails, int> dictionary = new Dictionary<QuestionDetails, int> { };
QuestionDetails detail = new QuestionDetails { lstQuestions = list, Status = 1 };
HttpResponseMessage mesage = Request.CreateResponse(HttpStatusCode.OK, detail);
return mesage;
return mesage;
}

Related

Fluent validation custom response ASP.NET Core Web API

I am working on an ASP.NET Core 6 Web API project. We use Fluent Validation. How can I return custom response. Please advice.
I would like to send custom response on different validation error such as page, limit, date etc
This is the response I get by default:
{
"type": "",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-097c689850af328c49705cea77fc6fbd-0c7defe165d9693f-00",
"errors": {
"Page": [
"Page value should be greater than 0"
],
"Limit": [
"Limit value should be greater than 0"
]
}
}
And this is the response I would like to get:
{
"traceId": "e45b3398-a2a5-43eb-8851-e45de1184021",
"timestamp": "2021-06-28T00:32:06.548Z",
"errors": [
{
"errorCode": "Contract Violation",
"message": "Page should be greater than 0",
"priority": "MEDIUM",
"properties": {
"name": "string",
"value": "string"
}
}
]
}
This is my code:
public async Task<IActionResult> Get([FromQuery] DataParameter input)
{
}
public class DataParameter
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int Page { get; set; }
public int Limit { get; set; }
}
public class QueryParameterValidator : AbstractValidator<QueryParameter>
{
public QueryParameterValidator()
{
RuleFor(model => model.Page)
.GreaterThan(0)
.WithMessage("Page value should be greater than 0");
RuleFor(model => model.Limit)
.GreaterThan(0)
.WithMessage("Limit value should be greater than 0");
RuleFor(model => model.StartDate)
.Matches(#"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")
.WithMessage("Transaction from date should be in the pattern of YYYY-MM-DD");
RuleFor(model => model.EndDate)
.Matches(#"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")
.WithMessage("Transaction to date should be in the pattern of YYYY-MM-DD");
}
}
Here is a whole working demo you could follow:
Model:
public class ErrorDetail
{
public string traceId { get; set; }
public DateTime timestamp { get; set; }
public List<Error> errors { get; set; } = new List<Error>();
}
public class Error
{
public string errorCode { get; set; }
public string message { get; set; }
public string priority { get; set; }
public Properties properties { get; set; }=new Properties();
}
public class Properties
{
public string name { get; set; }
public string value { get; set; }
}
Static class:
public static class CustomProblemDetails
{
public static ErrorDetail ErrorDetail { get; set; } =new ErrorDetail();
public static IActionResult MakeValidationResponse(ActionContext context)
{
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Status = StatusCodes.Status400BadRequest,
};
foreach (var keyModelStatePair in context.ModelState)
{
var errors = keyModelStatePair.Value.Errors;
if (errors != null && errors.Count > 0)
{
if (errors.Count == 1)
{
var errorMessage = GetErrorMessage(errors[0]);
ErrorDetail.errors.Add(new Error()
{
errorCode= "Contract Violation",
message = errorMessage,
priority= "MEDIUM",
properties= new Properties() {
name = "string",
value = "string"
}
});
}
else
{
var errorMessages = new string[errors.Count];
for (var i = 0; i < errors.Count; i++)
{
errorMessages[i] = GetErrorMessage(errors[i]);
ErrorDetail.errors.Add(new Error()
{
errorCode = "Contract Violation",
message = errorMessages[i],
priority = "MEDIUM"
});
}
}
}
}
ErrorDetail.traceId = context.HttpContext.TraceIdentifier;
ErrorDetail.timestamp = DateTime.Now;
var result = new BadRequestObjectResult(ErrorDetail);
result.ContentTypes.Add("application/problem+json");
return result;
}
static string GetErrorMessage(ModelError error)
{
return string.IsNullOrEmpty(error.ErrorMessage) ?
"The input was not valid." :
error.ErrorMessage;
}
}
Register:
builder.Services.AddControllers().AddFluentValidation().ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = CustomProblemDetails.MakeValidationResponse;
});
Result:

Loop for add a json for each object in list

I'm making a tool that needs to export a json. He needs to be in this format:
{
"version" : "2",
"mangas" : [ {
"manga" : [ "sample", "manganame", 1234567890, 0, 0 ],
"chapters" : [ {
"u" : "urlexample",
"r" : 1
}, {
"u" : "urlexample",
"r" : 1
}, {
"u" : "urlexample",
"r" : 1
} ]
} ]
}
And this is my code:
void createJson(String manganame, String mangaoid, String sourceid)
{
String[] mangainfo = { "/manga/" + mangaoid, manganame, sourceid, "0", "0" };
var root = new RootObject()
{
version = "2",
mangas = new List<Manga>()
{
new Manga()
{
manga = mangainfo,
chapters = new List<Chapter>()
{
new Chapter
{
u = "sample",
r = 1
}
}
}
}
};
var json = JsonConvert.SerializeObject(root);
File.WriteAllText(#"D:\path.txt", json);
Console.WriteLine(json);
}
I'm lost, if someone can help me. Already give a search on Google, but the answer didn't come up in my head, already trying for a few time, slowly I'm getting but now is time to ask for help lol
For the list I was talking about, I'll explain it. I have a sqlite DB that have various information from mangas etc... I execute a query where I filter by a id, "SELECT * FROM MangaChapter WHERE manga_id = 'someid'", then i put the result on a list using a for loop. In the DB chapter url is stored like that "mr-chapter-166165" this is why i have had to concat string in chapterList.add.
List<String> chapterList = new List<String>();
cmd.CommandText = "SELECT * FROM MangaChapter WHERE manga_id = '3252'";
reader = cmd.ExecuteReader();
while (reader.Read())
{
chapterList.Add("/pagesv2?oid=" + reader.GetString("oid"));
}
For reference this is what I'm using to manage the sqlite db https://www.nuget.org/packages/dotConnect.Express.for.SQLite/
In the list, each chapter is something like that "/pagesv2?oid=mr-chapter-166165", if I print all the list on the console we'll be having something like that:
/pagesv2?oid=mr-chapter-166165
/pagesv2?oid=mr-chapter-166166
/pagesv2?oid=mr-chapter-166167
Here are the classes I generated from the given JSON sample
public class Chapter
{
[JsonProperty("u")]
public string U { get; set; }
[JsonProperty("r")]
public int R { get; set; }
}
public class Manga
{
[JsonProperty("manga")]
public IList<object> MangaInfos { get; set; }
[JsonProperty("chapters")]
public IList<Chapter> Chapters { get; set; }
}
public class Example
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("mangas")]
public IList<Manga> Mangas { get; set; }
}
and here the code to reproduce the give JSON sample
var d = new Example
{
Version = "2",
Mangas = new List<Manga>
{
new Manga()
{
MangaInfos = new List<object>{ "sample", "manganame", 1234567890, 0, 0 },
Chapters = new List<Chapter>
{
new Chapter()
{
U = "urlexample",
R = 1,
},
new Chapter()
{
U = "urlexample",
R = 1,
},
new Chapter()
{
U = "urlexample",
R = 1,
},
},
},
},
};
var json = JsonConvert.SerializeObject(d,Formatting.Indented);
Console.WriteLine(json);
The output looks like
{
"version": "2",
"mangas": [
{
"manga": [
"sample",
"manganame",
1234567890,
0,
0
],
"chapters": [
{
"u": "urlexample",
"r": 1
},
{
"u": "urlexample",
"r": 1
},
{
"u": "urlexample",
"r": 1
}
]
}
]
}
and live view at .net fiddle
Based on your comment, if you want to have various chapters for each "Manga", you have to change your data structure and that changes the Result Json you want.
maybe something like this?
public partial class Root
{
public long Version { get; set; }
public Mangas[] Mangas { get; set; }
}
public partial class Mangas
{
public Manga[] Manga { get; set; }
}
public partial class Chapter
{
public string U { get; set; }
public long R { get; set; }
}
public partial struct Manga
{
public long? Integer;
public string String;
public Chapter[] Chapters { get; set; }
}
Iterate through chapters. Solution below.
class Parent
{
public int Version { get; set; }
public List<Manga> mangas { get; set; }
}
class Manga
{
public List<object> manga { get; set; }
public List<Chapter> chapters { get; set; }
}
class Chapter
{
public string u { get; set; }
public int r { get; set; }
}
void createJson(String manganame, string mId, String mangaoid, long sourceid)
{
var json = new Parent()
{
Version = 2,
mangas = new List<Manga>()
{
new Manga()
{
manga = new List<object>{ "/manga/"+mangaoid, manganame, sourceid, 0, 0 },
chapters = Chapters(),
}
}
};
var sjson = JsonConvert.SerializeObject(json, Formatting.Indented);
File.WriteAllText(#"C:\Users\Izurii\Desktop\oi.json", sjson);
}
List<Chapter> Chapters()
{
List<Chapter> chapters = new List<Chapter>();
for(int i = 0; i < links.Count; i ++)
{
chapters.Add(
new Chapter()
{
u = links[i],
r = 1,
});
}
return chapters;
}

handle empty Json Array from object

I have a json object that returns two empty arrays
"subQuestions": [] and "answers": []
I have created classes for the object, but I cannot get it to work,
this is what I have so far.
Object
"questions": [
{
"questionId": "1",
"question": "Ipsum",
"helpText": null,
"questionType": "MultipleChoice",
"answerChoices": [
{
"answerChoiceId": "b2b-2.01-answer1",
"value": "Lorem",
"subQuestions": []
}
],
"answers": []
}
Classes
public class AnswerChoice
{
public string answerChoiceId { get; set; }
public string value { get; set; }
public List<object> subQuestions { get; set; }
}
public class Question
{
public string questionId { get; set; }
public string question { get; set; }
public object helpText { get; set; }
public string questionType { get; set; }
public List<AnswerChoice> answerChoices { get; set; }
public List<object> answers { get; set; }
}
public class ObjectRoot
{
public string productId { get; set; }
public List<Question> questions { get; set; }
}
var jsonBody = new ObjectRoot()
{
productId = productId,
questions = new[]
{
new Question() {
questionId = "b2b-2.01",
question ="Vad är syftet med ert engagemang hos oss?",
helpText = null,
questionType = "MultiChoise",
answerChoices = new []{
new AnswerChoice{
answerChoiceId = "",
value = "",
**HERE is what it gets tricky for me**
}
}
}
}
};
The tricky part for me is after value = "", and the subQuestion object needs to be added, have tried multiple ways but no luck.
In your classes all collections is List not array. So to make it work you need to call ToList extension method. And for empty collections just call List constructor
var jsonBody = new ObjectRoot()
{
productId = "productId",
questions = new[]
{
new Question() {
questionId = "b2b-2.01",
question ="Vad är syftet med ert engagemang hos oss?",
helpText = null,
questionType = "MultiChoise",
answerChoices = new []{
new AnswerChoice{
answerChoiceId = "",
value = "",
subQuestions = new List<object>() // empty collection
}
}.ToList(),
answers = new List<object>()
}
}.ToList()
};

Use Linq or C# to parse Json

I am getting familiar with C# and Linq and appreciate any help. It should be easy for someone who works with it. I have a Json object that returns contact information. I also have a list of ids. I need to compare the list to the Json object and wherever the value in the list matches the userclientcode in the Json object, I need to extract the following information (only for the matches):
clienttaxonomy (if not empty)
fullname (if not empty)
[0]contactdata ( -> email if not null or empty)
[1]contactdata (-> address if not null or empty)
[2]contactdata (-> phone number if not null or empty)
First List
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354",
"12342341", "123412322", "163341234", "2345234115", "8967896", "75626234 };
JSON object returned with:
return JsonConvert.DeserializeObject<RelatedContacts>(json)?.list;
This is the Json object:
[![Json object][1]][1]
This is the Json string (unescaped):
{
"type": "com.kurtosys.api.userprofile.domain.RelatedContactList",
"list": [{
"objectlistid": 5678765,
"objectlisttypeid": 4567876,
"objectlistname": "ALL.National",
"clienttaxonomyid": 765677,
"clienttaxonomy": "National Wholesaler",
"order": 1,
"contacts": [{
"personid": 7654345678,
"fullname": "Person Jallo",
"userid": 876567,
"userclientcode": "341234123",
"contactdetails": [{
"contactid": 8765567,
"contacttypeid": 4565,
"contactdata": "person.contact#site.com"
}, {
"contactid": 876545678,
"contacttypeid": 4565,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 87654567,
"contacttypeid": 4584,
"contactdata": "410-413-2640"
}]
}]
}, {
"objectlistid": 765678,
"objectlisttypeid": 40400461,
"objectlistname": "RM.Internal",
"clienttaxonomyid": 7567898,
"clienttaxonomy": "Internal Regional Wholesaler",
"order": 2,
"contacts": [{
"personid": 56789876,
"fullname": "Jackson Man",
"userid": 876567,
"userclientcode": "1012275",
"contactdetails": [{
"contactid": 309598309,
"contacttypeid": 76546,
"contactdata": "mister.jackson##site.com.com"
}, {
"contactid": 876567,
"contacttypeid": 4581,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 876567,
"contacttypeid": 2342,
"contactdata": "123-413-2604"
}]
}]
}, {
"objectlistid": 309571364,
"objectlisttypeid": 40400461,
"objectlistname": "RM.External",
"clienttaxonomyid": 309580710,
"clienttaxonomy": "External Regional Wholesaler",
"order": 3,
"contacts": [{
"personid": 302736188,
"fullname": "Phal Sumi",
"userid": 303826019,
"userclientcode": "163341234",
"contactdetails": [{
"contactid": 309598253,
"contacttypeid": 2342,
"contactdata": "misters.emailas#site.com"
}, {
"contactid": 309611930,
"contacttypeid": 2342,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 34234132,
"contacttypeid": 3422,
"contactdata": "342-803-1793"
}]
}]
}]
}
How do I
1] Select using Linq and Lambdas and put in a list fullname, email, address etc from the deserialized object ?
2]compare with first list and only transfer those items where the userclientcode == the number in list A.
I have tried:
var query5 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
var selected = relatedContact.Where(p => p.contacts
.Any(a => fileContactIds.Contains(p.contacts))
.ToList();
var query2 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
.Select(s => new
{
Description = s.clienttaxonomy,
Fullname = s.contacts[0].fullname,
Email = s.contacts[0].contactdetails[0].contactdata,
Address = s.contacts[0].contactdetails[1].contactdata,
PhoneNumber = s.contacts[0].contactdetails[2].contactdata
});
But don't really know what I'm doing it seems. Any suggestions on how to get the required sections ? I think part of the reason is that the contactdata is a list.
Thanks all
You can create a classes for the desearlization of JSON Object like this
public class Rootobject
{
public string type { get; set; }
public List[] list { get; set; }
}
public class List
{
public int objectlistid { get; set; }
public int objectlisttypeid { get; set; }
public string objectlistname { get; set; }
public int clienttaxonomyid { get; set; }
public string clienttaxonomy { get; set; }
public int order { get; set; }
public Contact[] contacts { get; set; }
}
public class Contact
{
public long personid { get; set; }
public string fullname { get; set; }
public int userid { get; set; }
public string userclientcode { get; set; }
public Contactdetail[] contactdetails { get; set; }
}
public class Contactdetail
{
public int contactid { get; set; }
public int contacttypeid { get; set; }
public string contactdata { get; set; }
}
And then to extract the selected information we can also create a another class like
public class ExtractedInfo
{
public string ocClientTaxonomy { get; set; }
public string ocFullName { get; set; }
public CTDetails ocContactDetails { get; set; }
}
public class CTDetails
{
public string ocCTAddress { get; set; }
public string ocCTEmail { get; set; }
public string ocCTPhoneNumber { get; set; }
}
Now we have to find all the data from JSON
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354", "12342341", "123412322", "163341234", "2345234115", "8967896", "75626234" };
//Read JSON from txt file. You can do it by your way
string myjson = File.ReadAllText("Some.txt");
string ctphno, ctadd, ctemail, cltax, ctfullname;
List<ExtractedInfo> ei = new List<ExtractedInfo>();
CTDetails ctdtl = new CTDetails();
ExtractedInfo eiex = new ExtractedInfo();
//Deserialize the JSON string to Object.
Rootobject AllData = JsonConvert.DeserializeObject<Rootobject>(myjson);
//Finding all data in List Class
foreach(List lst in AllData.list)
{
cltax = lst.clienttaxonomy; // you can directly put eiex.ocClientTaxonomy = lst.clienttaxonomy;
foreach(Contact ct in lst.contacts)
{
//To check if value in the list matches the objectlistid in the Json object
if(fileContactIds.Contains(lst.objectlistid.ToString()))
{
ctfullname = ct.fullname; // you can directly put eiex.ocFullName = ct.fullname;
foreach(Contactdetail ctd in ct.contactdetails)
{
//Here we are trying to find the Match for Email.
if(Regex.IsMatch(ctd.contactdata, #"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase))
{
ctemail = ctd.contactdata;
ctdtl.ocCTEmail = ctemail;
}
//Here We trying to find the match for Phone Number.
else if(Regex.IsMatch(ctd.contactdata, #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}", RegexOptions.IgnoreCase))
{
ctphno = ctd.contactdata;
ctdtl.ocCTPhoneNumber = ctphno;
}
//If NOthing matches than it might be address (Assumed)
else
{
ctadd = ctd.contactdata;
ctdtl.ocCTAddress = ctadd;
}
}
eiex.ocFullName = ctfullname;
}
}
eiex.ocClientTaxonomy = cltax;
eiex.ocContactDetails = ctdtl;
ei.Add(eiex);
}
Hope this helps and fit in your requirements.

Json not returning the correct values in the desired pattern

I need this as my json return. This data is being pulled from the DB but currently I am using static data.
{
"data": [
{
"id": 1,
"latitude":17.3700,
"longitude": 78.4800,
"gallery":
[
"assets/img/items/1.jpg"
]
}
]
}
I have tried this in my code behind but I am not getting the desired result.
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public List<> getData()
{
Account account = new Account
{
id = 1,
latitude = "17.3700",
longitude ="78.4800",
gallery = new List<string>
{
"assets/img/items/1.jpg",
"assets/img/items/2.jpg",
}
};
return new JavaScriptSerializer().Serialize(account);
}
public class Account
{
public int id { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public IList<string> gallery { get; set; }
}
Result:
{
"id":2,
"latitude":"17.3700",
"longitude":"78.4800",
"gallery":["assets/img/items/1.jpg","assets/img/items/2.jpg"]
}
You need to create a new class with the data property:
public class Result { public object[] Data { get; set; } }
and return that:
public string getData()
{
Result result = new Result
{
Data = new [] { new Account { id = 1, ... } }
};
return new JavaScriptSerializer().Serialize(result);
}

Categories