How to pass User object into json to send to api endpoint? - json

I am getting this error 400 when trying to submit a POST.
"$.User": [
"The JSON value could not be converted to WebApi.Models.User. Path: $.User | LineNumber: 5 | BytePositionInLine: 19."
]
}
This is my Order Model in asp.net core 3 api
namespace WebApi.Models
{
public class DispatchRequest
{
[Key]
public int DispatchRequestID { get; set; }
[Required]
[Column(TypeName = "nvarchar(100)")]
public string DispatchRequestNo { get; set; }
[Required]
public string CreatedOn { get; set; }
[Required]
[Column(TypeName = "int(10)")]
[ForeignKey("UserID")]
public User User { get; set; }
public int UserID { get; set; }
public ICollection<DispatchRequestItem> DispatchRequestsItems { get; set; }
}
}
So it seems like the problem is that the value for the json key "User" is not a user object. How do I do that, in order to make the POST request pass?
I am using angular to send the post request, but it didnt work, so I am using Postman now to try and troubleshoot and realized the above.

As a general tip, I would first recommend you to start using Swagger, its a beautiful thing that makes you a page in apiURL/swagger where you can test all your endpoints and have examples of what object each endpoint needs. Also you can scaffold your angular api with the swagger.json and https://www.npmjs.com/package/api-client-generator
Why would you have as Required the object User? having the UserId as required would do just fine. Also if you are attaching the User object , you have to double check not to update the user in the db when EF Core does its magic

Related

Form-Data array not being deserialized to request dto

I'm trying to do filtering function for KendoUI Grid.
Kendo sends data as form-data:
take:20
skip:0
page:1
pageSize:20
filter[filters][0][operator]:eq
filter[filters][0][value]:abc
filter[filters][0][field]:No
filter[logic]:and
I tried to deserialize it using dto:
public class FilteringRule
{
public string Field { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
}
public class FilteringInfo
{
public string Logic { get; set; }
public FilteringRule[] Filters { get; set; }
}
public class FilteredQuery
{
FilteringInfo Filter { get; set; }
//...
}
but deserialization fails:
'filter[filters][0][operator]' does not exist on type 'FilteredQuery'
'filter[filters][0][value]' does not exist on type 'FilteredQuery'
'filter[filters][0][field]' does not exist on type 'FilteredQuery'
'filter[logic]' does not exist on type 'FilteredQuery'
How to make this work? When I manually send json instead of form-data it works.
Can kendo send json? Setting contentType: "application/json" in datasource doesn't help. Kendo still sends data as form-data, servicestack throws error: "unable to bind request".
ServiceStack allows sending complex objects via QueryStrings using the lightweight JSV Syntax which from your example would look something like:
?filter={filters:[{operator:eq,value:abc,field:no}],{logic:and}}
But since Kendo is unlikely to support this syntax, you would be better off sending JSON if it supports it which would naturally map to your DTOs.

JSON array is converting to a generic list, but not converting to a generic collection. Why?

I am sending a Json Array from the client web application to asp.net webapi.
For example,
{
"SurveyId":3423,
"CreatorId":4235,
"GlobalAppId":34,
"AssociateList":[
{"AssociateId":4234},
{"AssociateId":43},
{"AssociateId":23423},
{"AssociateId":432}
],
"IsModelDirty":false,
"SaveMode":null
}
Here Associate List is a JSON Array,
Usually it will automatically serialize to a List<> object.
Using the below code ,i am posting the response to the WebApi
public IEnumerable<Associate> Post(ResponseStatus responseStatus)
{
return this.responsestatusrepository.ResponseStatusCheck(responseStatus);
}
The ResponseStatus class is shown below.
public class ResponseStatus : AppBaseModel
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public List<Associate> AssociateList { get; set; }
}
I have changed the List<> to Collection<> as a part of my code analysis correction.
ie, public Collection<Associate> AssociateList { get; set; }
But it is always getting a null value when we are using collection instead of List. Is there any specific reason for this?
Ok, I think I will have to answer this in an indirect way.
What you are passing on to the server is an array of objects (in JSON format), but once you start processing this in C# the array of objects is now treated as a single c# object. Inside this object, your model expects one of the fields to be a Collection of Associate.
Right, when I work with JSON data similar to whats mentioned in this case - I prefer to use Newtonsofts' JOject.
So here is how I made the C# object with the JSON data you provided:
Used your model:
public class ResponseStatus
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public Collection<Associate> AssociateList { get; set; }
}
public class Associate
{
public int AssociateId { get; set; }
}
Made a routine which takes string (the JSON data), and returns an object of type ResponseStatus:
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
---------------------------------------------------------------------
public static ResponseStatus GetResponseStatusObject(string jsonData)
{
JObject jObject = JObject.Parse(jsonData);
return jObject.ToObject<ResponseStatus>();
}
Now when I call this method and pass on the exact same JSON data which you provided, I get this:
This might not directly solve your problem, but hopefully guide you in the right direction in understanding array/object serialization when working with JavaScript/C#.
Best of luck!

