{"id":180375,"date":"2013-05-21T09:18:03","date_gmt":"2013-05-21T05:18:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=180375"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=180375","title":{"rendered":"<span class=\"post_title\">OData \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0432 .NET MVC<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0412 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u0448\u0435\u0434\u0448\u0435\u043c ASP.NET and <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=282650\">Web Tools 2012.2 Update<\/a> \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0430 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 oData \u0432 ASP.NET Web API. \u0420\u0435\u0448\u0438\u043b \u0441\u0430\u043c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c, \u0434\u0430 \u0438 \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0448\u0443 \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 oData \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 front-end \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d Kendo UI framework.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h5>\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435.<\/h5>\n<p>  \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0441 \u0446\u0435\u043b\u044c\u044e \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043f\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u043d\u043e\u0432\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 .NET MVC, \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0437\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0433\u0440\u0435\u0445\u0438. \u0418\u0442\u0430\u043a\u2026<\/p>\n<h5>\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430.<\/h5>\n<p>  \u041a\u0430\u0447\u0430\u0435\u043c \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=282650\">ASP.NET and Web Tools 2012.2 Update<\/a> (\u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0436\u0435\u043b\u0430\u043d\u0438\u044f, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442 <a href=\"http:\/\/nuget.org\/packages\/Microsoft.AspNet.WebApi.OData\">Microsoft ASP.NET Web API OData<\/a>). \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 <b>ASP.NET MVC 4 Web Application<\/b> \u0438 \u043d\u0430\u0437\u043e\u0432\u0435\u043c <b>\u00abODataSample\u00bb<\/b>. \u0412 \u0434\u0438\u0430\u043b\u043e\u0433\u0435 <b>New ASP.NET MVC 4 Project<\/b> \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d <b>Web API<\/b>.<br \/>  \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u043f\u0430\u043a\u0435\u0442 <b>KendoUIWeb <\/b>\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438: \u0432 \u0444\u0430\u0439\u043b<b> _Layout.cshtml<\/b> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043a\u043b\u0431\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430<i> kendo.common.min.css, kendo.default.min.css, kendo.web.min.js.<\/i><\/p>\n<h5>\u041c\u043e\u0434\u0435\u043b\u044c.<\/h5>\n<p>  \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044f \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f\u043c, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0435 <b>Models<\/b> \u043a\u043b\u0430\u0441\u0441 <b>Category<\/b> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u043b\u044f:  <\/p>\n<pre><code class=\"cs\">    public class Category     {         public int ID { get; set; }         [Required]         [StringLength(50)]         public string Name { get; set; }      } <\/code><\/pre>\n<p>  \u0412 \u0442\u043e\u0439 \u0436\u0435 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <b>ODataSampleContext<\/b>:  <\/p>\n<pre><code class=\"cs\">    public class ODataSampleContext : DbContext     {         public ODataSampleContext() : base(&quot;name=ODataSampleContext&quot;)         {         }         public DbSet&lt;Category&gt; Categories { get; set; }     } <\/code><\/pre>\n<p>  \u0418 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c Entity Framework Migration \u2013 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432 Package manager console:  <\/p>\n<ul>\n<li>Enable-Migrations<\/li>\n<li>Add-Migration Init<\/li>\n<li>Update-Database<\/li>\n<\/ul>\n<p>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 \u0431\u0430\u0437\u0435 \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438. \u041c\u043e\u0436\u043d\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Migration, \u043d\u043e \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. \u042f \u0434\u0430\u0436\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u041d\u043e \u044f \u0447\u0442\u043e-\u0442\u043e \u043e\u0442\u0432\u043b\u0435\u043a\u0430\u044e\u0441\u044c. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443.<\/p>\n<h5>OData \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440.<\/h5>\n<p>  \u041f\u043e\u043a\u0430 \u0435\u0449\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f OData \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d <b>\u00abEmpty API Controller\u00bb<\/b> \u0438 \u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439:  <\/p>\n<pre><code class=\"cs\">public class CategoryController : EntitySetController&lt;Category, int&gt;     {         private ODataSampleContext db = new ODataSampleContext();          public override IQueryable&lt;Category&gt; Get()         {             return db.Categories; ;         }          protected override void Dispose(bool disposing)         {             db.Dispose();             base.Dispose(disposing);         }     } <\/code><\/pre>\n<p>  \u0412\u043e\u043e\u0431\u0449\u0435, <b>EntitySetController<\/b> \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d \u043e\u0442 <b>ODataController<\/b>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e\u0442 <b>ApiController<\/b>. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 WebApi. \u0422\u0430\u043a \u0447\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0430\u043c\u043e\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u043d\u0430 ASP.NET CodePlex project. <b>EntitySetController <\/b>\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u0430: \u0442\u0438\u043f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u0442\u0438\u043f \u043a\u043b\u044e\u0447\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438.<br \/>  \u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0444\u0430\u0439\u043b <b>WebApiConfig<\/b>:  <\/p>\n<pre><code class=\"cs\">public static class WebApiConfig     {         public static void Register(HttpConfiguration config)         { \t\t\/\/ ...             config.EnableQuerySupport(); \t\t\/\/ ...             ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();             modelBuilder.EntitySet&lt;Category&gt;(&quot;Category&quot;);              Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();             config.Routes.MapODataRoute(&quot;ODataRoute&quot;, &quot;odata&quot;, model);          }     } <\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 <b>EnableQuerySupport<\/b> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432(query options) OData \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0442\u0438\u043f <b>IQueryable<\/b>. \u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043d\u0435\u0442, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c<b> [Queryable]<\/b> \u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0412\u0430\u043c \u043d\u0443\u0436\u043d\u044b. \u041a\u0441\u0442\u0430\u0442\u0438, \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<i> $filter, $inlinecount, $orderby, $skip, $top<\/i>; \u043c\u0430\u043b\u043e\u0432\u0430\u0442\u043e, \u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0446\u0435\u043b\u0435\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u044f \u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (server-side paging). \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 ( Entity Data Model -EDM). \u041c\u0435\u0442\u043e\u0434 <b>EntitySet<\/b> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 EDM. \u041c\u0435\u0442\u043e\u0434 <b>MapODataRoute<\/b> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 URI \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443(endpoint). \u042d\u0442\u043e \u0432\u0441\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u043e\u0439:<a href=\"http:\/\/localhost:52864\/odata\/Category\"> http:\/\/localhost:52864\/odata\/Category<\/a>. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 JSON:  <\/p>\n<pre><code class=\"html\">{  &quot;odata.metadata&quot;:&quot;http:\/\/localhost:52864\/odata\/$metadata#Category&quot;,&quot;value&quot;:[     {       &quot;ID&quot;:1,&quot;Name&quot;:&quot;Categoty1&quot;     },{       &quot;ID&quot;:2,&quot;Name&quot;:&quot;Category2&quot;     }   ] } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435<a href=\"http:\/\/localhost:52864\/odata\/Category(1)\"> http:\/\/localhost:52864\/odata\/Category(1)<\/a>, \u0433\u0434\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u2013 \u044d\u0442\u043e \u043a\u043b\u044e\u0447, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <b>GetEntityByKey<\/b>:  <\/p>\n<pre><code class=\"cs\">        \/\/...         protected override Category GetEntityByKey(int key)         {             return db.Categories.FirstOrDefault(c =&gt; c.ID == key);         }         \/\/... <\/code><\/pre>\n<h5>\u0423\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0443.<\/h5>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u044c <b>Product<\/b>, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 <b>Category<\/b>.  <\/p>\n<pre><code class=\"cs\">public class Product     {         public int ProductID { get; set; }         [Required]         public string Name { get; set; }         public decimal Price { get; set; }         [Required]         public int CategoryID { get; set; }         public virtual Category Category { get; set; }     } <\/code><\/pre>\n<p>  \u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 <code> public DbSet&lt;Product&gt; Products { get; set; }<\/code> \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<i> Add-Migration AddProduct, Update-Database<\/i>. \u0412\u043e\u0442 \u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0432 \u0431\u0430\u0437\u0435. \u041a\u0441\u0442\u0430\u0442\u0438, \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <b>Seed<\/b> \u0432 \u043a\u043b\u0430\u0441\u0441\u0435<b> Migrations\/Configuration.cs<\/b> \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c:<b> context.Products.AddOrUpdate(\u2026)<\/b>.<br \/>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 OData. \u0418 \u0442\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432 OData \u043e\u0442\u0432\u0435\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0442\u0438\u043f\u044b. \u0412 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435 OData \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <b>$expand<\/b>, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u0431\u0435\u0449\u0430\u044e\u0442 \u0432 \u0441\u043a\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c; \u043d\u043e \u0432\u0441\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 Data Tranfer Object (DTO):  <\/p>\n<pre><code class=\"cs\">    public class ProductDTO     {         public ProductDTO() { }         public ProductDTO(Product product)         {             ProductID = product.ProductID;             Name = product.Name;             Price = product.Price;             CategoryID = product.CategoryID;             CategoryName = product.Category.Name;         }         [Key]         public int ProductID { get; set; }         [Required]         public string Name { get; set; }         public decimal Price { get; set; }         public int CategoryID { get; set; }         public string CategoryName { get; set; }         public Product ToEntity()         {             return new Product             {                 ProductID = ProductID,                 Name = Name,                 Price = Price,                 CategoryID = CategoryID              };         }     } <\/code><\/pre>\n<h5>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438<\/h5>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0438 \u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:  <\/p>\n<pre><code class=\"cs\">  public class ProductController : EntitySetController&lt;ProductDTO, int&gt;     {         ODataSampleContext _context = new ODataSampleContext();                public override IQueryable&lt;ProductDTO&gt; Get()         {             return _context.Products.Include(p =&gt; p.Category)                 .Select(product =&gt; new ProductDTO                 {                     ProductID = product.ProductID,                     Name = product.Name,                     Price = product.Price,                     CategoryID = product.CategoryID,                     CategoryName = product.Category.Name,                 });         }          protected override ProductDTO GetEntityByKey(int key)         {             return new ProductDTO(_context.Products.FirstOrDefault(p =&gt; p.ProductID == key));         }          protected override void Dispose(bool disposing)         {             _context.Dispose();             base.Dispose(disposing);         } } <\/code><\/pre>\n<p>  \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043e\u0442\u043b\u0438\u0447\u0438\u0435\u043c \u043e\u043d \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u2013 \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 DTO. \u0412 \u0432\u0438\u0434\u0435 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u00ab\u043c\u0430\u043f\u043f\u0435\u0440\u0430\u00bb.<br \/>  \u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b. \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 \u043c\u0435\u0442\u043e\u0434:  <\/p>\n<pre><code class=\"cs\">protected override ProductDTO CreateEntity(ProductDTO entityDto)         {             if (ModelState.IsValid)             {                 var entity = entityDto.ToEntity();                 _context.Products.Add(entity);                 _context.SaveChanges();                 return new ProductDTO(_context.Products.Include(p =&gt; p.Category).FirstOrDefault(p =&gt; p.ProductID == entity.ProductID));             }             else             {                 HttpResponseMessage response = null;                 response = Request.CreateResponse(HttpStatusCode.BadRequest, new ODataError                 {                     ErrorCode = &quot;ValidationError&quot;,                     Message = String.Join(&quot;;&quot;, ModelState.Values.First().Errors.Select(e =&gt; e.ErrorMessage).ToArray())                  });                 throw new HttpResponseException(response);             }         } <\/code><\/pre>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0431\u0430\u0437\u0443 \u0437\u0430\u043f\u0438\u0441\u044c. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0441\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c <b>HttpStatusCode.BadRequest<\/b> \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 <b>ODataError<\/b>.<br \/>  \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u0434 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0432\u0438\u0434\u0435 JSON. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u044f\u0437\u044b\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <b>HttpResponseException<\/b> \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435.<br \/>  \u0414\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 \u043c\u0435\u0442\u043e\u0434\u044b:  <\/p>\n<pre><code class=\"cs\">        protected override ProductDTO UpdateEntity(int key, ProductDTO updateDto)         {                          if (!_context.Products.Any(p =&gt; p.ProductID == key))             {                 throw new HttpResponseException(HttpStatusCode.NotFound);             }             var update = updateDto.ToEntity();             _context.Products.Attach(update);              _context.Entry(update).State = System.Data.EntityState.Modified;             _context.SaveChanges();             return new ProductDTO(_context.Products.Include(p =&gt; p.Category).FirstOrDefault(p =&gt; p.ProductID == key));                     }         protected override ProductDTO PatchEntity(int key, Delta&lt;ProductDTO&gt; patch)         {             Product product = _context.Products.FirstOrDefault(p =&gt; p.ProductID == key);             if (product == null)             {                 throw new HttpResponseException(HttpStatusCode.NotFound);             }             ProductDTO ProductDTO = new ProductDTO(product);              patch.Patch(ProductDTO);             _context.Products.Attach(ProductDTO.ToEntity());              _context.SaveChanges();             return new ProductDTO(product);         }         public override void Delete([FromODataUri] int key)         {             Product product = _context.Products.FirstOrDefault(p =&gt; p.ProductID == key);             if (product == null)             {                 throw new HttpResponseException(HttpStatusCode.NotFound);             }             _context.Products.Remove(product);             _context.SaveChanges();         }          protected override int GetKey(ProductDTO entity)         {             return entity.ProductID;         } <\/code><\/pre>\n<p>  \u0418\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 PatchEntity, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 Delta, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<h5>\u041a\u043b\u0438\u0435\u043d\u0442 \u2013 KendoUI Grid<\/h5>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <b>HomeController<\/b> \u043c\u0435\u0442\u043e\u0434:  <\/p>\n<pre><code class=\"cs\">public ActionResult Products() {             return View(); } <\/code><\/pre>\n<p>  \u0418 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0443\u044e View<b> Products.cshtml<\/b> \u0432 \u043f\u0430\u043f\u043a\u0435 <b>View\/Home<\/b>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <b>div<\/b> \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c <b>Grid<\/b>:  <\/p>\n<pre><code class=\"html\">@{     ViewBag.Title = &quot;Product&quot;;     Layout = &quot;~\/Views\/Shared\/_Layout.cshtml&quot;; }  &lt;div id=&quot;body&quot;&gt;     &lt;section class=&quot;featured&quot;&gt;         &lt;div class=&quot;content-wrapper&quot;&gt;             &lt;hgroup class=&quot;title&quot;&gt;                 &lt;h1&gt;Product&lt;\/h1&gt;             &lt;\/hgroup&gt;             &lt;div id=&quot;Grid&quot; style=&quot;height: 380px&quot;&gt;&lt;\/div&gt;         &lt;\/div&gt;     &lt;\/section&gt; &lt;\/div&gt; <\/code><\/pre>\n<p>  \u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u0442\u043e\u043b\u044c\u043a\u043e JavaScript:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Script \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">&lt;script&gt;     $(document).ready(function () {         $(&quot;#Grid&quot;).kendoGrid({             columns: [                 { field: &quot;Name&quot;, title: &quot;Product Name&quot;, width: &quot;100px&quot; },                 { field: &quot;CategoryName&quot;, title: &quot;Category&quot;, width: &quot;150px&quot;, editor: categoryDropDownEditor, template: &quot;#=CategoryName#&quot; },                 { field: &quot;Price&quot;, title: &quot;Price&quot;, width: &quot;100px&quot; },                 { command: &quot;edit&quot;, title: &quot;Edit&quot;, width: &quot;110px&quot; },                 { command: &quot;destroy&quot;, title: &quot;Delete&quot;, width: &quot;110px&quot; },             ],             pageable: true,             pageSize: 5,             sortable: true,             filterable: true,             editable: &quot;popup&quot;,              toolbar: [&quot;create&quot;],              dataSource: {                 serverPaging: true,                 serverFiltering: true,                 serverSorting: true,                 pageSize: 5,                 type: &quot;odata&quot;,                 schema: {                     data: function (response) {                         if (response.value !== undefined)                             return response.value;                          else{                             delete response[&quot;odata.metadata&quot;];                             return response;                         }                     },                     total: function (response) {                         return response['odata.count'];                     },                     model: {                         id: &quot;ProductID&quot;,                         fields: {                             ProductID: { editable: false, type: &quot;number&quot; },                             Name: {  type: &quot;string&quot;, nullable: false },                             Price: { nullable: false, type: &quot;number&quot; },                             CategoryID: {  type: &quot;number&quot;,validation: { required: true }, editable: true},                             CategoryName: { validation: { required: true }, editable: true },                         }                     },                 },                 batch: false,                 error: error,                 transport: {                     create: {                         url: &quot;\/odata\/Products&quot;,                         contentType: &quot;application\/json&quot;,                         type: &quot;POST&quot;,                     },                     read: {                         url: &quot;\/odata\/Products&quot;,                         dataType: &quot;json&quot;,                         contentType: &quot;application\/json&quot;,                      },                     update: {                         url: function (record) {                             return &quot;\/odata\/Products&quot; + &quot;(&quot; + record.ProductID + &quot;)&quot;;                         },                         dataType: &quot;json&quot;,                         contentType: &quot;application\/json&quot;,                         type: &quot;PUT&quot;,                         headers: { Prefer: &quot;return-content&quot; }                     },                     destroy: {                         url: function (record) {                             return &quot;\/odata\/Products&quot; + &quot;(&quot; + record.ProductID + &quot;)&quot;;                         },                         contentType: &quot;application\/json&quot;,                         type: &quot;DELETE&quot;                     },                     parametermap: function (data, operation) {                         console.log(data);                         if (operation === &quot;read&quot;) {                             var parammap = kendo.data.transports.odata.parametermap(data);                             return parammap;                         }                         return json.stringify(data);                     }                 }             }         });       });      function categoryDropDownEditor(container, options) {         $('&lt;input data-bind=&quot;value:CategoryID&quot;\/&gt;')             .appendTo(container)             .kendoDropDownList({                 dataTextField: &quot;Name&quot;,                 dataValueField: &quot;ID&quot;,                 optionLabel: &quot;--Select Value--&quot;,                 dataSource: {                     schema: {                         data: &quot;value&quot;,                         total: function (response) {                             return response['odata.count'];                         },                         model: {                             id: &quot;ID&quot;,                             fields: {                                 ID: { editable: false, type: &quot;number&quot; },                                 Name: { type: &quot;string&quot;, nullable: false },                              }                         },                     },                     type: &quot;odata&quot;,                     serverFiltering: true,                     serverPaging: true,                     pageSize: 20,                     transport: {                         read: {                             url: &quot;\/odata\/Categories&quot;,                             dataType: &quot;json&quot;,                             contentType: &quot;application\/json&quot;                         }                     },                     parametermap: function (data, operation) {                         if (operation === &quot;read&quot;) {                             var parammap = kendo.data.transports.odata.parametermap(data);                             return parammap;                         }                         return json.stringify(data);                     }                 },              });     } &lt;\/script&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0438 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e Kendo \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0439\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u0445. \u0417\u0430 \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <b>dataSource<\/b>. \u0412 schema \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432 \u043a\u0430\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445 \u0438\u0434\u0443\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 (<b>data<\/b>), \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (<b>total<\/b>), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445. \u00ab<b>total<\/b>\u00bb \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441 <b>GET \/odata\/Products?%24inlinecount=allpages&#038;%24top=5<\/b> \u0432\u044b\u0434\u0430\u0441\u0442 \u043f\u0435\u0440\u0432\u044b\u0435 5 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0412 <b>transport<\/b> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0425\u043e\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 <code>headers: { Prefer: &quot;return-content&quot; } <\/code>\u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <b>update<\/b>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044f\u0437\u0443\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0441 \u0438\u0437\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0434\u043b\u044f \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0440\u043d\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0442\u0432\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438. \u0414\u043b\u044f \u043f\u043e\u043b\u044f &quot;<b>CategoryName<\/b>&quot; \u0443\u043a\u0430\u0437\u0430\u043d \u0441\u0432\u043e\u0439 <code>editor: categoryDropDownEditor<\/code>, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e \u0441 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430. <br \/>  \u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0432\u043e\u0442 \u044d\u0442\u043e:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">script \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">&lt;script&gt;     function error(e) {         if (e.errorThrown === &quot;Bad Request&quot;) {             var response = JSON.parse(e.xhr.responseText);             console.log(response);             if (response['odata.error'] != undefined) {                 alert(response['odata.error'].message.value)             }         }         else {             alert(e.status + &quot;: &quot; + e.errorThrown)         }     }; &lt;\/script&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041a\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043e\u0448\u0438\u0431\u043a\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c <b>ODataError<\/b>, \u043f\u0440\u0438\u043c\u0435\u0440:  <\/p>\n<pre><code class=\"html\">{   &quot;odata.error&quot;:{     &quot;code&quot;:&quot;ValidationError&quot;,&quot;message&quot;:{       &quot;lang&quot;:&quot;en-US&quot;,&quot;value&quot;:&quot;\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435 Name.&quot;     }   } } <\/code><\/pre>\n<p>  \u0412 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0448\u0438\u0431\u043e\u043a. <\/p>\n<h5>\u0420\u0435\u0437\u044e\u043c\u0435<\/h5>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/storage2\/ad9\/763\/5c7\/ad97635c77b91f0bfafca393ff8026dd.png\" alt=\"image\"\/><br \/>  \u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 REST \u0441\u0435\u0440\u0432\u0438\u0441 \u0441 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0435\u0439, \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439, \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0435\u0439, \u043f\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439, \u043f\u0440\u0438 \u0447\u0435\u043c \u0432\u0441\u0435 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0434\u0432\u0443\u0445 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0412\u0441\u0435 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 .net MVC, \u0432\u0441\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. <br \/>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/storage2\/866\/36c\/a00\/86636ca006f78a1bedccd8617cd25888.png\" alt=\"image\"\/><br \/>  \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<br \/>  \u2022 <a href=\"http:\/\/www.asp.net\/web-api\/overview\/odata-support-in-aspnet-web-api\">\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0430\u0439\u0442<\/a><br \/>  \u2022 <a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2012\/11\/02\/odata-in-webapi-microsoft-asp-net-web-api-odata-0-2-0-alpha-release.aspx\">\u0411\u043b\u043e\u0433 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/a> <br \/>  \u2022 <a href=\"http:\/\/pluralsight.com\/training\/Courses\/TableOfContents\/aspnetwebapi-odata\">\u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 <\/a><\/p>\n<p>  P.S. \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0445\u0430\u0431\u0440\u0430\u0432\u0447\u0430\u043d \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0442\u0435\u043c\u0443 \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c SPA (Single page application) \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u041d\u043e \u0432\u043e\u0442 \u0432 \u0447\u0435\u043c \u0437\u0430\u0433\u0432\u043e\u0437\u0434\u043a\u0430 \u2013 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043c\u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0431\u0435\u0441\u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e. \u0415\u0441\u043b\u0438 \u0443 \u043a\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0438\u0434\u0435\u044f, \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u0447\u0430\u0442\u044c, \u0430 \u0432\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0425\u0430\u0431\u0440. \t\t\t \t\t\t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/180375\/\"> http:\/\/habrahabr.ru\/post\/180375\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0412 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u0448\u0435\u0434\u0448\u0435\u043c ASP.NET and <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=282650\">Web Tools 2012.2 Update<\/a> \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0430 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 oData \u0432 ASP.NET Web API. \u0420\u0435\u0448\u0438\u043b \u0441\u0430\u043c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c, \u0434\u0430 \u0438 \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0448\u0443 \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 oData \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 front-end \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d Kendo UI framework.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-180375","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/180375","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=180375"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/180375\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=180375"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=180375"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=180375"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}