Gol*_*ide 10 entity-framework postman asp.net-core
我有一个 .Net Core 2.1 API,它使用 EF 核心发布数据。当我从 Postman 向 http://localhost:3642/task/create 发出 POST 请求时,我收到一个 400 Bad Request 错误(由于语法错误,该请求无法完成)。经过仔细研究,我得到了一个建议来注释掉来自控制器的 ValidateAntiForgery 令牌。当我通过此更改传递来自邮递员的请求时,我收到 200 Ok 状态消息,但没有数据被提交到 Sql Server 中的表。有什么我应该在我的 API 中配置的东西,我还缺少什么?
我的控制器如下所示:
[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();
}
Run Code Online (Sandbox Code Playgroud)
在 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; }
}
Run Code Online (Sandbox Code Playgroud)
这是我在 Postman 中的有效载荷:
{
"Assignee": "Ed tshuma",
"Summary": "Finish reconciliations",
"Description": "collate all the pending data"
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*att 10
这里有很多问题。首先,为什么要将视图模型保存到数据库中。在这种情况下,这实际上是一个实体,而不是视图模型。您绝对应该使用视图模型,但您还应该有一个单独的实体类。然后,您的视图模型应该只包含您希望实际允许用户编辑的Bind属性,完全不需要属性,无论如何都应该避免。(请参阅:绑定是邪恶的)。
// 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; }
}
Run Code Online (Sandbox Code Playgroud)
还要注意责任分工。实体只有对数据库重要的东西([Required]这里表示该列应该是不可为空的)。而视图模型只关心视图。没有Id属性,因为它不需要或不需要,并且显示名称和错误消息显示给用户只放在这里。
然后,您需要从您的视图模型映射到您的实体类:
[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");
}
Run Code Online (Sandbox Code Playgroud)
这里的映射是相当直接的,但你可能更愿意使用像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");
}
Run Code Online (Sandbox Code Playgroud)
最后,关于你的问题的主要问题,有两个问题。首先,此操作是为传统的 HTML 表单发布 ( x-www-form-urlencoded) 设计的。因此,将 JSON 发送给它是没有意义的,并且将 JSON 发送给它是行不通的。要在 Postman 中对其进行测试,您应该将请求作为x-www-form-urlencoded. 如果您不这样做,那么您的模型基本上将始终无效,因为帖子正文中没有任何内容绑定到您的模型。
为了接收 JSON,您的参数需要FromBody应用该属性 ( [FromBody]TaskViewModel model)。但是,如果这样做,您将无法再接收传统的表单帖子,在这种情况下,这就是将要发送的内容。如果您通过 AJAX 发送(您可以想象使用 JSON),那么您还应该返回JSON 或PartialView,但不是View或重定向。
最后,您需要包含请求验证令牌,它应该是 post body name 中的另一个键__RequestVerificationToken。要获取要发送的值,您首先需要加载视图的 GET 版本,然后检查源代码。将有一个带有该值的隐藏输入。
克里斯·帕拉特是对的,你需要发送__RequestVerificationToken。
如果你注释掉[ValidateAntiForgeryToken]属性,看起来你是从Body-raw-JSON发送数据,那么你需要使用[FromBody]来访问数据。
[HttpPost]
public async Task<IActionResult> Create([Bind("Assignee,Summary,Description")] [FromBody] TaskViewModel taskViewModel)
Run Code Online (Sandbox Code Playgroud)
如果您不想添加[FromBody],您可以使用以下方式发送数据form-data
| 归档时间: |
|
| 查看次数: |
30516 次 |
| 最近记录: |