1

WebApi 2 OData 컨트롤러에 연결된 KendoUI 데이터 소스가 있고 업데이트 작업에 문제가 있습니다. 나는 잘 만들고 삭제할 수 있습니다. Visual Studio에서웹 API + OData - Patch 요청 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":"" 
    } 
    } 
} 

디버깅 패치 기능은 이드 통과가 아닌되고 있음을 보여줍니다 : 나는 호출이 업데이트를 한 후 서버에 데이터 소스를 동기화 할 때

나는 400 오류 회사 개체입니다. 방화범은 PATCH 요구는 다음과 같습니다 있음을 보여줍니다

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

나는 직감이 서버가 이해하지 못하는 것을 이것에 대해 남았습니다 뭔가가있다.

모델은 간단하고 나는 VS 나를 위해 생성 된 어떤으로 컨트롤러 왼쪽 :

모델 :

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/자바 스크립트는 다음과 같습니다.

<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> 

답변

2

질문은 검도 지원 포럼 here에 대한 답변입니다.

parameterMap: function (data, operation) { 
    return JSON.stringify(data); 
} 
:

용액으로 된 parameterMap 기능을 변경했다