如何将复杂的对象参数传递给odata webapi 2.2函数

时间:2014-06-13 13:31:02

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

控制器:

public class PhaseController: ODataController
{
    [EnableQuery]
    [System.Web.Http.HttpGet]
    public IQueryable < Phase > CustomPhases(CustomPhaseRequest request = null)
    {

        if (request == null) //default values
            request = new CustomPhaseRequest()
        {
            Duration = 3,
                PhaseFilters = new List < CustomPhaseFilter > ()
                {
                    new CustomPhaseFilter()
                        {
                            Name = "sp500", DisplayName = "SP500", GreaterThanValue = 10, Method = "returns", FieldName = "BLAH"
                        },
                        //new CustomPhaseFilter() { Name= "yr10",      DisplayName= "10YR",    GreaterThanValue= 0, Method= "delta", FieldName= "BAR", Unit= "bp" },                
                        //new CustomPhaseFilter() { Name= "em",        DisplayName= "EM",      GreaterThanValue= 0, Method= "returns", FieldName= "FOO" }
                }
        };
        var provider = DrawDownController.YadiYadahDataProvider;
        var data = provider.GetCustomPhases(provider.GetCachedData(), request);
        return data.AsQueryable();
    }
}

控制器动作参数:

public class CustomPhaseRequest
{
    public int Duration { get; set; }
    public List<CustomPhaseFilter> PhaseFilters { get; set; }
}

public class CustomPhaseFilter
{
    public string Name { get; set; }              // maps to str
    public string DisplayName { get; set; }       // maps to display
    public double? SmallerThanValue { get; set; } // maps to value
    public double? GreaterThanValue { get; set; } // maps to value
    public string Method { get; set; }            // maps to method
    public string FieldName { get; set; }         // maps to dataStr   
    public string Unit { get; set; }              // maps to unit    
}

模型构建器代码:

ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();

EntitySetConfiguration < Phase > phaseConfig = modelBuilder.EntitySet < Phase > ("Phase");
phaseConfig.EntityType.HasKey(p => p.Key);

var phaseType = modelBuilder.EntityType < Phase > ();
var customPhasesFunction = phaseType.Collection.Function("CustomPhases");

customPhasesFunction.ReturnsCollection < Phase > ().Parameter < CustomPhaseRequest > ("request");

IEdmModel model = modelBuilder.GetEdmModel();
config.MapODataServiceRoute("odata", "odata", model);

从javascript如何调用此odata函数并传入复杂的参数?

http://example.com/odata/Phase/Default.CustomPhases(@param)

尝试在典型的odata函数url中传递复杂类型时存在许多问题。 首先是它是基本URL的一部分,而不是params的一部分(在?之后),所以如果你采用json有效载荷,如:

{
    "Duration": 3, 
    "PhaseFilters": [
        {
            "Name": "sp500", 
            "DisplayName": "SP500", 
            "GreaterThanValue": 10, 
            "Method": "returns", 
            "FieldName": "BLAH"
        }, 
        {
            "Name": "yr10", 
            "DisplayName": "10YR", 
            "GreaterThanValue": 0, 
            "Method": "delta", 
            "FieldName": "BAR", 
            "Unit": "bp"
        }, 
        {
            "Name": "em", 
            "DisplayName": "EM", 
            "GreaterThanValue": 0, 
            "Method": "returns", 
            "FieldName": "FOO"
        }
    ]
}

将它字符串化并对其进行urlencoded,即使我告诉asp.net忽略某些字符,当我手动构建url时,它仍然没有参数绑定到实际的odata控制器操作。它给出了404。

其次是我不知道是否可以使用http GET应用程序/ json内容类型和数据参数,并在执行jquery ajax调用时将其放在url的非参数位置。

从语义上讲,这是一个odata函数(不是动作),因为它不会修改任何东西 - 只需使用自定义参数检索数据,因此它使用GET spec-wise(如果我错了请纠正我)...

这是怎么做到的?

1 个答案:

答案 0 :(得分:3)

函数和动作的参数只能是webapi 2.2中的原始类型或枚举类型。

如果需要复杂类型,可以将参数类型定义为字符串,然后将参数作为字符串文字传递。

然后在您的控制器中,您可以获取参数的字符串值并将其反序列化为CustomPhaseRequest对象。

public IQueryable<Phase> CustomPhases(string requestString)
{
    // Deserialize the requestString to requestObject
}

然而,网址的长度有限制。因此,如果参数字符串太长,您必须将其定义为操作并在主体中传递参数,尽管它不会修改任何内容。