Can't post complex object through Json to Web API - HTTP Error 500

I'm using a REST client that I have already used to post other complex objects in my database.
I can't post too much code because it is work-related but here is what I am trying to send to the web API from my rest client:
{"BinID":"PBN0012","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-07-11T17:51:49.670028+00:00","ModifiedByUID":"00000000-0000-0000-0000-000000000000","BatchBins":[],"BinsInUses":[]}
That is the object after serialized by JsonConvert.
I'm using HttpWebResponse (and getting an HTTP 500 Internal Server Error - and System.ArgumentException on Xamarin "Illegal Characters in Path".
Even when I try to post directly through SOAP UI I get this message:
{
"$id": "1",
"Message": "An error has occurred."
}
This is what I get when I type "(IP Address....)/Api/Bins/GetBins into my browser:
[{"$id":"1","BatchBins":[],"BinsInUses":[{"$id":"2","Bin":{"$ref":"1"},"BinID":"PBN0001","EntrySequence":1}],"BinID":"PBN0001","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"3","BatchBins":[],"BinsInUses":[{"$id":"4","Bin":{"$ref":"3"},"BinID":"PBN0002","EntrySequence":2}],"BinID":"PBN0002","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"5","BatchBins":[],"BinsInUses":[{"$id":"6","Bin":{"$ref":"5"},"BinID":"PBN0003","EntrySequence":3}],"BinID":"PBN0003","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"7","BatchBins":[],"BinsInUses":[{"$id":"8","Bin":{"$ref":"7"},"BinID":"PBN0004","EntrySequence":4}],"BinID":"PBN0004","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"9","BatchBins":[],"BinsInUses":[],"BinID":"PBN0005","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"10","BatchBins":[],"BinsInUses":[],"BinID":"PBN0006","BinType":"Dryer","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"11","BatchBins":[],"BinsInUses":[],"BinID":"PBN0007","BinType":"Dryer","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"12","BatchBins":[],"BinsInUses":[],"BinID":"PBN0008","BinType":"Dryer","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"13","BatchBins":[],"BinsInUses":[],"BinID":"PBN0009","BinType":"Dryer","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"14","BatchBins":[],"BinsInUses":[],"BinID":"PBN0010","BinType":"Dryer","IsDeleted":false,"ModifiedDateTime":"2014-06-02T00:00:00","ModifiedByUID":"b6c1b64f-874b-4180-949a-97c77cc4194c"},{"$id":"15","BatchBins":[],"BinsInUses":[],"BinID":"PBN0011","BinType":"Wash","IsDeleted":false,"ModifiedDateTime":"2014-07-03T15:34:11.67","ModifiedByUID":"9f05ab31-2521-4a7e-9258-b7092aae5058"}]
The Bin class consists of:
public partial class Bin
{
public Bin()
{
this.BatchBins = new HashSet<BatchBin>();
this.BinsInUses = new HashSet<BinsInUse>();
}
public string BinID { get; set; }
public string BinType { get; set; }
public bool IsDeleted { get; set; }
public System.DateTime ModifiedDateTime { get; set; }
public System.Guid ModifiedByUID { get; set; }
public virtual ICollection<BatchBin> BatchBins { get; set; }
public virtual ICollection<BinsInUse> BinsInUses { get; set; }
}
And the table for "Bin" in the database has the following columns:
BinID (PK, nvarchar(100),not null)
BinType (nvarchar(5), not null)
IsDeleted (bit, not null)
ModifiedDateTime (datetime,not null)
ModifiedByUID (uniqueidentifier, not null)
I know I used the correct types for each of these considering my other objects passed through just fine. Any Suggestions on how to get the json string to post??
Just so everybody knows, in case they get this kind of error and can't find a solution, you might have the same problem I had.
I'd copied and pasted methods in my API to save time (because many methods/classes had similar names) and I ended up with two methods with the same exact name; I had forgotten to change the method name. Just for future reference.

JSON deserialization throws circular reference ONLY in live build

I have a strange issue that I can't wrap my head around. I am trying to create an "export to csv" function for my MVC4 application where the relevant JSON is passed via an ajax call to my ActionResult. The ActionResult deserializes the stringify'd JSON (with JSON.Net), writes it to a file in csv format, then returns the server path to the new file. My success callback then receives the path and calls the url to download.
This works fine locally, but on my live test server I get the following exception:
A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'.
The JSON (and subsequently the objects they are deserialized to) are slightly complex. They come from a grouped subset of a SlickGrid DataView. I was getting circular reference exceptions when I included the aggregate information for column totals (this is only relevant to those that are versed in SlickGrid, I do not believe the data being passed to the server is an issue), but I've removed them before passing the JSON to the server. Here is my JSON to C# class structure:
[Serializable]
public class Row
{
public int id { get; set; }
public DateTime DateCreated { get; set; }
public int RefNo { get; set; }
public string ClientName { get; set; }
public string Plate { get; set; }
public string Address1 { get; set; }
public int? ProductID { get; set; }
public string Product { get; set; }
public string S1 { get; set; }
public string S2 { get; set; }
}
[Serializable]
public class RootReportObject
{
public bool __group { get; set; }
public int level { get; set; }
public int count { get; set; }
public string value { get; set; }
public string title { get; set; }
public int collapsed { get; set; }
public List<Row> rows { get; set; }
public object groups { get; set; }
public string groupingKey { get; set; }
}
The only thing that I'm thinking is that, because of the way the data is structured, the List<> of rows in the root object may be throwing the circular references during deserializtion because a group does not necessarily have unique row references.
My question is why does it work fine locally?? I have no idea what I'm missing.
That's great that the [ScriptIgnore] attribute is helping. Also, something to be completely sure of is that all of your URL paths, including in your AJAX code, resolve correctly to the application root. When some of these are wrong, this is a notorious source of problems during the move from development to production.
It doesn't sound like it is necessarily the primary issue but I don't have any understanding of your app's design. It's definitely worth looking over.

Sencha Touch and WCF REST post parameter always null

I'm building an application using sencha touch 1.1 in the client side and WCF REST services in the server side. I'm facing some problems when the sencha sore syncs data, the parameter sent to update method is always null. This is the c# definition of the parameter:
namespace HomeInventory.Application.Service.Dto{
[Serializable]
[DataContract(Namespace = "http://xxxxx.xxx.org/shopinglist")]
public class DtoShopingList{
[DataMember]
public long Id { get; set; }
[DataMember]
public string CreationDate { get; set; }
[DataMember]
public string ListName { get; set; }
[DataMember]
public DtoUser User { get; set; }
[DataMember]
public DtoListItem[] Items { get; set; }
[DataMember]
public bool IsDefault { get; set; }
}
This the json posted by sencha to the server:
{"records":"[{\"Id\":0,\"ListName\":\"Default\",\"CreationDate\":\"23/01/2012\",\"IsDefault\":true,\"items\":[]}]"}
It seems to me that WCF JSON serializer is unabled to parse the JSON to the corresponding class. Any help in how to fix it?
Thanks in advance.
Well, in case it serves someone else, I got rid of the backslashes with the following settings in the proxy.
writer: {
encode: false,
type: 'json'
}
Best regards.