【问题标题】:ASP.NET Web API OData Action on the EDM Model RootEDM 模型根上的 ASP.NET Web API OData 操作
【发布时间】:2013-03-25 19:14:34
【问题描述】:

我正在使用 OData 构建 Web API 服务,并希望将方法公开为服务中的操作,如下所示。

http://myServer/odata/myAction

我目前正在按如下方式映射 OData 路由:

Dim modelBuilder As ODataModelBuilder = New ODataConventionModelBuilder
modelBuilder.EntitySet(Of Product)("Products")

Dim myAction = modelBuilder.Action("myAction")
myAction.Parameter(Of String)("Parameter1")
myAction.Returns(Of Boolean)()

Dim model As IEdmModel = modelBuilder.GetEdmModel
config.Routes.MapODataRoute("ODataRoute", "odata", model)

This wonderful tutorial 展示了如何将动作与这样的实体相关联:

http://myServer/odata/Products(1)/myAction

按照教程,我可以在创建模型后在 ProductsController 类中编写操作的方法,使用以下代码行:

Dim myAction = modelBuilder.Entity(Of Product).Action("myAction")

但是,如果我不想将动作与实体相关联,我应该在哪里编写动作的方法?有没有我需要写的 DefaultController 类?

【问题讨论】:

    标签: vb.net asp.net-web-api action odata


    【解决方案1】:

    我们目前不提供开箱即用的支持,但您自己很容易做到这一点。下面的示例(这个不错的示例实际上来自尚未公开的 Mike Wasson :-))

    ------------------------------------------------------
    // CreateMovie is a non-bindable action. 
    // You invoke it from the service root: ~/odata/CreateMovie
    ActionConfiguration createMovie = modelBuilder.Action("CreateMovie");
    createMovie.Parameter<string>("Title");
    createMovie.ReturnsFromEntitySet<Movie>("Movies");
    
    // Add a custom route convention for non-bindable actions.
    // (Web API does not have a built-in routing convention for non-bindable actions.)
    IList<IODataRoutingConvention> conventions = ODataRoutingConventions.CreateDefault();
    conventions.Insert(0, new NonBindableActionRoutingConvention("NonBindableActions"));
    
    // Map the OData route.
    Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
    config.Routes.MapODataRoute("ODataRoute", "odata", model, new DefaultODataPathHandler(), conventions);
    
    --------------------------------------------------------------
    
    // Implements a routing convention for non-bindable actions.
    // The convention maps "MyAction" to Controller:MyAction() method, where the name of the controller 
    // is specified in the constructor.
    public class NonBindableActionRoutingConvention : IODataRoutingConvention
    {
        private string _controllerName;
    
        public NonBindableActionRoutingConvention(string controllerName)
        {
            _controllerName = controllerName;
        }
    
        // Route all non-bindable actions to a single controller.
        public string SelectController(ODataPath odataPath, System.Net.Http.HttpRequestMessage request)
        {
            if (odataPath.PathTemplate == "~/action")
            {
                return _controllerName;
            }
            return null;
        }
    
        // Route the action to a method with the same name as the action.
        public string SelectAction(ODataPath odataPath, System.Web.Http.Controllers.HttpControllerContext controllerContext, ILookup<string, System.Web.Http.Controllers.HttpActionDescriptor> actionMap)
        {
            if (controllerContext.Request.Method == HttpMethod.Post)
            {
                if (odataPath.PathTemplate == "~/action")
                {
                    ActionPathSegment actionSegment = odataPath.Segments.First() as ActionPathSegment;
                    IEdmFunctionImport action = actionSegment.Action;
    
                    if (!action.IsBindable && actionMap.Contains(action.Name))
                    {
                        return action.Name;
                    }
                }
            }
            return null;
        }
    }
    
    --------------------------------------------------
    
    // Controller for handling non-bindable actions.
    [ODataFormatting]
    [ApiExplorerSettings(IgnoreApi = true)]
    public class NonBindableActionsController : ApiController
    {
        MoviesContext db = new MoviesContext();
    
        [HttpPost]
        public Movie CreateMovie(ODataActionParameters parameters)
        {
            if (!ModelState.IsValid)
            {
                throw new HttpResponseException(HttpStatusCode.BadRequest);
            }
    
            string title = parameters["Title"] as string;
    
            Movie movie = new Movie()
            {
                Title = title
            };
    
            db.Movies.Add(movie);
            db.SaveChanges();
            return movie;
        }
    
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }    
    

    【讨论】:

    • 这正是我想要的。我看到该操作显示在http://myServer/odata/$metadata 中,但是我如何从客户端调用它?我目前正在 LINQPad 中进行测试,使用 WCF Data Services 5.1 (OData3) 驱动程序进行连接,并希望像调用方法一样调用 OData 操作。但是,不可绑定的操作和绑定到实体集合的操作在 LINQPad 中都不可见。
    • 我找到了这个,它应该为我指明正确的方向:msdn.microsoft.com/en-us/library/…
    • @KiranChalla 最近有什么开箱即用的支持吗?
    猜你喜欢
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2020-10-06
    • 2021-11-15
    相关资源
    最近更新 更多