Web API + OData - PATCH 请求 400 错误

2024-05-06

我有一个链接到 Web Api 2 OData 控制器的 Kendo UI 数据源,并且在更新操作时遇到问题。我可以很好地创建和删除。

当我在进行任何更新后调用将数据源同步到服务器时,我收到 400 错误:

{
  "odata.error":{
    "code":"","message":{
      "lang":"en-US","value":"The request is invalid."
    },"innererror":{
      "message":"patch : Invalid JSON. A token was not recognized in the JSON content.\r\n","type":"","stacktrace":""
    }
  }
}

Visual Studio 中的调试显示修补函数正在传递 Id,而不是 Company 对象。 Firebug 显示 PATCH 请求如下所示:

models=%7B%22Id%22%3A1026%2C%22Title%22%3A%22Test+Company+test%22%7D

我有预感,这有一些奇怪的地方,服务器无法理解。

该模型很简单,我将控制器保留为 VS 为我生成的任何内容:

Model:

public class Company {
    public Company() { }

    public Company(Company company) {
        this.Id = company.Id;
        this.Title = company.Title;
        this.Projects = company.Projects;
    }

    public int Id { get; set; }
    public string Title { get; set; }

    public virtual ICollection<Project> Projects { get; set; }
}

控制器:

public class CompanyController : ODataController
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET odata/Company
    [Queryable]
    public IQueryable<Company> GetCompany()
    {
        return db.Companies;
    }

    // GET odata/Company(5)
    [Queryable]
    public SingleResult<Company> GetCompany([FromODataUri] int key)
    {
        return SingleResult.Create(db.Companies.Where(company => company.Id == key));
    }

    // PUT odata/Company(5)
    public async Task<IHttpActionResult> Put([FromODataUri] int key, Company company)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (key != company.Id)
        {
            return BadRequest();
        }

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

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

        return Updated(company);
    }

    // POST odata/Company
    public async Task<IHttpActionResult> Post(Company company)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Companies.Add(company);
        await db.SaveChangesAsync();

        return Created(company);
    }

    // PATCH odata/Company(5)
    [AcceptVerbs("PATCH", "MERGE")]
    public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Company> patch)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Company company = await db.Companies.FindAsync(key);
        if (company == null)
        {
            return NotFound();
        }

        patch.Patch(company);

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

        return Updated(company);
    }

    // DELETE odata/Company(5)
    public async Task<IHttpActionResult> Delete([FromODataUri] int key)
    {
        Company company = await db.Companies.FindAsync(key);
        if (company == null)
        {
            return NotFound();
        }

        db.Companies.Remove(company);
        await db.SaveChangesAsync();

        return StatusCode(HttpStatusCode.NoContent);
    }

    // GET odata/Company(5)/Projects
    [Queryable]
    public IQueryable<Project> GetProjects([FromODataUri] int key)
    {
        return db.Companies.Where(m => m.Id == key).SelectMany(m => m.Projects);
    }

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

    private bool CompanyExists(int key)
    {
        return db.Companies.Count(e => e.Id == key) > 0;
    }
}

最后,KendoUI,HTML/Javascript 是这样的:

<h2>Company List</h2>

<div id="company-data">
    <div class="col-md-3 col-sm-5 col-xs-5">
        <div id="company-list" style="padding: 0px; height: 500px; overflow: auto" data-role="listview" data-template="list-template" data-bind="source: companies, events: {change: OnSelect}" data-selectable="true"></div>
        <div>
            <button class="btn btn-success btn-sm" id="btn-add-company"><span class="glyphicon glyphicon-plus"></span> Add</button>
            <button class="btn btn-danger btn-sm" id="btn-delete-company" data-bind="visible: hasSelection, click: deleteSelection"><span class="glyphicon glyphicon-remove"></span> Delete</button>
            <button class="btn btn-default btn-sm" id="btn-clear-company" data-bind="visible: hasSelection, click: clearSelection"><span class="glyphicon glyphicon-ban-circle"></span> Clear</button>
            <button class="btn btn-primary btn-sm btn-block" id="btn-save" data-bind="visible: hasChanges, click: saveChanges"><span class="glyphicon glyphicon-cloud-upload"></span> Save All</button>
        </div>
    </div>
    <div class="col-md-9 col-sm-7 col-xs-7" data-bind="visible: hasSelection">
        <label for="company-title">Title:</label><br />
        <input id="company-title" data-bind="value: selectedItem.Title" ><br />
    </div>
