发布关系数据时无法反序列化当前 JSON 对象
Cannot deserialize the current JSON object while posting relational data
好的,这里有很多问题和答案,如果你知道这个的确切副本,请指出我那里,但我太笨了,不明白如何让它发挥作用。
我想给工作添加一个工人,在到达 ModelState 之前一切都很好。这是我正在执行的步骤。
- 填写表格
我提交表单和控制台断点。
Name = "test", Description = "test",
worker = {Id: 21, FirstName: "Will", LastName: "Smith", Job: null}
Angular 控制台中的服务
jobs = {Name: "test", Description: "test", worker: {…}}
Not sure why the dots in the brackets.
达到 API 方法但模型状态失败。
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
在浏览器控制台中我得到:
Message:"The request is invalid."
ModelState:job.worker.Id:["Cannot deserialize the current JSON object (e.g. {…N object. Path 'worker.Id', line 1, position 16."]
来自 ModelState 的完整错误消息是:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type
'System.Collections.Generic.ICollection`1[TestRotaru.Models.Worker]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be deserialized from a JSON
object. JsonObjectAttribute can also be added to the type to force it
to deserialize from a JSON object. Path 'worker.Id', line 1, position
51.
到目前为止,这就像一个重复的问题,但我尝试了一些东西,但我不理解答案中的某些内容。
我尝试用以下属性装饰我的模型:
These on top of the class
//[Serializable]
//[DataContract(IsReference = true)]
//[JsonObject(MemberSerialization.OptIn)]
On properties
//[JsonProperty]
现在我没有头绪,我不明白的事情:
var dict = JsonConvert.DeserializeObject
<Dictionary<string, Item>>(*Where this string comes from*);
这只是一个示例,我关心的是括号中的字符串,而不是字典或其他内容。
这是我的方法:
[ResponseType(typeof(Job))]
public IHttpActionResult PostJob(Job job)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
job.DueDate = DateTime.Now;
db.Job.Add(job);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = job.Id }, job);
}
在所有关于此问题的答案中,每个人的圆括号中都有那个随机的 json 字符串......我应该从哪里得到它?
这是我的模型:
工作模型:
//[Serializable]
//[DataContract(IsReference = true)]
//[Serializable()]
//[JsonObject(MemberSerialization.OptIn)]
public class Job
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public string Description { get; set; }
[JsonProperty]
public DateTime DueDate { get; set; }
[JsonProperty]
public bool IsCompleted { get; set; }
//[JsonProperty]
//[System.Runtime.Serialization.IgnoreDataMember]
public virtual ICollection<Worker> Worker { get; set; }
}
工人模型:
//[Serializable]
//[DataContract(IsReference = true)]
//[JsonObject(MemberSerialization.OptIn)]
public class Worker
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string FirstName { get; set; }
[JsonProperty]
public string LastName { get; set; }
//[JsonProperty]
//[System.Runtime.Serialization.IgnoreDataMember]
public virtual ICollection<Job> Job { get; set; }
}
Angular 组件和服务:
add(Name: string, Description: string, worker): void {
this.jobsServices.addJob({Name, Description, worker } as Jobs)
.subscribe(jobs => {
this.jobs.push(jobs);
});
}
addJob(jobs: Jobs): Observable<Jobs> {
return this.http.post<Jobs>(this.apiURL, jobs, httpOptions);
}
div class="row">
<div class="col-md-12">
<label class="labelInputs">Select Worker</label><br>
<select [(ngModel)]="worker" class="form-control">
<option [value]="0">Select Worker</option>
<option *ngFor="let worker of workers" [ngValue]="worker">{{worker.FirstName}} {{worker.LastName}}</option>
</select>
</div>
<button class="brn btn-lg btn-block btn-change" (click)="add(name.value, desc.value, worker)">Add Job</button>
好吧,这是一个很长的问题,但我想证明自己,我做了我的研究,我只是没有抛出错误消息并寻求解决方案,但这真的让我很紧张。
因为我正在发布关系数据并且我的控制台显示 ModelState{job.worker.Id: [,…]}
我该如何反序列化它?再加上我的 ModelState 在到达 API 时将 worker 显示为 null,我猜是因为它不是从 json 转换而来的,但值得知道。
感谢您的帮助。
所以,问题是在您的 SPA 上,您将 worker
作为单个对象发送,而您的 API 需要一个工作人员列表(数组)。现在我不知道你想要什么.. 但你可以通过改变你的 API 模型来修复它以期待一个工人或改变你的 SPA 发送工人列表。没有人可以回答你..取决于你的应用程序的要求。但是,我最好的猜测是一个工作可能有几个工人。所以:
Api 模型(大部分相同..只是删除了属性并将 Worker 更改为 Workers):
public class Job
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime DueDate { get; set; }
public bool IsCompleted { get; set; }
public virtual ICollection<Worker> Workers { get; set; }
}
public class Worker
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// This is an "array". your spa needs to send in this format.
public virtual ICollection<Job> Job { get; set; }
}
温泉码:
export class Job {
id: int;
name: string;
// other fields here..
// Workers property that maps API model
workers: Array<Worker>;
constructor(id: int, name: string [other fields..]) {
this.id = id;
// and so on..
}
public addWorker(worker) {
this.workers.push(worker);
}
}
export class Worker {
id: int;
firstName: string;
// other fields here.. No need for array of jobs here!
}
使用此模型,您可以在调用 API(添加函数)之前执行此操作:
add(Name: string, Description: string, worker: Worker): void {
// creates a job using constructor
const job = new Job(name, description);
// add Job via function(can even be more complex and add validation and so on..)
job.addWorker(worker);
this.jobsServices.addJob(job)
.subscribe(jobs => {
this.jobs.push(jobs);
});
}
这将调用带有 json 的 api,如下所示:
{
"id": 1,
"name": "some name",
[ other fields..]
"workers": [
{ "id:" 1, "name": "some worker name" }
]
}
好的,这里有很多问题和答案,如果你知道这个的确切副本,请指出我那里,但我太笨了,不明白如何让它发挥作用。
我想给工作添加一个工人,在到达 ModelState 之前一切都很好。这是我正在执行的步骤。
- 填写表格
我提交表单和控制台断点。
Name = "test", Description = "test", worker = {Id: 21, FirstName: "Will", LastName: "Smith", Job: null}
Angular 控制台中的服务
jobs = {Name: "test", Description: "test", worker: {…}} Not sure why the dots in the brackets.
达到 API 方法但模型状态失败。
if (!ModelState.IsValid) { return BadRequest(ModelState); }
在浏览器控制台中我得到:
Message:"The request is invalid."
ModelState:job.worker.Id:["Cannot deserialize the current JSON object (e.g. {…N object. Path 'worker.Id', line 1, position 16."]
来自 ModelState 的完整错误消息是:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.ICollection`1[TestRotaru.Models.Worker]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'worker.Id', line 1, position 51.
到目前为止,这就像一个重复的问题,但我尝试了一些东西,但我不理解答案中的某些内容。 我尝试用以下属性装饰我的模型:
These on top of the class
//[Serializable]
//[DataContract(IsReference = true)]
//[JsonObject(MemberSerialization.OptIn)]
On properties
//[JsonProperty]
现在我没有头绪,我不明白的事情:
var dict = JsonConvert.DeserializeObject
<Dictionary<string, Item>>(*Where this string comes from*);
这只是一个示例,我关心的是括号中的字符串,而不是字典或其他内容。
这是我的方法:
[ResponseType(typeof(Job))]
public IHttpActionResult PostJob(Job job)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
job.DueDate = DateTime.Now;
db.Job.Add(job);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = job.Id }, job);
}
在所有关于此问题的答案中,每个人的圆括号中都有那个随机的 json 字符串......我应该从哪里得到它?
这是我的模型:
工作模型:
//[Serializable]
//[DataContract(IsReference = true)]
//[Serializable()]
//[JsonObject(MemberSerialization.OptIn)]
public class Job
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public string Description { get; set; }
[JsonProperty]
public DateTime DueDate { get; set; }
[JsonProperty]
public bool IsCompleted { get; set; }
//[JsonProperty]
//[System.Runtime.Serialization.IgnoreDataMember]
public virtual ICollection<Worker> Worker { get; set; }
}
工人模型:
//[Serializable]
//[DataContract(IsReference = true)]
//[JsonObject(MemberSerialization.OptIn)]
public class Worker
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string FirstName { get; set; }
[JsonProperty]
public string LastName { get; set; }
//[JsonProperty]
//[System.Runtime.Serialization.IgnoreDataMember]
public virtual ICollection<Job> Job { get; set; }
}
Angular 组件和服务:
add(Name: string, Description: string, worker): void {
this.jobsServices.addJob({Name, Description, worker } as Jobs)
.subscribe(jobs => {
this.jobs.push(jobs);
});
}
addJob(jobs: Jobs): Observable<Jobs> {
return this.http.post<Jobs>(this.apiURL, jobs, httpOptions);
}
div class="row">
<div class="col-md-12">
<label class="labelInputs">Select Worker</label><br>
<select [(ngModel)]="worker" class="form-control">
<option [value]="0">Select Worker</option>
<option *ngFor="let worker of workers" [ngValue]="worker">{{worker.FirstName}} {{worker.LastName}}</option>
</select>
</div>
<button class="brn btn-lg btn-block btn-change" (click)="add(name.value, desc.value, worker)">Add Job</button>
好吧,这是一个很长的问题,但我想证明自己,我做了我的研究,我只是没有抛出错误消息并寻求解决方案,但这真的让我很紧张。
因为我正在发布关系数据并且我的控制台显示 ModelState{job.worker.Id: [,…]}
我该如何反序列化它?再加上我的 ModelState 在到达 API 时将 worker 显示为 null,我猜是因为它不是从 json 转换而来的,但值得知道。
感谢您的帮助。
所以,问题是在您的 SPA 上,您将 worker
作为单个对象发送,而您的 API 需要一个工作人员列表(数组)。现在我不知道你想要什么.. 但你可以通过改变你的 API 模型来修复它以期待一个工人或改变你的 SPA 发送工人列表。没有人可以回答你..取决于你的应用程序的要求。但是,我最好的猜测是一个工作可能有几个工人。所以:
Api 模型(大部分相同..只是删除了属性并将 Worker 更改为 Workers):
public class Job
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime DueDate { get; set; }
public bool IsCompleted { get; set; }
public virtual ICollection<Worker> Workers { get; set; }
}
public class Worker
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// This is an "array". your spa needs to send in this format.
public virtual ICollection<Job> Job { get; set; }
}
温泉码:
export class Job {
id: int;
name: string;
// other fields here..
// Workers property that maps API model
workers: Array<Worker>;
constructor(id: int, name: string [other fields..]) {
this.id = id;
// and so on..
}
public addWorker(worker) {
this.workers.push(worker);
}
}
export class Worker {
id: int;
firstName: string;
// other fields here.. No need for array of jobs here!
}
使用此模型,您可以在调用 API(添加函数)之前执行此操作:
add(Name: string, Description: string, worker: Worker): void {
// creates a job using constructor
const job = new Job(name, description);
// add Job via function(can even be more complex and add validation and so on..)
job.addWorker(worker);
this.jobsServices.addJob(job)
.subscribe(jobs => {
this.jobs.push(jobs);
});
}
这将调用带有 json 的 api,如下所示:
{
"id": 1,
"name": "some name",
[ other fields..]
"workers": [
{ "id:" 1, "name": "some worker name" }
]
}