I using C# with Web API. I have this server method:
[System.Web.Http.HttpPost]
public HttpResponseMessage Test(CompareOutput model)
{
return new HttpResponseMessage(HttpStatusCode.OK);
}
This is my data-model:
public class CompareOutput
{
public CompareOutput(int wc, int source_start, int source_end, int suspected_start, int suspected_end)
{
this.WordsCount = wc;
this.SourceStartChar = source_start;
this.SourceEndChar = source_end;
this.SuspectedStartChar = suspected_start;
this.SuspectedEndChar = suspected_end;
}
public CompareOutput()
{
}
[JsonProperty("wc")]
public int WordsCount { get; set; }
[JsonProperty("SoS")]
public int SourceStartChar { get; set; }
[JsonProperty("SoE")]
public int SourceEndChar { get; set; }
[JsonProperty("SuS")]
public int SuspectedStartChar { get; set; }
[JsonProperty("SuE")]
public int SuspectedEndChar { get; set; }
public override string ToString()
{
return string.Format("{0} -> {1} | {2} -> {3}", this.SourceStartChar, this.SourceEndChar, this.SuspectedStartChar, this.SuspectedEndChar);
}
}
Now, I trying to call this method with this data (placed in BODY of the HTTP request):
{
"wc":11,
"SoS":366,
"SoE":429,
"SuS":393,
"SuE":456
}
This call isn't working. All the int members getting defualt values ("0").
When I trying to send this HTTP-BODY, it's working good:
{
"WordsCount":11,
"SourceStartChar":366,
"SourceEndChar":429,
"SuspectedStartChar":393,
"SuspectedEndChar":456
}
I can understand from that - alternative names (which defined in the model with JsonPropertry attribute) isn't working.
How can I solve it?
Thank you.
Try to decorate your properties this way...
[JsonProperty(PropertyName = "wc")]
public int WordsCount { get; set; }
[JsonProperty(PropertyName = "SoS")]
public int SourceStartChar { get; set; }
[JsonProperty(PropertyName = "SoE")]
public int SourceEndChar { get; set; }
[JsonProperty(PropertyName = "SuS")]
public int SuspectedStartChar { get; set; }
[JsonProperty(PropertyName = "SuE")]
public int SuspectedEndChar { get; set; }
Related
I'm trying to use Refit for easy Web API usage.
Trying to use the API of api.stackexchange.com.
FYI - It must be done with Refit.
Main code:
static async Task Main(string[] args)
{
//Ignore the Dependecy injection.... Same error happens without it.
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
{
services
.AddRefitClient<IStackOverFlowAPIClient>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.stackexchange.com"));
}).Build();
IStackOverFlowAPIClient client = host.Services.GetRequiredService<IStackOverFlowAPIClient>();
var root = await client.GetAnswerById(287944); //Breaks here
foreach (var question in root.items)
{
Console.WriteLine(question.ToString());
}
}
Interface with functions:
internal interface IStackOverFlowAPIClient
{
[Get("/2.3/answers/{id}?order=desc&sort=activity&site=stackoverflow")]
Task<Root> GetAnswerById(int id); //Tried to use dynamic instead of Root
}
Classes that represent the JSON:
public class Root
{
public List<Item> items { get; set; }
public bool has_more { get; set; }
public int quota_max { get; set; }
public int quota_remaining { get; set; }
public Root(List<Item> items, bool has_more, int quota_max, int quota_remaining)
{
this.items = items;
this.has_more = has_more;
this.quota_max = quota_max;
this.quota_remaining = quota_remaining;
}
}
public class Item
{
public Owner owner { get; set; }
public bool is_accepted { get; set; }
public int score { get; set; }
public int last_activity_date { get; set; }
public int last_edit_date { get; set; }
public int creation_date { get; set; }
public int answer_id { get; set; }
public int question_id { get; set; }
public string content_license { get; set; }
public Item(Owner owner, bool is_accepted, int score, int last_activity_date, int last_edit_date, int creation_date, int answer_id, int question_id, string content_license)
{
owner = owner;
is_accepted = is_accepted;
score = score;
last_activity_date = last_activity_date;
last_edit_date = last_edit_date;
creation_date = creation_date;
answer_id = answer_id;
question_id = question_id;
content_license = content_license;
}
}
public class Owner
{
public int account_id { get; set; }
public int reputation { get; set; }
public int user_id { get; set; }
public string user_type { get; set; }
public string profile_image { get; set; }
public string display_name { get; set; }
public string link { get; set; }
public Owner(int account_id, int reputation, int user_id, string user_type, string profile_image, string display_name, string link)
{
this.account_id = account_id;
this.reputation = reputation;
this.user_id = user_id;
this.user_type = user_type;
this.profile_image = profile_image;
this.display_name = display_name;
this.link = link;
}
}
Whenever I try to use the function client.GetAnswerById(287944), I get the following exception:
System.Text.Json.JsonException: ''0x1F' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'
Thing is that I'm getting the same error when I use other techniques instead of refit (for testing, as i must use refit)
What am I missing? Do I need to encode the response? If so how is that done?
I am trying to post data to a web api with this structure:
Ledger Header and a list of ledger details. This is my class in the web api for the two:
public class PropertyLedgerDetail
{
[Key]
public int LedgerDetailID { get; set; }
public int LedgerID { get; set; }
public int? TransactionID { get; set; }
public int? TransactionTypeID { get; set; }
public double? Amount { get; set; }
public double? PaymentAmount { get; set; }
public int Month { get; set; }
public int Year { get; set; }
[StringLength(1000)]
public string Remarks { get; set; }
public bool Voided { get; set; }
public DateTime? PostingDateTime { get; set; }
}
public class PropertyLeger
{
[Key]
public int LedgerID { get; set; }
public int CollectingAgentID { get; set; }
public int UnitID { get; set; }
public int PaymentTypeID { get; set; }
[StringLength(15)]
public string ORNumber { get; set; }
public int? VoidedLedgerID { get; set; }
public bool? Voided { get; set; }
[StringLength(100)]
public string Remarks { get; set; }
public DateTime? TransactionDateTime { get; set; }
public DateTime? PostingDateTime { get; set; }
}
and this is to combine the two classes so I can receive it from my frontend:
public class AddLedger
{
public PropertyLeger PropertyLedger { get; set; }
public List<PropertyLedgerDetail> PropertyLedgerDetails { get; set; }
}
In my Angular front end, this is how I set up the properties to send:
Get values from 2 forms
add() {
const PropertyLedgerModel: any = {
CollectingAgentID: this.CollectingAgentID.value,
UnitID: this.unitId,
PaymentTypeID: this.PaymentTypeID.value,
ORNumber: this.ORNumber.value,
VoidedLedgerID: this.VoidedLedgerID.value,
Voided: this.Voided.value,
Remarks: this.Remarks0.value
}
const PropertyLedgerDetailsModel: any[] = this.dataSource;
const model: any = {
PropertyLedger: PropertyLedgerModel,
PropertyLedgerDetails: PropertyLedgerDetailsModel
}
this.pps.addLedger(model)
.subscribe((data: any) => {
debugger;
if (data.StatusCode === 200) {
this.ts.success(data.ReasonPhrase);
} else {
this.ts.error(data.ReasonPhrase);
}
},
err => {
this.ts.error('An error has occured in saving payment(s): ' +err);
})
}
To actually send this to the web api
addLedger(model: any) {
debugger;
const ep = this.rootUrl + '/api/newpropertyledger';
const PropertyLedgerModel: any = model.PropertyLedger;
const PropertyLedgerDetailsModel: any [] = model.PropertyLedgerDetails;
const Model: any = {
PropertyLedger: PropertyLedgerModel,
PropertyLedgerDetails: PropertyLedgerDetailsModel
};
return this.http.post(ep, Model);
}
I created a debug point on the part that will receive the data:
but the data from the front end doesn't reach the web api. I just get this error:
Message:"No HTTP resource was found that matches the request URI 'http://localhost:15232/api/newpropertyledger'."
MessageDetail:"No type was found that matches the controller named 'newpropertyledger'."
Please show me how to do it right. Thank you so much.
Assuming your api routing is correct i.e any of the api methods are getting hit, this should help..
addLedger(model: any) {
debugger;
const ep = this.rootUrl + '/api/newpropertyledger';
const PropertyLedgerModel: any = model.PropertyLedger;
const PropertyLedgerDetailsModel: any [] = model.PropertyLedgerDetails;
const Model: any = {
PropertyLedger: PropertyLedgerModel,
PropertyLedgerDetails: PropertyLedgerDetailsModel
};
return this.http.post(ep, JSON.stringify(ledger));
}
public HttpResponseMessage NewPropertyLedger(string data)
{
AddLedger ledger = JsonConvert.DeserializeObject<AddLedger>(data);
}
I am using Restsharp library to do Webservice operations.I tried to access data from the link(http://www.mocky.io/v2/595616d92900003d02cd7191) and print it in Console but I am not getting any response.When I used breakpoints,Response is showing null.Here's my code to get data from the link.
private async void GetItemsFromJSON()
{
IRestClient client = new RestClient("http://www.mocky.io/v2/595616d92900003d02cd7191");
IRestRequest request = new RestRequest(Method.GET);
request.RequestFormat = DataFormat.Json;
try
{
await Task.Run(() =>
{
IRestResponse<List<ItemDetails>> response = client.Execute<List<ItemDetails>>(request);
var Items = SimpleJson.DeserializeObject<ItemDetails>(response.Content);
Console.WriteLine(response.Content);
}
public class ItemDetails
{
public List<Itemschema> items { get; set; }
}
public class Itemschema
{
public int id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public int attribute_set_id { get; set; }
public int price { get; set; }
public int status { get; set; }
public int visibility { get; set; }
public string type_id { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public int weight { get; set; }
}
Am I missing something here?My schema class which corresponds to the Json data is shown above.
I suspect that:
IRestResponse<List<ItemDetails>> response = client.Execute<List<ItemDetails>>(request);
should be:
IRestResponse<ItemDetails> response = client.Execute<ItemDetails>(request);
http://www.mocky.io/v2/595616d92900003d02cd7191 seems to return an items property which contains an array of schemas. That maps closer to ItemDetails than List<ItemDetails>.
This complete sample works, so you may want to compare it with your code:
using System;
using System.Collections.Generic;
using RestSharp;
namespace Test
{
public class ItemDetails
{
public List<Itemschema> items { get; set; }
}
public class Itemschema
{
public int id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public int attribute_set_id { get; set; }
public int price { get; set; }
public int status { get; set; }
public int visibility { get; set; }
public string type_id { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public int weight { get; set; }
}
public class Program
{
static void Main(string[] args)
{
IRestClient client = new RestClient("http://www.mocky.io/v2/595616d92900003d02cd7191");
IRestRequest request = new RestRequest(Method.GET);
request.RequestFormat = DataFormat.Json;
IRestResponse<ItemDetails> response = client.Execute<ItemDetails>(request);
var Items = SimpleJson.DeserializeObject<ItemDetails>(response.Content);
Console.WriteLine(Items.items.Count);
Console.ReadLine();
}
}
}
I have the following two classes:
public class TestQuestionModel
{
public TestQuestionModel()
{
this.Answers = new List<TestQuestionAnswerModel>();
}
public int TestId { get; set; }
public int TestQuestionId { get; set; }
public int QuestionNumber { get; set; }
public virtual ICollection<TestQuestionAnswerModel> Answers { get; set; }
}
public class TestQuestionAnswerModel
{
public int AnswerUId { get; set; }
public bool? Correct { get; set; }
public bool? Response { get; set; }
public string Text { get; set; }
}
What I would like to do is to store the Answers into a string and put into this class:
public class TestQuestion
{
public int TestId { get; set; }
public int TestQuestionId { get; set; }
public int QuestionNumber { get; set; }
public string AnswerString { get; set; }
}
Can someone tell me how I can do this in both directions (putting it in the string and taking it out)
Possible way:
public string Serialize(ICollection<TestQuestionAnswerModel> answers)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(answers);
}
public ICollection<TestQuestionAnswerModel> Deserialize(string data)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return (ICollection<TestQuestionAnswerModel>)serializer.Deserialize<ICollection<TestQuestionAnswerModel>>(data);
}
I'm scraping data from a variety of pages on a site, and I want to assign points to a total score based on whether or not elements (H1s, alt tags, meta titles; that sort of thing) exist, are unique or are duplicates. I'd like to create a method that can do this for every element I scrape, which I am using custom classes to store.
public class PageData
{
[Key]
[Required]
public int Id { get; set; }
[Required]
public string PageUrl { get; set; }
public string Analytics { get; set; }
public bool Paginated { get; set; }
public bool Flash { get; set; }
public bool Iframe { get; set; }
public bool NoIndexFollow { get; set; }
public bool SchemaTag { get; set; }
public virtual ICollection<Platform> Platforms { get; set; }
public virtual ICollection<AltTag> AltTags { get; set; }
public virtual ICollection<Canonical> Canonicals { get; set; }
public virtual ICollection<MetaTitle> MetaTitles { get; set; }
public virtual ICollection<MetaDesc> MetaDescs { get; set; }
public virtual ICollection<BlogLocation> BlogLocations { get; set; }
public virtual ICollection<H1> H1s { get; set; }
public virtual ICollection<H2> H2s { get; set; }
public virtual ICollection<H3> H3s { get; set; }
public virtual ICollection<ViewState> ViewStates { get; set; }
}
public class H1
{
public H1() { }
public H1(int id, string h1)
{
this.Id = id;
this.H1String = h1;
}
public override string ToString()
{
return H1String;
}
[Key]
public int KeyId { get; set; }
public string H1String { get; set; }
[ForeignKey("PageData")]
public int Id { get; set; }
[ScriptIgnore]
public virtual PageData PageData { get; set; }
}
Method to try allocate scores
public void pageCheck(SiteData site, dynamic pageObj, int lowAssignedScore, int highAssignedScore, int totalScore)
{
List<string> uniqueCheckList = new List<string>();
bool uniqueCheck = true;
foreach (PageData page in site.PageDatas)
{
if (pageObj.Count != 0)
{
foreach (var modelObj in pageObj)
{
if (uniqueCheckList.Contains(modelObj.ToString()))
{
totalScore =+ lowAssignedScore;
uniqueCheck = false;
break;
}
uniqueCheckList.Add(modelObj.ToString());
}
if (uniqueCheck)
{
totalScore += highAssignedScore;
}
}
}
I'm instantiating a new page object to pass in which element of the page I want:
PageData page = new PageData();
pageCheck(site, page.H1s, 4, 6, totalScore);
When I pass in page.H1s it is coming through as:
{System.Collections.Generic.List < Bescoured.Models.PageModels.H1 > }
Is there a way to do what I am trying to do in c#? Or will it not let me due to the static nature of the language? I started off by creating a method that was specific to H1 then trying to make it generic but it looks like I need to make a method for each element.
EDIT:
An example of how I would do it if I had make a method for each element
foreach (PageData page in site.PageDatas)
{
if (page.H1s.Count != 0)
{
foreach (H1 h1 in page.H1s)
{
if (h1s.Contains(h1.H1String))
{
totalScore += 4;
uniqueCheck = false;
break;
}
h1s.Add(h1.H1String);
}
if (uniqueCheck)
{
totalScore += 6;
}
}
}
I see you're only using the ToString() method of a element. Why not pass a IEnumerable< string> into it?
public void pageCheck(SiteData site, IEnumerable<string> pageObj, int lowAssignedScore, int highAssignedScore, int totalScore)
Usage:
pageCheck(site, page.H1s.Select(item => item.ToString()), 4, 6, totalScore);
pageCheck(site, page.AltTags.Select(item => item.ToString()), 4, 6, totalScore);
I'll always try to avoid dynamics, unless there's no other option.