2013-04-03 29 views
3

我正在使用OData构建Web API服务,并且想按如下方式在服务中公开方法。ASP.NET Web API在EDM模型根目录下的OData操作

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类?

回答

7

我们目前不支持这个开箱即用,但它很容易做到这一点。下面的例子(这个很好的例子实际上来自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); 
    } 
}  
+0

这正是我所期待的。我看到这个动作显示在'http:// myServer/odata/$ metadata'中,但是我怎样从客户端调用它?我目前正在使用WCF数据服务5.1(OData3)驱动程序进行连接测试,并且希望将OData操作看作是一种方法。但是,在LINQPad中,不可绑定的动作和绑定到实体集合的动作都不可见。 – MCattle 2013-04-04 17:51:21

+0

我发现这个,应该指向正确的方向:http://msdn.microsoft.com/en-us/library/hh859851(v=vs.103).aspx#sectionToggle3 – MCattle 2013-04-04 19:50:26

+0

@KiranChalla有没有关于这方面的最新新进展得到了开箱即用的支持? – mare 2013-11-26 12:09:00