ASP.NET Odata Web API可组合函数问题

时间:2015-06-09 14:59:07

标签: c# asp.net asp.net-web-api odata

我在Web API Odata中构建服务层,它暴露了文件管理API,我遇到了可组合函数的问题。让我们考虑以下场景。可以通过两种方式访问​​特定文件:通过ID或复杂路径。我最初的设计理念是拥有2个URL:

/File({IdAsGuid})
/Repositories({RepositoryName})/Libraries({libName})/Path({path})/api.getFileByName(name={fileName})

使用OdataRoute属性可以很好地工作。 下一步是支持版本,它们将使用URL,如:

/File({IdAsGuid})/Versions({versionNumber})
/Repositories({RepositoryName})/Libraries({libName})/Path({path})/api.getFileByName(name={fileName})/Versions({versionNumber})

使用EntitySet"版本"作为路径段没有问题或第一个URL。但Odata拒绝验证函数调用后使用的EntitySet。错误:

  

细分' eBesNg.getContentByName'必须是最后一段   URI,因为它是以下之一:$ ref,$ batch,$ count,$ value,   $ metadata,命名媒体资源,动作,不可分解   功能,动作导入,不可分解的功能导入,   void返回类型的操作,或带void的操作导入   返回类型。

经过一些研究,我意识到这个功能定义如下:

 builder.Namespace = "api";
 var function = builder.EntityType<Path>().Function("getFileByName");
 function.Parameter<string>("name");
 function.ReturnsFromEntitySet<File>("Files");

可能需要additonaly:

function.IsComposable = true;

然而,这产生了一个不同的问题。现在在Odata验证期间,我收到Null Exception:

[NullReferenceException: Object reference not set to an instance of an object.]   
     

Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CreatePropertySegment(ODataPathSegment   previous,IEdmProperty属性,String queryPortion)+205
  Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CreateNextSegment(字符串   文字)+405
  Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.ParsePath(ICollection的1 segments) +244
Microsoft.OData.Core.UriParser.Parsers.ODataPathFactory.BindPath(ICollection
1   segment,ODataUriParserConfiguration配置)+96
  Microsoft.OData.Core.UriParser.ODataUriParser.ParsePathImplementation()   205

我错过了什么?是不是可以将函数用作导航并继续在Odata中导航结果?

1 个答案:

答案 0 :(得分:0)

您应该正确设置函数的EntitySetPath。那就是取代

function.ReturnsFromEntitySet( “文件”);

function.ReturnsEntityViaEntitySetPath( “bindingParameter / XXX”);

以下是完整的示例:

class Path
{
    public string Id { get; set; }
    public File File { get; set; }
}

class File
{
    public Guid Id { get; set; }
    public ICollection<Version> Versions { get; set; }
}

class Version
{
    public string Id { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var builder = new ODataConventionModelBuilder();
        builder.Namespace = "api";
        builder.EntityType<File>();
        var function = builder.EntityType<Path>().Function("getFileByName");
        function.Parameter<string>("name");
        //function.ReturnsFromEntitySet<File>("Files");
        function.ReturnsEntityViaEntitySetPath<File>("bindingParameter/File");
        function.IsComposable = true;
        builder.EntitySet<Path>("Paths");
        builder.EntitySet<Version>("Versions");
        var model = builder.GetEdmModel();

        string path = "Paths('1')/api.getFileByName(name='sd')/Versions('s')";
        var parser = new ODataUriParser(model, new Uri(path, UriKind.Relative));
        var pa = parser.ParsePath();
        Console.WriteLine(pa);
    }
}