C# Web API 2.2 OData V4-剑道网格-自定义创建的IHttpActionResult
我有一个连接到odata CRUD服务的剑道UI网格(Web API 2.2 odata V4)。数据源配置如下所示-baseUrl对所有人都是相同的,只是HTTP谓词发生了变化C# Web API 2.2 OData V4-剑道网格-自定义创建的IHttpActionResult,c#,kendo-grid,odata,asp.net-web-api,C#,Kendo Grid,Odata,Asp.net Web Api,我有一个连接到odata CRUD服务的剑道UI网格(Web API 2.2 odata V4)。数据源配置如下所示-baseUrl对所有人都是相同的,只是HTTP谓词发生了变化 var dataSource = new kendo.data.DataSource({ type: "odata", transport: { read: { beforeSend: prepareRequest, url: baseUr
var dataSource = new kendo.data.DataSource({
type: "odata",
transport: {
read: {
beforeSend: prepareRequest,
url: baseUrl,
type: "GET",
dataType: "json"
},
update: {
beforeSend: prepareRequest,
url: function (data) {
return baseUrl + "(" + data.CategoryId + ")";
},
type: "PUT",
dataType: "json"
},
create: {
beforeSend: prepareRequest,
url: baseUrl,
type: "POST",
dataType: "json"
},
destroy: {
beforeSend: prepareRequest,
url: function (data) {
return baseUrl + "(" + data.CategoryId + ")";
},
type: "DELETE",
dataType: "json"
},
parameterMap: function (data, operation) {
if (operation == "read") {
var paramMap = kendo.data.transports.odata.parameterMap(data);
delete paramMap.$format;
delete paramMap.$inlinecount;
paramMap.$count = true;
return paramMap;
} else if (operation == "create" || operation == "update") {
delete data["__metadata"];
return JSON.stringify(data);
}
}
},
batch: false,
pageSize: 10,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
sort: { field: "CategoryCode", dir: "asc" },
schema: {
data: function (data) { return data.value; },
total: function (data) { return data['@@odata.count']; },
model: {
id: "CategoryId",
fields: {
CategoryId: { editable: false, type: "number" },
CategoryCode: { editable: true, type: "string", required: true, validation: { maxlength: 2 } },
Description: { editable: true, type: "string", required: true, validation: { maxlength: 50 } },
Created: { editable: false, type: "date" },
CreatedBy: { editable: false, type: "string" },
Updated: { editable: false, type: "date" },
UpdatedBy: { editable: false, type: "string" }
}
}
},
error: function (e) {
commonNotification.hide();
commonNotification.show(getRequestError(e), "error");
},
change: function (e) {
commonNotification.hide();
if (e.action == "sync") {
commonNotification.show("@SharedResources.Changes_Saved", "success");
}
},
requestStart: function (e) {
if (e.type == "read" && this.hasChanges()) {
if (confirm("@SharedResources.Dirty_Navigation_Confirmation") == false) {
e.preventDefault();
} else {
this.cancelChanges();
}
}
}
});
一般来说,一切都很好。prepareRequest()函数用于应用自定义授权标头,并将Accept标头设置为“application/json;odata=verbose”
读取时,JSON响应如下所示-这就是为什么dataSource.schema.data函数返回data.value
{
"@odata.context":"https://localhost:44305/odata/$metadata#Categories",
"@odata.count":2,
"value":[
{
"CategoryId":1,
"CategoryCode":"01",
"Description":"Something",
"Created":"2014-08-01T11:03:30.207Z",
"CreatedBy":"DOMAIN\\User",
"Updated":"2014-09-05T14:36:22.6323744-06:00",
"UpdatedBy":"DOMAIN\\User"
},{
"CategoryId":2,
"CategoryCode":"02",
"Description":"Something Else",
"Created":"2014-08-01T11:03:35.61Z",
"CreatedBy":"DOMAIN\\User",
"Updated":"2014-08-26T16:07:29.198241-06:00",
"UpdatedBy":"DOMAIN\\User"
}
]
}
但是,当我创建或更新实体时,返回的JSON如下所示:
{
"@odata.context":"https://localhost:44305/odata/$metadata#Categories/$entity",
"CategoryId":3,
"CategoryCode":"03",
"Description":"Yet Another",
"Created":"2014-09-06T07:55:52.4933275-06:00",
"CreatedBy":"DOMAIN\\User",
"Updated":"2014-09-06T13:55:34.054Z",
"UpdatedBy":""
}
因为这不是用“值”包装的,所以剑道网格没有正确地更新数据源。执行POST或PUT的控制器当前返回实体,如下所示:
return Created(category);
return Json(new { value = new[] { category } });
schema: {
data: function (data) {
if (data.value) {
return data.value;
} else {
delete data["@@odata.context"];
return data;
}
},
total: function (data) { return data['@@odata.count']; },
model: {
etc...
或
我可以通过将响应更改为JsonResult来解决此问题,如下所示:
return Created(category);
return Json(new { value = new[] { category } });
schema: {
data: function (data) {
if (data.value) {
return data.value;
} else {
delete data["@@odata.context"];
return data;
}
},
total: function (data) { return data['@@odata.count']; },
model: {
etc...
有了它,一切都按预期工作……然而,我的HTTP响应现在是200(似乎JsonResult总是以200作为响应)。在一个完美的世界里,我可以在创建时返回201。我是否应该接受我让它和200一起工作和生活,或者,是否有一种简单的方法来响应201并根据需要格式化我的JSON?Web API 2似乎允许更定制的http响应,但我的Web API 2.2控制器操作正在返回IHttpActionResult。我真的不想创建一个自定义类只是为了有一个特殊的返回类型,而且我似乎不能用Created()返回我的匿名对象
总而言之,我真的倾向于用我所拥有的生活。然而,我希望有一种方法可以返回带有201的匿名对象,或者有一种方法可以接受剑道数据源中的非“值包装”json,并让它适当地更新数据。这就是我最终要做的——我创建了自己的“CreatedObject”方法来生成ResponseMessageResult。这将使用匿名“value”对象包装对象,并序列化为json。然后,我可以返回它和所需的响应代码
public ResponseMessageResult CreatedObject(string location, object createdObject)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(new { value = new[] { createdObject } });
// Create the response and add the 201 response code
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Created);
response.Headers.Add("Location", location);
response.Content = new System.Net.Http.StringContent(json);
// return the result
return ResponseMessage(response);
}
这解决了Kendo数据源作为客户端的问题。但是,我不喜欢为特定客户机操纵odata响应的想法。因此,我修改了客户端以处理正常的Web API OData响应,如下所示:
return Created(category);
return Json(new { value = new[] { category } });
schema: {
data: function (data) {
if (data.value) {
return data.value;
} else {
delete data["@@odata.context"];
return data;
}
},
total: function (data) { return data['@@odata.count']; },
model: {
etc...
现在,在返回适当的数据之前,schema.data()函数检查对象是否包装在“值”中。当返回创建的对象时,我必须删除@odata.context属性,因为kendo不喜欢它。我更喜欢在客户端处理这个问题的解决方案。 我必须添加一个非空的PK,因为我的odata端点将不包含空id:
parameterMap: function (data, operation) {
if (operation == "read") {
var paramMap = kendo.data.transports.odata.parameterMap(data);
delete paramMap.$format;
delete paramMap.$inlinecount;
paramMap.$count = true;
return paramMap;
} else if (operation == "create" || operation == "update") {
//delete data["__metadata"];
if (data.Id==null) {
data.Id = 1;
}
return JSON.stringify(data);
}
},
更新,因为不再需要任何调整来使其工作 从更改数据集类型
键入:“odata”
到
键入:“odata-v4”
我们应该做到这一点。示例源代码是