gpt4 book ai didi

entity-framework - 如何修复 .Net Core POST 操作中的 400 Bad Request 错误?

转载 作者:行者123 更新时间:2023-12-03 06:35:29 32 4
gpt4 key购买 nike

我有一个使用 EF 核心发布数据的 .Net Core 2.1 API。当我从 Postman 向 http://localhost:3642/task/create 发出 POST 请求时,我收到 400 错误请求错误(由于语法错误,请求无法完成)。四处挖掘后,我得到了一个注释掉的建议来自 Controller 的 ValidateAntiForgery token 。当我通过此更改传递来自 postman 的请求时,我收到 200 Ok 状态消息,但没有数据被提交到 Sql Server 中的表。我应该在我的 API 中配置什么,我还缺少什么?
我的 Controller 如下所示:

 [HttpPost]
// [ValidateAntiForgeryToken]
public async Task<IActionResult>
Create([Bind("Assignee,Summary,Description")] TaskViewModel taskViewModel)
{
if (ModelState.IsValid)
{
_context.Add(taskViewModel);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View();
}
在 TaskViewModel.cs 我有:
 public class TaskViewModel 
{
[Required]
public long Id { get; set; }

[Required(ErrorMessage = "Please provide Task Summary")]
[Display(Name = "Summary")]
public string Summary { get; set; }

[Required(ErrorMessage = "Please enter task description")]
[Display(Name = "Description")]
public string Description { get; set; }

[Required(ErrorMessage = "Please select Assignee")]
[Display(Name = "Assign To")]
public string Assignee { get; set; }
}
这是我在 Postman 中的有效载荷:
{
"Assignee": "Ed tshuma",
"Summary": "Finish reconciliations",
"Description": "collate all the pending data"
}

最佳答案

这里有很多问题。首先,为什么要将 View 模型保存到数据库中。在这种情况下,这实际上是一个实体,而不是 View 模型。您绝对应该使用 View 模型,但您还应该有一个单独的实体类。然后,您的 View 模型应该只包含您希望实际允许用户编辑的属性,完全不需要 Bind。属性,无论如何都应该避免。 (见:Bind is Evil)。

// added "Entity" to the name to prevent conflicts with `System.Threading.Task`
[Table("Tasks")]
public class TaskEntity
{
[Key]
public long Id { get; set; }

[Required]
public string Summary { get; set; }

[Required]
public string Description { get; set; }

[Required]
public string Assignee { get; set; }
}

public class TaskViewModel
{
[Required(ErrorMessage = "Please provide Task Summary")]
[Display(Name = "Summary")]
public string Summary { get; set; }

[Required(ErrorMessage = "Please enter task description")]
[Display(Name = "Description")]
public string Description { get; set; }

[Required(ErrorMessage = "Please select Assignee")]
[Display(Name = "Assign To")]
public string Assignee { get; set; }
}

另外,注意责任分工。实体只有对数据库重要的东西( [Required] 在这里表示该列应该是不可为空的)。而 View 模型只关心 View 。没有 Id属性,因为它不需要或不需要,并且要呈现给用户的显示名称和错误消息仅放置在此处。

然后,您需要从 View 模型映射到实体类:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(TaskViewModel model)
{
if (!ModelState.IsValid)
return View(model);

var task = new TaskEntity
{
Assignee = model.Assignee,
Summary = model.Summary,
Description = model.Description
};

_context.Add(task);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}

这里的映射相当简单,但您可能更喜欢使用像 AutoMapper 这样的库来为您处理: _mapper.Map<TaskEntity>(model) .

虽然这是专门针对创建操作的,但值得指出更新的细微差别。您需要首先从数据库中检索现有任务,然后将发布的值映射到该任务上。其余的保持相对相同:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Update(long id, TaskViewModel model)
{
if (!ModelState.IsValid)
return View(model);

var task = await _context.Tasks.FindAsync(id);
if (task == null)
return NotFound();

task.Assignee = model.Assignee;
task.Summary = model.Summary;
task.Description = model.Description;

await _context.SaveChangesAsync();
return RedirectToAction("Index");
}

最后,关于你的问题的主要问题,有两个问题。首先,此操作是为传统的 HTML 表单帖子 ( x-www-form-urlencoded) 设计的。因此,向它发送 JSON 是没有意义的,向它发送 JSON 将不起作用。要在 Postman 中测试它,您应该将请求发送为 x-www-form-urlencoded .如果你不这样做,那么你的模型基本上总是无效的,因为没有任何东西会从帖子正文绑定(bind)到你的模型。

为了接收 JSON,您的参数需要有 FromBody应用于它的属性 ( [FromBody]TaskViewModel model)。但是,如果您这样做,您将无法再收到传统的表单帖子,在这种情况下,这就是将要发送的内容。如果您通过 AJAX 发送(您可以想象使用 JSON),那么您还应该返回 JSON 或者 PartialView ,但不是 View或重定向。

最后,您需要包含请求验证 token ,它应该是帖子正文名称中的另一个键 __RequestVerificationToken .要获取要发送的值,您需要首先加载 View 的 GET 版本,然后检查源。将有一个隐藏的输入值。

关于entity-framework - 如何修复 .Net Core POST 操作中的 400 Bad Request 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55723977/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com