web api 2 学习笔记 (OData RPC)

Web API 2 + OData v4 

等我熟悉了再写一个完整系列. 这里只给我自己看

builder : 

复制代码
//Entity RPC 写方
builder.Namespace = "RPC";
var gettotalFn = builder.EntityType<Voucher>().Collection.Function("getTotal"); //Function 是用于安全请求的
gettotalFn.Returns<int>(); //一般都是返回 Task<IHttpActionResult>, 所以这里写什么不太重要,也不会有什么error
var setTotalAction = builder.EntityType<Voucher>().Collection.Action("setTotal");
setTotalAction.Returns<int>();
setTotalAction.ReturnsFromEntitySet<LoginPerson>("loginPersons"); //如果返回entity要这样写,loginPersons 如果之前有命名过,那么要写一模一样哦
setTotalAction.ReturnsCollectionFromEntitySet<LoginPerson>("loginPersons") //for List<LoginPersons>

//官网的写法
var setTotalTwoAction = builder.EntityType<Voucher>().Collection.Action("setTotalTwo");
setTotalTwoAction.Returns<int>();
setTotalTwoAction.Parameter<string>("name");
setTotalTwoAction..CollectionEntityParameter<string>("names"); //List<string> 的写法  
//Global RPC 写法 var getDataAction = builder.Action("setData"); //setData route name not method name oh!,所以我们要写符号也行,e.g. 通过[ODataRoute("abc.setData")] 也是可以调用到的。 getDataAction.Returns<int>(); var getDataFn = builder.Function("getData"); getDataFn.Returns<int>();

.Collection.Action 和 .Action 是有区别的, 一个表示 /api/Orders/RPC.xxx 另一个是 /api/Orders(5)/RPC.xxx
复制代码

entity controller :

复制代码
//GET : //localhost:55573/api/vouchers?$skip=5&customeData=5
public IQueryable<Voucher> get(ODataQueryOptions<Voucher> options, int customeData) 
{
    return db.vouchers;
}
//DELETE : //localhost:55573/api/vouchers(5)
[ODataRoute("({id})")]
public async Task<IHttpActionResult> delete([FromODataUri]int id)
{
    return Ok("");
}
//POST : //localhost:55573/api/vouchers  (body is voucher object json)
public async Task<IHttpActionResult> post([FromBody]Voucher voucher)
{
    return Ok(voucher);
}

//RPC----------------------------------------------------------------------------------------------------

//GET //localhost:55573/api/vouchers/RPC.getTotal()
public async Task<int> getTotal() //这里可以依赖注入ODataQueryOptions | body data | params 都可以的!
{
    return 11;
}
//POST //localhost:55573/api/vouchers/RPC.setTotal?paraData=5
//body : {name : "keatkeat"}
public class BodyData
{
    public string name { get; set; }
}
//这里没有放[HttpPost]也是可以,但是方法名字千万不要用get开头
public async Task<int> setTotal(int paraData, BodyData bodyData) //这里可以依赖注入ODataQueryOptions | body data | params 都可以的! { return 11; } //官网的写法
[ODataRoute("({id})/RPC.updateProducts")] 如果要api/products(1)/RPC.updateProducts 就要这样写
public async Task<IHttpActionResult> setTotalTwo(int paraData, ODataActionParameters parameters) { string name = (string)parameters["name"]; //get from body 这是个字典
   List<AccountRole> roles = ((IEnumerable<AccountRole>)(parameter["roles"])).ToList();  for list
return Ok(11); }

复制代码

 

Global contoller : 

复制代码
    //开一个隔离的ctrl for Global RPC
    public class RPCController : ODataBaseController
    {
        //POST //localhost:55573/api/getData()  这里不需要放namspace哦
        [HttpPost] //一定要放
        [ODataRoute("setData")] //需要用ODataRoute 帮助     
        //parameter 和entity RPC 的用法是一样的
        public async Task<IHttpActionResult> setData()
        {           
            return Ok(11);
        }

        //GET //localhost:55573/api/getData()  
        [HttpGet]
        [ODataRoute("getData")]
        public async Task<IHttpActionResult> getData()
        {
            return Ok(22);
        }
    }
复制代码

 Note : Odata 所有控制器,如果没有写上attribute [HttpPost|Get|..]  来表明它的请求方法,那么Odata会智能的用你的方法名开头来做请求方法的区分。

    建议 : 1. 方法名前面都加入请求方式

       2. 使用Attribute 

 

更新 : 

今天遇到一个bug, 就是如果我们没有使用上面说的官网的写法的话,parameter不可以是抽象的, 也不可以是 entity 类, 所以只可以放一些简单的对象, 可能是 odata 无法智能的从@odata.type 里创建出来。解决方法很简单就是使用官网的写法就可以了。

还有就是抽象是不能被 Validate 的 

 

复制代码
[ODataRoute("RPC.setPayment")]
public async Task<IHttpActionResult> setPayment(ODataActionParameters parameters) 
{
    if (!ModelState.IsValid) //这里只是验证 parameter 类型是否正确
    {

    }
    else
    {
        SetPaymentData s = (SetPaymentData)parameters["setPaymentData"];
        BankTransfer payment = (BankTransfer)parameters["payment"];

        Validate(s);
        if (!ModelState.IsValid) //这里才是验证 property 
        {

        }
        Validate(payment);
        if (!ModelState.IsValid) //error 会被累加起来 
        {

        }
    } 
    return Ok();
}
复制代码

 

 

更新  : 2016-01-29 

RPC Globar 案例

var getOrder = builder.Function("getOrder"); //简单的写 builder.Function 或 builder.Action 
//return 和 normal 一样

 

复制代码
//可以用一个 GlobalController 来装
public
class GlobalController : BaseController { [ODataRoute("getOrder")] [EnableQuery(AllowedQueryOptions = Helper.ALLOW_QUERY | AllowedQueryOptions.Expand, MaxExpansionDepth = 4)] public SingleResult<Order> getOrder(string code, string token) { IQueryable<Order> order = db.Orders.Where(o => o.code == code && o.token == token); return SingleResult.Create<Order>(order); } }
复制代码

builder.Function("名子") ,ODataRoute("名字") , api/"名字" 一致, 方法名就无所谓

调用的 url 是 "api/getOrder" 

 

posted @   兴杰  阅读(537)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 百万级群聊的设计实践
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示