Web API 2:更新导航属性(实体)
本文关键字:属性 实体 导航 更新 API Web | 更新日期: 2023-09-27 17:57:44
我正在寻找Web API功能的一些指导,这些功能在更新具有导航属性的实体方面在MVC中是轻而易举的。
在MVC中,它被实现为:
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public virtual async Task<ActionResult> Update(Page page)
{
Guard.IsNotNull(page, "page");
var pageToUpdate = await this.repository.Query.Include(p => p.Tags).Include(p => p.Name).SingleOrDefaultAsync(p => p.Pk == page.Pk);
if (pageToUpdate == null)
{
return this.RedirectToRoute(H.Constants.Routes.Error.Index, new
{
view = H.Constants.Views.Error.ViewPages.NotFound
});
}
if (this.TryUpdateModel(pageToUpdate))
{
this.repository.BeginTransaction();
this.repository.Update(pageToUpdate); // Updates related entities!
await this.repository.CommitTransactionAsync();
return this.RedirectToRoute(H.Constants.Routes.Data.Read);
}
return this.View(H.Constants.Views.FolderNames.ViewPages.FormatWith(H.Constants.Views.Data.ViewPages.Update), pageToUpdate);
}
所有的导航属性都将更新,生活也很好。
当在Web API中尝试这件事时,就没那么多了。相关实体不会更新。示例:
[HttpPatch]
[HttpPut]
public virtual async Task<IHttpActionResult> Update(int pk, Page page)
{
Guard.IsNotNegativeOrZero(pk, "pk");
if (this.ModelState.IsValid)
{
if (page.Pk == pk)
{
try
{
this.repository.BeginTransaction();
this.repository.Update(page); // Doesn't update related entities.
await this.repository.CommitTransactionAsync();
return this.StatusCode(HttpStatusCode.NoContent);
}
catch (DbUpdateConcurrencyException dbUpdateConcurrencyException)
{
if (this.repository.Query.Any(p => p.Pk == pk))
{
return this.InternalServerError(dbUpdateConcurrencyException);
}
return this.NotFound();
}
}
return this.BadRequest();
}
return this.BadRequest(this.ModelState);
}
今天在Web API中可以做到这一点吗?或者Web API当前是一个不完整的Microsoft产品?
编辑:更新了示例,没有引用WCF
TryUpdateModel在WebAPI中不存在。您可能还会发现实体的序列化存在问题。出于这两个原因,我使用AutoMapper将ViewModels映射到EF实体上,并且您可以使用AutoMapper中的Mappings来处理您的导航特性。
web API方法看起来像这样:
public HttpResponseMessage Post(MyViewModel model)
{
if (someValidationCheckHere)
return new HttpResponseMessage(HttpStatusCode.BadRequest);
_myService.Update(Mapper.Map<MyViewModel, MyEntity>(model));
return new HttpResponseMessage(HttpStatusCode.OK);
}
正如其他人所说,服务和最终的存储库都会进行更新。在这个例子中,我使用automapper忽略了导航属性,但您可以配置automapper来处理它们:
Mapper.CreateMap<MyViewModel, MyEntity>()
.ForMember(x => x.NavigationProperty, opt => opt.Ignore());
我在global.asax.中的application_start上调用的静态类中设置了所有映射