【问题标题】:.NET Web API (not Core) - Creating a Patch operation in an Entity Framework controller.NET Web API(非核心)- 在实体框架控制器中创建补丁操作
【发布时间】:2018-09-18 20:47:41
【问题描述】:

我在带有 Angular 前端的 .NET Web API(非核心)项目中使用 Entity Framework目前,我能找到的唯一补丁实施示例是针对 ASP.Net Core 产品的 - 所以我首先想确认 patch 是否甚至可以用普通的 ASP.Net Web API(不是核心)

我想在我的一些控制器中实现patch,但默认情况下,实体控制器似乎没有附带补丁操作的代码。相反,它带有GETPUTPOSTDELETE。我的实体控制器中需要什么代码才能使补丁请求有效?有没有办法在添加新的实体控制器时指定这一点,还是必须始终手动输入?

我的控制器:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using api.Models;
using api.Models.my_model;
using System.Net.Mail;
using System.Configuration;

namespace api.Controllers.my_model
{
    public class myController : ApiController
    {
        private myCodeFirst db = new myCodeFirst();

        // GET: api/my
        public IQueryable<myTable> GetmyTable()
        {
            return db.myTable;
        }

        // GET: api/my/5
        [ResponseType(typeof(myTable))]
        public IHttpActionResult GetmyTable(int id)
        {
            myTable myTable = db.myTable.Find(id);
            if (myTable == null)
            {
                return NotFound();
            }

            return Ok(myTable);
        }

        // PUT: api/my/5
        [ResponseType(typeof(void))]
        public IHttpActionResult PutmyTable(int id, myTable myTable)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != myTable.ID)
            {
                return BadRequest();
            }

            db.Entry(myTable).State = EntityState.Modified;

            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!myTableExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return StatusCode(HttpStatusCode.NoContent);
        }

        // POST: api/my
        [ResponseType(typeof(myTable))]
        public IHttpActionResult PostmyTable(myTable myTable)
        {

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.myTable.Add(myTable);


            db.SaveChanges();


            return CreatedAtRoute("DefaultApi", new { id = myTable.ID }, myTable);
        }

        // DELETE: api/my/5
        [ResponseType(typeof(myTable))]
        public IHttpActionResult DeletemyTable(int id)
        {
            myTable myTable = db.myTable.Find(id);
            if (myTable == null)
            {
                return NotFound();
            }

            db.myTable.Remove(myTable);
            db.SaveChanges();

            return Ok(myTable);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

        private bool myTableExists(int id)
        {
            return db.myTable.Count(e => e.ID == id) > 0;
        }


    }



}

【问题讨论】:

  • 使用[HttpPatch] 属性。事实上,您应该尽可能使用所有 Http 方法属性,而不是依赖命名约定
  • 同意 maccettura。像这样的命名约定实际上会导致方法命名不佳,从而导致可维护性和可读性差。
  • 谢谢大家。你们中的任何一个都可以发布一个控制器实现补丁的示例吗?我在网上找到的所有示例都是针对 ASP.NET Core 的,并使用 JsonPatchDocument 之类的命名空间,这在 .Net Web API(非核心)中似乎不可用,而这正是我正在使用的。

标签: c# angular entity-framework asp.net-web-api patch


【解决方案1】:

PATCH 方法是 HTTP 协议支持的一种请求方法,用于对现有资源进行部分更改。 可以看到一些 JSON Patch 操作:

添加

{
    "op": "add",
    "path": "/a/b",
    "value": "foo"
}

删除

{
    "op": "remove",
    "path": "/a/b"
}

替换

{
    "op": "replace",
    "path": "/a/b",
    "value": "foo"
}

复制

{
    "op": "copy",
    "from": "/a/b",
    "path": "/a/c"
}

移动

{
    "op": "move",
    "from": "/a/b",
    "path": "/a/c"
}

测试

{
    "op": "test",
    "path": "/a/b",
    "value": "foo"
}

在 ASP.NET Core 中,您可以使用 [HttpPatch] 属性指定补丁方法。 要在此方法中获取数据,您应该使用 JsonPatchDocument&lt;TModel&gt; 存在于 Microsoft.ApsNetCore.JsonPatch 命名空间中,其中 TModel 是您要转换为它的实体。另一个有用的包是 AutoMapper。您可以从 NuGet 包管理器安装它,如下所示:

Install-Package AutoMapper

并在您的控制器中引用它。

现在是时候看一个 ASP.NET Core Web API 中的示例了:

public async Task<IActionResult> PartiallyUpdateBook([FromRoute] Guid id, [FromBody] JsonPatchDocument<BookModel> patchDoc)
{
    // If the received data is null
    if (patchDoc == null)
    {
        return BadRequest();
    }

    // Retrieve book from database
    var book = await _context.Books.SingleOrDefaultAsync(x => x.Id == id)

    // Check if is the book exist or not
    if (book == null)
    {
        return NotFound();
    }

    // Map retrieved book to BookModel with other properties (More or less with eexactly same name)
    var bookToPatch = Mapper.Map<BookModel>(book);

    // Apply book to ModelState
    patchDoc.ApplyTo(bookToPatch, ModelState);

    // Use this method to validate your data
    TryValidateModel(bookToPatch);

    // If model is not valid, return the problem
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    // Assign entity changes to original entity retrieved from database
    Mapper.Map(bookToPatch, book);

    // Say to entity framework that you have changes in book entity and it's modified
    _context.Entry(book).State = EntityState.Modified;

    // Save changes to database
    await _context.SaveChangesAsync();

    // If everything was ok, return no content status code to users
    return NoContent();
}

【讨论】:

  • 谢谢萨贾德。我们正在使用ASP.net Web API,而不是ASP.NET Core Web API - 在这种情况下这仍然有效吗?另外,是否可以在没有第三方插件的情况下实施补丁?还是拥有一个好的插件非常重要?
  • 据我所知,所有 ASP.NET Web API 都支持此属性。绝对可以在没有 Automapper 包的情况下实现示例代码。但是你应该写很多代码!这个包很强大,我建议在你所有的项目中使用它。 Automapper 主页:automapper.org 和 GitHub 上的源代码:github.com/AutoMapper/AutoMapper
  • 嗯...例如,即使在.net Core 中,JsonPatchDocument 也需要安装 JsonPatchDocument:Install-Package Microsoft.AspNetCore.JsonPatch。在.NET Web API 中,此安装不兼容且无法正常工作。所以在.net web API(不是核心)中,我认为我没有能力使用 JSON Patch Document。网上关于这个的文档真的不多——我真的希望 Patch 可以用于 .NET Web API,但我不确定。
  • 好的,它只是用于 .net 核心。所以你可以将这个包Install-Package Marvin.JsonPatch 用于.net 框架。
  • 感谢 Sajad,我实际上在您发布之前就发现了这个扩展 - 可以选择它,或者 MyQuay 的另一个 JsonPatch 扩展,或者使用 ODATA。我认为这个 Marvin.Jsonpatch 可能是一个更好的选择,而不是仅仅为了一个补丁而拥有 ODATA 的所有依赖项。有什么方法可以在这里查看我的问题,看看您是否可以理解他的文档以在客户端上实现JsonPatchDocumentstackoverflow.com/questions/52527311/…到目前为止感谢您的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多