0

Hoping someone can hepl with an issue I've been having. I've created a Web API that fetches records from the a database. I have the following functions in place which work ok:

localhost:8080/api/Budgets -- Returns all Budgets

localhost:8080/api/Budgets(799) -- Returns all for contract 799

What I'm looking for is to be able to pass in two parameters to allow me to do calulations on the records retrieved so something like:

localhost:8080/api/Budgets(799)/215 -- Where 799 is the contract Number and 215 is a material number.

This will allow me to return a dataset of only materials for that budget that I can then do calculations on. There is only one SQL table for this which contains both the contract number and material number as well as a load of other figures.

Here's what I have so far but it doesnt seem to be working:

    public IHttpActionResult Get()
    {
        return Ok(context.Budgets);
    }

    public IHttpActionResult Get([FromODataUri] int key)
    {
        var budgets = context.Budgets.FirstOrDefault(p => p.ProjectNo == key);
        if (budgets == null)
        {
            return NotFound();
        }
        return Ok(budgets);
    }

[ODataRoute("GetMaterialUsage(ProjectId={ProjectId},ResourceCode={ResourceCode})")]
        public IHttpActionResult GetMaterialUsage([FromODataUri] int ProjectId, [FromODataUri] string ResourceCode)
        {
            var budgets = context.Budgets.FirstOrDefault(p => p.ProjectNo == ProjectId && p.ResourceCode == ResourceCode);
            if (budgets == null)
            {
                return NotFound();
            }
            return Ok(budgets);
        }

WebApiConfig:

            ODataModelBuilder builder = new ODataConventionModelBuilder();

        // Web API configuration and services
        builder.EntitySet<BudgetTypes>("BudgetTypes");
        builder.EntitySet<Budgets>("Budgets");
        var function = builder.Function("GetMaterialUsage");
        function.Parameter<int>("ProjectId");
        function.Parameter<string>("ResourceCode");
        function.ReturnsCollectionFromEntitySet<Budgets>("Budgets");


        // Web API routes
        config.MapHttpAttributeRoutes();

        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: "api",
            model: builder.GetEdmModel()
        );

Can anyone shine some light on how this can be done? I just want to pass 2 parameters to a function from the url.

At the moment the following links return 404: localhost:8080/api/Budgets(752,230) localhost:8080/api/Budgets(ProjectNo=752,ResourceCode=230)

2 Answers 2

1

you have specify the ODataRoute:

[ODataRoute("GetMaterialUsage(ProjectId={ProjectId},ResourceCode={ResourceCode})")]

And second parameter is string, so you should call like

localhost:8080/api/GetMaterialUsage(ProjectNo=752,ResourceCode='230')

If you need something like your not-working url, you need bound this function to your entity Budget, you will know how to do it refer to this page: http://odata.github.io/WebApi/#04-06-function-parameter-support

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the help. Assing the ODataRoute like your comment sorted it :)
0

I'm not 100% sure on this answer, because I've used OData a little differently, but I think the principle is still the same; I believe the key is to add a 2nd nullable parameter to your 2nd Get function...

//try: localhost:8080/api/Budgets(799,251)
//use this in-place of your second get function
//note the nullable (optional) 2nd parameter
public IHttpActionResult Get([FromODataUri] int key, [FromODataUri] int? key2 = null)
{
    if (key2 == null)
    {
        //carry-on as usual using the 1-param code
        var budgets = context.Budgets.FirstOrDefault(p => p.ProjectNo == key);
        if (budgets == null)
        {
            return NotFound();
        }
        return Ok(budgets);
    }
    else
    {
        //if a second param is also supplied...

    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.