2014-10-29 61 views
13

OData V4規範規定它必須是可能的: https://issues.oasis-open.org/browse/ODATA-636如何在ASP.NET Web API實現中將數組傳遞給OData函數?

「複雜類型和數組只能通過 參數別名被傳遞給函數」當我試圖用的OData參數別名發生異常傳遞一個數組。

/TestEntities/NS.TestFunction([email protected])[email protected]=[1,2,3]

結果:

無法轉換類型的對象「EdmValidCoreModelPrimitiveType」鍵入 「Microsoft.OData.Edm.IEdmStructuredType

有趣的是,元數據文件是正確的COM這種情況下提出:

<Function Name="TestFunction" IsBound="true"> 
    <Parameter Name="bindingParameter" Type="Collection(NS.TestEntity)"/> 
    <Parameter Name="ArrayHere" Type="System.Int32[]"/> 
    <ReturnType Type="Collection(NS.TestEntity)"/> 
</Function> 

是否有可能使用ASP.NET MVC Web API 2 OData將數組傳遞給查詢字符串中的OData函數?

UPDATE:

這裏是構建EDM模型和控制器的代碼。

var builder = new ODataConventionModelBuilder(); 

builder.Namespace = "NS"; 

builder.EntitySet<TestEntity>("TestEntities"); 

builder.EntityType<TestEntity>().Collection 
    .Function("TestFunction") 
    .ReturnsCollectionFromEntitySet<TestEntity>("TestEntities") 
    .Parameter<int[]>("ArrayHere"); 

控制器:

public class TestEntitiesController : ODataController 
{ 
    public IEnumerable<TestEntity> TestFunction(int[] arrayHere) 
    { 
     throw new NotImplementedException(); 
    } 
} 

標記與[FromODataUri]參數不解決問題。

更新2:

這裏是堆棧跟蹤:

