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

Web API 2:更新导航属性(实体)

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上调用的静态类中设置了所有映射