本文转自:https://code.msdn.microsoft.com/Support-Composite-Key-in-d1d53161

he default EntitySetController doesn't support composite keys. So if you have composite key models, you need some additional work. Here is an example about how to do that.

The model is simple:

public class Person
{
[Key]
public string FirstName { get; set; }
[Key]
public string LastName { get; set; } public int Age { get; set; }
}

The odata url for this model will look like:

GET http://localhost:33051/People(FirstName='Kate',LastName='Jones') HTTP/1.1

And we want to have strong typed parameters in web api actions to this URL.

    public Person Get([FromODataUri] string firstName, [FromODataUri] string lastName)

Note that the FromODataUri model binder attribute is used to parse from odata uri representation to clr type. In odata, string value is "'xxx'" and we want it to be "xxx".

In order to make the route to work, you can add a custom routing convention to parse the key path. Here is a sample implementation:

public class CompositeKeyRoutingConvention : EntityRoutingConvention
{
public override string SelectAction(System.Web.Http.OData.Routing.ODataPath odataPath, System.Web.Http.Controllers.HttpControllerContext controllerContext, ILookup<string, System.Web.Http.Controllers.HttpActionDescriptor> actionMap)
{
var action = base.SelectAction(odataPath, controllerContext, actionMap);
if (action != null)
{
var routeValues = controllerContext.RouteData.Values;
if (routeValues.ContainsKey(ODataRouteConstants.Key))
{
var keyRaw = routeValues[ODataRouteConstants.Key] as string;
IEnumerable<string> compoundKeyPairs = keyRaw.Split(',');
if (compoundKeyPairs == null || compoundKeyPairs.Count() == 0)
{
return action;
} foreach (var compoundKeyPair in compoundKeyPairs)
{
string[] pair = compoundKeyPair.Split('=');
if (pair == null || pair.Length != 2)
{
continue;
}
var keyName = pair[0].Trim();
var keyValue = pair[1].Trim(); routeValues.Add(keyName, keyValue);
}
}
} return action;
}
}

The convention is inherited from EntityRoutingConvention, which is the default convetion to handle entity key. By calling base.SelectAction, it will add the full key path into routeValues. The new convention will check if it contains "," and seperate it into multiple keys and set each of them into routeValues. So when web api select actions, it will use those values to determine which action to choose. If there is no "," found, it behaves same as base convetion.

To register the convetion, you need to set it when mapping odata route:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableQuerySupport(); var mb = new ODataConventionModelBuilder(config);
mb.EntitySet<Person>("People"); var conventions = ODataRoutingConventions.CreateDefault();
conventions.Insert(0, new CompositeKeyRoutingConvention()); config.Routes.MapODataRoute(
routeName: "OData",
routePrefix: null,
model: mb.GetEdmModel(),
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions);
}
}

Register the route at the postion 0 is to make it be executed before other default routing convetions. So the default EntityRoutingConvetion won't be executed before it. After that, you should be able to get routing work.

Then, how to build url for composite keys? 
You don't need to do that for odata links include edit link and self link when using ODataConventionModelBuilder. It will automatically identify composite keys and build the uri for you.

However, you need to build the link for location header. Here is a sample code from PeopleController.cs to handle post request:

public HttpResponseMessage PostPerson(Person person)
{
if (ModelState.IsValid)
{
_repo.UpdateOrAdd(person); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, person);
string key = string.Format(
"{0}={1},{2}={3}",
"FirstName", ODataUriUtils.ConvertToUriLiteral(person.FirstName, Microsoft.Data.OData.ODataVersion.V3),
"LastName", ODataUriUtils.ConvertToUriLiteral(person.LastName, Microsoft.Data.OData.ODataVersion.V3));
response.Headers.Location = new Uri(Url.ODataLink(
new EntitySetPathSegment("People"),
new KeyValuePathSegment(key)));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}

Hope it helps.