at Microsoft.OData.Core.UriParser.TypePromotionUtils.CanConvertTo(SingleValueNode sourceNodeOrNull, IEdmTypeReference sourceReference, IEdmTypeReference targetReference) 
at Microsoft.OData.Core.UriParser.Parsers.MetadataBindingUtils.ConvertToTypeIfNeeded(SingleValueNode source, IEdmTypeReference targetTypeReference) 
at Microsoft.OData.Core.UriParser.Parsers.FunctionCallBinder.BindSegmentParameters(ODataUriParserConfiguration configuration, IEdmOperation functionOrOpertion, ICollection`1 segmentParameterTokens) 
at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.TryBindingParametersAndMatchingOperation(String identifier, String parenthesisExpression, IEdmType bindingType, ODataUriParserConfiguration configuration, ICollection`1& boundParameters, IEdmOperation& matchingOperation) 
at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.TryCreateSegmentForOperation(ODataPathSegment previousSegment, String identifier, String parenthesisExpression) 
at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CreateNextSegment(String text) 
at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.ParsePath(ICollection`1 segments) 
at Microsoft.OData.Core.UriParser.Parsers.ODataPathFactory.BindPath(ICollection`1 segments, ODataUriParserConfiguration configuration) 
at Microsoft.OData.Core.UriParser.ODataUriParser.ParsePathImplementation() 
at Microsoft.OData.Core.UriParser.ODataUriParser.Initialize() 
at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath, Boolean enableUriTemplateParsing) 
at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath) 
at System.Web.OData.Routing.ODataPathRouteConstraint.Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary`2 values, HttpRouteDirection routeDirection) 
at System.Web.Http.Routing.HttpRoute.ProcessConstraint(HttpRequestMessage request, Object constraint, String parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) 
at System.Web.Http.Routing.HttpRoute.ProcessConstraints(HttpRequestMessage request, HttpRouteValueDictionary values, HttpRouteDirection routeDirection) 
at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) 
at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext) 
+0

燦你張貼拋出異常的代碼? – Pseudonym 2014-10-29 15:45:59

+0

有趣的問題,我真的很高興看到你用來將函數添加到$元數據和函數實現的代碼。 – gdoron 2014-10-29 19:32:16

+0

@gdoron,請參閱已更新的問題 – 2014-10-30 17:24:09

回答

8

我不知道你當前正在使用的OData的版本,但這裏是我已經實現了一個解決方案,適用於V4和傳遞簡單的數組到的OData Action方法

在你WebConfig.cs

ODataModelBuilder builder = new ODataConventionModelBuilder(); 
builder.EntitySet<TestEntity>("TestEntities"); 

builder.Namespace = "NS"; 

builder.EntityType<TestEntity>() 
     .Action("TestAction") 
    .CollectionParameter<string>("ArrayHere");  

在這裏,你的控制器的方法

[HttpPost] 
public async Task<IHttpActionResult> TestAction([FromODataUri] int key, ODataActionParameters parameters) 
{ 
    // Do your thing here.. 
    var invites = parameters["ArrayHere"] as IEnumerable<string>; 
} 

產生的API端點請求看起來應該像下面這樣:

POST http://localhost/odata/TestEntities(1)/NS.TestAction HTTP/1.1 
Content-type: application/json 
Host: localhost:49255 
Content-Length: 37 

{"ArrayHere":["hello", "world"]}  

我去了這方面的問題了幾次,並不能使它爲OData功能工作。我挖得更深一點,發現了一切方法的CollectionParameter<>()方法。我沒有回去嘗試用Function,因爲我沒有真正看到需要。我希望這可以幫助你

+1

感謝您的答案,但問題是關於傳遞數組到OData函數(作爲查詢字符串的一部分),而不是Action(作爲請求有效載荷),也爲我工作。 – 2015-01-22 07:53:38

14

假設你使用的是OData V4,你需要在註冊函數時使用CollectionParameter,並且你在arrayHere參數上缺少[FromODataUri]。另外,請使用IEnumerable<int>而不是數組來嘗試。

var builder = new ODataConventionModelBuilder(); 

builder.Namespace = "NS"; 

builder.EntitySet<TestEntity>("TestEntities"); 

builder.EntityType<TestEntity>().Collection 
    .Function("TestFunction") 
    .ReturnsCollectionFromEntitySet<TestEntity>("TestEntities") 
    .CollectionParameter<int>("ArrayHere"); 

有了這樣的控制器功能...

[HttpGet] 
public async Task<IHttpActionResult> TestFunction([FromODataUri] IEnumerable<int> ArrayHere) 
{ 
    // Do stuff 
} 

現在你可以做出這樣的請求......

http://yourRestService/API/TestEntities/NS.TestFunction(ArrayHere=[1,2,3])

作爲一個說明,你也可以接受一系列複雜類型。你必須URL編碼爲陣列JSON和使用參數別名,所以你會像這樣結束了......

builder.EntityType<TestEntity>().Collection 
    .Function("TestFunction2") 
    .ReturnsCollectionFromEntitySet<TestEntity>("TestEntities") 
    .CollectionParameter<person>("ArrayHere"); 

[HttpGet] 
public async Task<IHttpActionResult> TestFunction2([FromODataUri] IEnumerable<person> ArrayHere) 
{ 
    // Do stuff 
} 

http://yourRestService/API/TestEntities/NS.TestFunction2([email protected])[email protected]=%5B%7B%22FirstName%22%3A%22Bob%22%2C+%22LastName%22%3A%22Dole%22%7D%2C%7B%22FirstName%22%3A%22Bill%22%2C+%22LastName%22%3A%22Clinton%22%7D%5D

+0

太棒了! CollectionParameter!我試圖使用參數()。我想澄清的是,這些參數的值包含在括號中的網址:NS.TestFunction9(IntArrayHere = [11,12,13,14,15]) – Jerther 2015-10-22 12:42:27

+0

嗯,我想知道爲什麼我得到了對此投票。有任何想法嗎? – MHollis 2015-11-20 15:00:13

+0

太棒了... Upvote from .. – 2016-02-22 14:22:57