Tuesday, December 25, 2018

Extract Filter part in Odata QueryOptions Web API

If you are creating Web API using Odata controller  and want to extract filters query from Odata request. Refer below sample query(bold part is odata filter)

You can download the code from (https://github.com/mesan21ster/ExtractOdataFilterOptions)
You can also follow my YouTube channel (https://www.youtube.com/playlist?list=PLbAvaAiacB_FwIYjEU8hDXnn6r56XeHrU)

Follow below simple steps to get that.

Sample Odata URL
https://localhost:44335/odata/testData/testDataType?$format=json&$filter=(FirstName+eq+'Santosh'+AND+LastName+eq+'Kumar'+AND+Age+eq+ 30+AND+BirthYear+eq+2019+AND+BirthCity+eq+'Delhi')&$count=true&$orderby=Age+desc

Namespaces used in code
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Linq;
using Microsoft.AspNet.OData;
using Microsoft.AspNet.OData.Query;

using Microsoft.AspNet.OData.Routing;

Sample OdataController
namespace test.Controllers

{
[ODataRoutePrefix("testData")]

public class TestDataController : ODataController
{
[ODataRoute("testDataType")]
[HttpGet]
public IQueryable testoData(ODataQueryOptions oDataQueryOptions)
        {
//here you have to follow below steps to extract odata filters from odata query options parameter
}
}
}
Step 1

Declare filter expression

 string oDataFilterExpression = @"(?" +
                            "\n" + @"     (?.+?)\s+" +
                            "\n" + @"     (?eq|ne|gt|ge|lt|le|add|sub|mul|div|mod)\s+" +
                            "\n" + @"     '?(?.+?)'?" +
                            "\n" + @")" +
                            "\n" + @"(?:" +
                            "\n" + @"    \s*$" +
                            "\n" + @"   |\s+(?:or|and|not)\s+" +
                            "\n" + @")" +
                            "\n";  

Step 2
Declare regex and target filter string ( you can get your target filter string from "oDataQueryOptions.Filter.RawValue"
Regex oDataFilterRegex = new Regex(oDataFilterExpression, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);


string strTargetString = @"FirstName eq 'Santosh' AND LastName eq 'Kumar' AND Age eq  30 AND BirthYear eq 2019 AND BirthCity eq 'Delhi'".TrimEnd(')').TrimStart('(');

Step 3
Create a replace string in json format and make json array
string strReplace = @"{ 'Resource' : '${Resource}'," + @"   'Operator' : '${Operator}'," + @"   'Value'    : '${Value}'},";
 var val = oDataFilterRegex.Replace(strTargetString, strReplace);

 var filterJson = "[" + val.TrimEnd(',') + "]"; //Make json array

Step 4
Create a class to Deserialize json string to object
    public class FilterValue
    {
        public string Resource { get; set; }
        public string Operator { get; set; }
        public string Value { get; set; }

    }

Step 5 get result back
Deserialize json string to object and find your expected value

var oDataFilterObject = JsonConvert.DeserializeObject<List<FilterValue>>(filterJson);

var firstName= oDataFilterObject.Find(x => x.Resource == "FirstName").Value;