[转]Support Composite Key in ASP.NET Web API OData的更多相关文章

  1. node-odata: ASP.NET WEB API OData的替代品

    什么是 OData 协议? OData, 相信身为 .NET 程序员应该不为陌生, 尤其是它的实现: ASP.NET WEB API OData. 对于 OData, 官网上对其的定义是 OData ...

  2. [转]Getting started with ASP.NET Web API OData in 3 simple steps

    本文转自:https://blogs.msdn.microsoft.com/webdev/2013/01/29/getting-started-with-asp-net-web-api-odata-i ...

  3. 如何使用ASP.NET Web API OData在Oracle中使用Entity Framework 6.x Code-First方式开发 OData V4 Service

    环境: Visual Studio 2013 + .Net Framework 4.5.2 1.新建项目 2.安装OData,ODP.NET 安装的包: 下面是部分代码: using System; ...

  4. [转]ASP.NET web API 2 OData enhancements

    本文转自:https://www.pluralsight.com/blog/tutorials/asp-net-web-api-2-odata-enhancements Along with the ...

  5. Asp.Net Web Api 与 Andriod 接口对接开发经验,给小伙伴分享一下!

    最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用Asp.Net Web Api去跟 Andriod 那端做接口对接工作,自己也是第一次接触Web ...

  6. Asp.Net Web Api 与 Andriod 接口对接开发

    Asp.Net Web Api 与 Andriod 接口对接开发经验,给小伙伴分享一下!   最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用A ...

  7. [转]Supporting OData Query Options in ASP.NET Web API 2

    本文转自:https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/suppor ...

  8. Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)

    前言 很久没更新博客了,加上刚过年,现在准备重新开战,继续自己的学习之路.本文已同步到Web API2系列文章中http://www.cnblogs.com/aehyok/p/3446289.html ...

  9. [转]ASP.NET Web API对OData的支持

    http://www.cnblogs.com/shanyou/archive/2013/06/11/3131583.html 在SOA的世界中,最重要的一个概念就是契约(contract).在云计算的 ...

随机推荐

  1. 1-初步了解C#-语言基础

    本篇博客对应视频讲解 前言 终于开始讲语言了,我选择讲C#.为什么呢?因为C#是很好的入门语言,简洁.全面,面向对象类型安全,开发体验好,上手容易.而其他的语言也已经有人讲了很多了,C#相对来说要少一 ...

  2. ASP .NET运行机制(visio图)

  3. TestNG参数化之@Parameters传参

    通过TestNG实现参数话常用两种方式,一种是借助 @Parameters读取testng.xml中参数,一种是使用@DataProvider注解传参. 此次主要讲解XML传参,语法:在java类中定 ...

  4. StringBudiler源码简单解析

    StringBudiler源码 继承关系树 底层实现 默认容量() 特别的添加方法(append) 1.继承关系树 继承自AbstractStringBuilder与StringBuffer同族 2. ...

  5. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  6. FFmpeg工具使用总结

    . 一. FFmpeg是什么? 简单说,FFmpeg就是一个很好的,免费的,开源的视频转换工具.详细说,FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依 ...

  7. 隔离python 运行环境和Pycharm 设置代码同步

    隔离python 运行环境 查看当前有哪些虚拟环境:workon 进入虚拟环境:workon django 退出虚拟环境:deactivate 创建虚拟环境: mkvirtualenv -p /usr ...

  8. Exponentiation POJ-1001

    http://poj.org/problem?id=1001 //10000000 100000 #include<iostream> #include<cstring> us ...

  9. poj3207 Ikki's Story IV - Panda's Trick 2-SAT

    题目传送门 题意:在一个圆上顺时针安放着n个点,给出m条线段连接端点,要求线段不相交,线段可以在圆内也可以在圆外,问是否可以. 思路:假设一条线段,放在圆外是A,放在园内是A',那么两条线段如果必须一 ...

  10. SPOJ Lexicographical Substring Search 求字典序第k大子串 后缀自动机

    题目传送门 思路:按字典序,小的字符优先选取.对于一个字符,如果以这个字符开头的子串大于等于k个,那说明这个字符是应该选的,并且选完之后,可能还要继续选.如果以这个字符开头的子串小于k个,说明这个字符 ...