</div>

<script type="text/x-kendo-template" id="list-template">
    <div class="company" style="cursor: pointer">
        <span data-bind="text: Title"></span>
    </div>
</script>

<script>
    $(function () {
        var firstSync = true;
        var companyVM = new kendo.observable({
            // Data Source.
            companies: new kendo.data.DataSource({
                type: 'odata',
                transport: {
                    create: {
                        url: '/odata/Company',
                        dataType: 'json',
                        type: 'POST'
                    },
                    read: {
                        url: '/odata/Company',
                        dataType: 'json'
                    },
                    update: {
                        url: function (data) {
                            return '/odata/Company(' + data.Id + ')';
                        },
                        dataType: 'json',
                        type: 'PATCH'
                    },
                    destroy: {
                        url: function (data) {
                            return '/odata/Company(' + data.Id + ')';
                        },
                        dataType: 'json',
                        type: 'DELETE'
                    },
                    parameterMap: function (options, operation) {
                        if (operation !== "read" && options) {
                            console.log(operation + '*: ' + kendo.stringify(options));
                            return {
                                models: kendo.stringify(options)
                            };
                        }
                        console.log(operation + ': ' + kendo.stringify(options));
                        return options;
                    }
                },
                schema: {
                    data: function (data) {
                        return data['value'];
                    },
                    total: function (data) {
                        return data['odata.count'];
                    },
                    model: {
                        id: 'Id',
                        fields: {
                            Title: { type: 'string' }
                        }
                    }
                },
                change: function () {
                    // We don't want to fire the first time the data loads because that counts as changed.
                    if (!firstSync)
                        companyVM.set('hasChanges', true);
                    else
                        firstSync = false;
                }
            }),

            // Properties.
            selectedItem: null,
            hasSelection: function () {
                return this.get('selectedItem') != null;
            },
            hasChanges: false,

            // Functions.
            clearSelection: function() {
                this.set('selectedItem', null);
                $('#company-list').getKendoListView().clearSelection();
            },
            saveChanges: function() {
                this.companies.sync();
                this.set('hasChanges', false);
            },
            deleteSelection: function () {
                if (confirm('Warning, deletion is permanent! Are you sure you wish to delete this item?')) {
                    this.companies.remove(this.selectedItem);
                    this.set('hasChanges', true);
                    this.clearSelection();
                }
            },

            // Events.
            OnSelect: function (e) {
                var list = $(e.sender.element).getKendoListView();
                var row = list.select();
                var item = list.dataSource.getByUid(row.data('uid'));

                this.set('selectedItem', item);
            }
        });

        kendo.bind($('#company-data'), companyVM);
    });
</script>

Kendo 支持论坛上回答的问题here http://www.telerik.com/forums/web-api-odata---patch-request-400-error.

解决方案是将parameterMap函数更改为:

