【问题标题】:ASP.NET webapi odata put, The property 'ID' is part of the object's key information and cannot be modifiedASP.NET webapi odata put,属性“ID”是对象关键信息的一部分,不能修改
【发布时间】:2017-08-03 04:21:19
【问题描述】:

我是 ASP.NET webapi 的菜鸟,这是一个非常简单的情况,我陷入了困境。

我正在使用 webapi+odata

我的模特:

public class CategoryModel
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int ParentID { get; set; }
}

我的自动生成控制器的 put 方法:

public async Task<IHttpActionResult> Put([FromODataUri] int key, Delta<CategoryModel> patch)
{
    Validate(patch.GetEntity());

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

    CategoryModel categoryModel = await db.Category.FindAsync(key);
    if (categoryModel == null)
    {
        return NotFound();
    }

    patch.Put(categoryModel);

    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!CategoryModelExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return Updated(categoryModel);
}

还有我的 jquery ajax

jQuery.ajax(
        {
          url       : '/api/Category(3)',
          data      : { Name:'New Category' },
          method    : 'PUT',
          headers   : {
            Accept        : 'application/json',
          },
          statusCode: {
            401: () => {
              console.log('handle the unautherized here');
            },
          },
          beforeSend: (jqXHR, settings) => {},
          error     : (jqXHR, textStatus, errorThrown) => {
            //TODO do some global error reporting

            Util.Error(JSON.parse(jqXHR.responseText));
            resolve(null);
          },
          success   : (data, textStatus, jqXHR) => {
            resolve(data);
          },
          complete  : (jqXHR, textStatus) => {}
        }
      );

和错误:

{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "An error has occurred."
    },
    "innererror": {
      "message": "The property 'ID' is part of the object's key information and cannot be modified. ",
      "type": "System.InvalidOperationException",
      "stacktrace": "   at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperty(Int32 ordinal, Boolean detectOnlyComplexProperties, Boolean detectOnly)\r\n   at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties)\r\n   at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties(IList`1 entries)\r\n   at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()\r\n   at System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()\r\n   at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)\r\n   at System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)\r\n   at System.Data.Entity.Internal.InternalContext.GetStateEntries()\r\n   at System.Data.Entity.Infrastructure.DbChangeTracker.Entries()\r\n   at System.Data.Entity.DbContext.GetValidationErrors()\r\n   at System.Data.Entity.Internal.InternalContext.SaveChangesAsync(CancellationToken cancellationToken)\r\n   at System.Data.Entity.Internal.LazyInternalContext.SaveChangesAsync(CancellationToken cancellationToken)\r\n   at System.Data.Entity.DbContext.SaveChangesAsync(CancellationToken cancellationToken)\r\n   at System.Data.Entity.DbContext.SaveChangesAsync()\r\n   at Notifier.Controllers.CategoryController.<Put>d__3.MoveNext() in E:\\csharp\\notifier\\Notifier\\Notifier\\Controllers\\CategoryController.cs:line 66\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__3`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
    }

GETPOST 工作正常,但 PUTPATCH 给我这个错误。

请帮帮我...

更新:问题在于这个控制器使用 odata v3 生成的代码,我检查了普通的 webapi 控制器,它工作得很好,所以....

【问题讨论】:

  • 你在`await db.SaveChangesAsync();`上遇到错误?
  • @UmairAnwaar 是的
  • 数据库表有主键吗?
  • 您是否尝试过使用SingleOrDefault 获取对象并设置名称然后输入db.Entry("modifiedObject").State = EntityState.Modiied; db.SaveChanges();
  • @vanloc ID 是主键,如果没有指定另一个,默认情况下 EF 将 ID 作为主键。

标签: c# asp.net asp.net-web-api odata


【解决方案1】:

在我看来,您正在尝试更新一个 ID 不同于 3 的对象,但是您的 ajax 调用正在发送您在该行中硬编码的 Id = 3:

url       : '/api/Category(3)',

【讨论】:

  • 但是 OP 发送的数据在下一行:data : { Name:'New Category' },,其中没有 ID,这是一个 PUT:他们正在尝试创建一个新对象。
  • 也就是说,如果没有他们的进一步澄清,这可能是不可能真正回答的——一旦你有足够的代表点这样做,我们通常会要求作为 cmets 而不是答案——这是一个老问题所以他们很可能已经继续前进了。但是感谢您的帮助!
猜你喜欢
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
  • 2023-03-29
相关资源
最近更新 更多