parameterMap: function (data, operation) {
     return JSON.stringify(data);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web API + OData - PATCH 请求 400 错误 的相关文章

  • Kendo TreeView 搜索并突出显示

    我有一个带有 spriteclass 的 KendoTreeview 我想用我的搜索词突出显示节点 根节点和子节点 我已经实现了搜索功能 但是当我搜索它时 问题是突出显示节点中的术语 但在第一次搜索后缺少节点中的 SpriteClass 任
  • 将日期值绑定到角度剑道日期选择器中的 ng-model

    我有一个API 它以这种格式返回日期 014 08 26T15 10 45 402Z 我正在使用角度kendo ui 我面临的问题是日期没有绑定到kendo日期选择器 有人可以吗帮帮我
  • 在 Kendo 网格读取操作中发送附加参数

    我有一个剑道网格 如下所示 Html Kendo Grid
  • 如何使用 ComboBox 作为 Kendo UI 网格列?

    我正在使用剑道网格 并尝试将名称字段设置为具有自己的数据源的组合框 我没有收到 javascript 错误 但是当我去编辑网格中的名称字段时 它没有显示组合框 它仍然显示一个输入字段 function console log ready v
  • Web API 2 会话

    我无法从 web api 2 中获取会话数据 我已经验证 cookie 是在 fiddler 中发送的 我知道 Web api 2 的最佳实践是无状态 但由于项目的要求 现在有必要是全状态的 我已经尝试过这个链接 WebAPI 2 属性路由
  • 模板内的 MVC 助手

    我正在尝试在模板中使用 kendo MVC 助手 远程模板文件加载如下 http docs kendoui c om howto load templates external files remote templates http doc
  • OData 中的过滤器和集合

    这与 Azure 最近推出的搜索服务有关 该服务目前处于预览状态 我试图弄清楚如何将 OData 的过滤器与集合一起使用 我知道我可以这样做 filter Products any p p eq WidgetA 它将按 WidgetA 过滤
  • 带有 WebAPI OData 属性路由的 $Metadata 不起作用

    我正在为 OData 端点使用 OData 属性路由 这是我所拥有的示例 ODataRoutePrefix Profile public class ProfileODataController ODataController ODataR
  • 获取剑道网格中的点击事件

    我正在尝试获取 Kendo Grid 的单击事件 以便我可以将内容绑定到 Shift 和 Ctrl 单击 我无法使用 Kendo 提供的固有多选功能 因为它不支持拖放 当我在 dataBound 事件之后创建函数时 我的函数会在单击时被调用
  • 如何使用 OData 在单个 POST 请求中正确创建和链接一对一关系

    在 OData Operations 文档的第 2 4 节第四段中 它写道 在使用 POST 创建实体时 也可以在同一请求中创建链接 但是 我在尝试完成这项工作时遇到了麻烦 在创建时就多对多链接提出了类似的问题 看起来如果没有批量请求 就不
  • Kendo 网格列宽度 + 可滚动

    我正在尝试从 JavaScript 绑定到可滚动剑道网格 但在列宽方面遇到了一些问题 这fiddle http jsfiddle net mnTGm 1 演示了问题 问题末尾的代码 我在 html 中指定标头并向其中一个标头添加宽度 然后
  • Kendo 有 GUI 设计师吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Kendo 有没有像 Sencha Architect for Ext JS 这样的控件布局设计工具
  • 如何将 OData 查询字符串转换为 .NET 表达式树

    完全重写这个问题 因为我现在比以前理解得更多 我试图将 OData 查询字符串直接抽象为 NET 表达式树 似乎有很多关于此的问题和文章 但没有答案提供依赖于的抽象解决方案soley on the Microsoft Data OData命
  • OData 按最大值和字段过滤

    数据集包含具有以下键的记录 userID period and points 是否可以查询一条记录period and by max points 示例场景 Dataset period 2016 01 01 userID 1 period
  • AllowAnonymous 与 OverrideAuthorizeAttribute

    AllowAnonymous 和 OverrideAuthorizeAttribute 的使用有什么区别 是一样的吗 http www asp net web api overview security authentication and
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO
  • 与 JSONModel 相比,输入验证不适用于 v2.ODataModel

    在当前的项目中 我有一个简单的形式 https openui5 hana ondemand com api sap ui layout form SimpleForm 在一个视图上 在此视图上绑定 JSONModel validateVal
  • 将 ninject 与 Ninject.Web.Api 用于 Web Api 2 一起使用在 ASP.NET MVC 5 中不起作用

    我正在开发一个 Asp NET MVC 项目 我的项目也有 web api 我正在使用 ASP NET MVC5 和 Web Api 2 以及 Visual Studio 3 我正在使用 ninject 进行依赖项注入 我知道 ninjec
  • 如何公开具有 OData 服务的派生类和成员的多层模型?

    我正在尝试公开一个可供使用的模型OData服务 我目前采取的方法是 1 在模型中定义一个类来公开IQueryable集合例如 public class MyEntities public IQueryable
  • 有没有办法处理asp.net core odata错误

    有没有办法处理 asp net core odata 错误 我有一个模特班DimDateAvailable具有一个属性 主键为int DateId 然后我打电话 data DimDateAvailable select test 其他调用按

随机推荐