{"id":253,"date":"2014-07-04T08:53:00","date_gmt":"2014-07-04T08:53:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2014\/07\/04\/tutorial-sample-using-odatauriparser-for-odata-v4\/"},"modified":"2020-01-07T07:24:02","modified_gmt":"2020-01-07T14:24:02","slug":"tutorial-sample-using-odatauriparser-for-odata-v4","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/tutorial-sample-using-odatauriparser-for-odata-v4\/","title":{"rendered":"[Tutorial &amp; Sample] Using ODataUriParser for OData V4"},"content":{"rendered":"<h2><span style=\"color: #2e74b5;\"><span style=\"font-family: Calibri Light;\">Background<\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">This post is intended to guide you through the UriParser for OData V4, which is released within ODataLib V6.0 and later.<\/span><\/span><\/p>\n<p><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">You may have already read the following posts about OData UriParser in ODataLib V5.x:<\/span><\/span><\/p>\n<ul>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2012\/12\/06\/parsing-filter-and-orderby-using-the-odatauriparser.aspx\"><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">Parsing $filter and $orderby using the ODataUriParser<\/span><\/a><\/li>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2013\/05\/10\/parsing-odata-paths-select-and-expand-using-the-odatauriparser.aspx\"><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">Parsing OData Paths, $select and $expand using the ODataUriParser<\/span><\/a><\/li>\n<\/ul>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">Some parts of the articles <\/span><span style=\"font-family: Calibri; font-size: x-small;\">still apply to<\/span><span style=\"font-family: Calibri;\">\u00a0<\/span><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">V4 UriParser, such as introduction for ODataPath and QueryNode hierarchy. In this post, we will deal with API changes and features newly introduced.<\/span><\/span><\/p>\n<h2><span style=\"color: #2e74b5;\"><span style=\"font-family: Calibri Light;\">UriParser Overview<\/span><\/span><\/h2>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">The main reference document for UriParser is the <\/span><a href=\"http:\/\/docs.oasis-open.org\/odata\/odata\/v4.0\/odata-v4.0-part2-url-conventions.html\"><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">URL Conventions<\/span><\/a><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\"> specification. The ODataUriParser class is its main implementation in ODataLib.<\/span><\/span><\/p>\n<p><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">The ODataUriParser class has two main functionalities:<\/span><\/span><\/p>\n<ul>\n<li><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">Parse resource path<\/span><\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">Parse query options<\/span><\/span><\/li>\n<\/ul>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">We\u2019ve also introduced the new ODataQueryOptionParser class in ODataLib 6.2+, in case you do not have the full resource path and only want to parse the query options only. The ODataQueryOptionParser shares the same API signature for parsing query options, you can find more information below.<\/span><\/p>\n<h2><span style=\"color: #2e74b5;\"><span style=\"font-family: Calibri Light;\">What\u2019s new?<\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">If you are familiar with ODataLib V5.x UriParser, you may find the following new things in V6.x:<\/span><\/span><\/p>\n<ol>\n<li><span style=\"font-family: Calibri; font-size: x-small;\">All static methods are removed, the UriParser only have instance methods;<\/span><\/li>\n<li><span style=\"font-family: Calibri; font-size: x-small;\">Support alias parsing (see this <\/span><a href=\"http:\/\/blogs.msdn.com\/b\/odatateam\/archive\/2014\/03\/13\/using-parameter-alias-to-simplify-the-odata-url.aspx\"><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">article<\/span><\/a><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">);<\/span><\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">Support $count, $skip, $top, and $search (see below);<\/span><\/span><\/li>\n<\/ol>\n<h2><span style=\"color: #2e74b5;\"><span style=\"font-family: Calibri Light;\">Using ODataUriParser<\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">The use of ODataUriParser class is easy and straight forward, as we mentioned, we do not support static methods now, we will begin from creating an ODataUriParser instance.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">ODataUriParser has only one constructor:<\/span><\/span><\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"553\"><strong>public<\/strong><strong> ODataUriParser(<\/strong><strong>IEdmModel<\/strong><strong> model, <\/strong><strong>Uri<\/strong><strong> serviceRoot, <\/strong><strong>Uri<\/strong><strong> fullUri);<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">Parameters:<\/span><\/span><\/p>\n<ul>\n<li><span style=\"font-family: Calibri; font-size: x-small;\">model is the Edm model the UriParser will refer to;<\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">serviceRoot is the base Uri for the service, which could be a constant for certain service. Note that serviceRoot must be an absolute Uri;<\/span><\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">fullUri is the full request Uri including query options. When it is an absolute Uri, it must be based on the serviceRoot, or it can be a relative Uri.<\/span><\/span><\/li>\n<\/ul>\n<p>In the following demo we will use the model from <a href=\"http:\/\/services.odata.org\/V4\/OData\/OData.svc\/\"><span style=\"color: #0563c1;\">OData V4 demo service<\/span><\/a> , and create an ODataUriParser instance.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/ODataTeam\/422856c7406f9b555f8c.js\"><\/script><\/p>\n<h2><span style=\"font-size: large;\"><span style=\"color: #404040;\"><span style=\"font-family: Calibri Light;\">Parsing Resource Path<\/span><\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">You can use the following API to parse resource path:<\/span><\/span><\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/ODataTeam\/daed63f7f56638dc28f9.js\"><\/script><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">You don\u2019t need to pass in resource path as parameter here, because the constructor has taken the full Uri.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">The ODataPath holds the enumeration of path segments for resource path. All path segments are represented by classes derived from ODataPathSegment. <\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">In our demo, the resource Path in the full Uri is Products(1), then the result ODataPath would contain two segments: one EntitySetSegment for EntitySet named Products, and the other KeySegment for key with integer value \u201c1\u201d .<\/span><\/span><\/p>\n<h2><span style=\"font-size: large;\"><span style=\"color: #404040;\"><span style=\"font-family: Calibri Light;\">Parsing Query Options<\/span><\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">ODataUriParser supports parsing following query options: $select, $expand, $filter, $orderby, $search, $top, $skip, and $count. <\/span><\/span><\/p>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">For the first four, the parsing result is an instance of class XXXClause, which represents the query option as an <\/span><a href=\"http:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\"><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">Abstract Syntax Tree<\/span><\/a><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\"> (with semantic information bound). Note that $select and $expand query options are merged together in one SelectExpandClause class. The later three all have primitive type value, and the parsing result is the corresponding primitive type wrapped by Nullable class. <\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">For all query option parsing results, the Null value indicates the corresponding query option is not specified in the request URL.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">Here is a demo for parsing the Uri with all kinds of query options (please notice that value of skip would be null as it is not specified in the request Uri) :<\/span><\/span><\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/ODataTeam\/492c2cc87a01ee5a617b.js\"><\/script><\/p>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">\u00a0<\/span><\/p>\n<p><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">The data structure for SelectExpandClause, FilterClause, OrdeyByClause have already been presented in the two previous articles mentioned at the top of this post. Here I\u2019d like to talk about the newly introduced SearchClause.<\/span><\/span><\/p>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">SearchClause contains tree representation of the $search query. The detailed rule of $search query option can be found <\/span><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">here<\/span><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">. In general, the search query string can contain search terms combined with logic keywords: AND, OR and NOT.<\/span><\/span><\/p>\n<p><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">All search terms are represented by SearchTermNode, which is derived from SingleValueNode. SearchTermNode has one property named Text, which contains the original word or phrases.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">SearchClause\u2019s Expression property holds the tree structure for $search. If the $search contains single word, the Expression would be set to that SearchTermNode. But when $search is a combination of various term and logic keywords, the Expression would also contains nested <\/span><strong>BinaryOperatorNode<\/strong><span style=\"font-family: Calibri;\"> and <\/span><strong>UnaryOperatorNode<\/strong><span style=\"font-family: Calibri;\">.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">For example, if the query option $search has the value \u201ca AND b\u201d, the result SearchTermNode would have the following structure:<\/span><\/span><\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/ODataTeam\/1f53892fc1c76aed9d7b.js\"><\/script><\/p>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">\u00a0<\/span><\/p>\n<h2><span style=\"color: #2e74b5;\"><span style=\"font-family: Calibri Light;\">Using ODataQueryOption Parser<\/span><\/span><\/h2>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">There may be some cases that you already know the query context information but does not have the full request Uri. The ODataUriParser does not seems to be available as it will always require the full Uri, then the user would have to fake one.<\/span><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">In ODataLib 6.2 we shipped a new Uri parser that targets at query options only, it requires the model and type information be provided through its constructor, then it could be used for query options parsing as same as ODataUriParser.<\/span><\/span><\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/ODataTeam\/b0ceb69a0c7cb2e1c2dc.js\"><\/script><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">The constructor looks like this:<\/span><\/span><\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"553\">\n<p class=\"SourceCode\"><span style=\"font-family: Consolas;\">public ODataQueryOptionParser(<span style=\"color: #2b91af;\">IEdmModel<\/span> model, <span style=\"color: #2b91af;\">IEdmType<\/span> targetEdmType, <span style=\"color: #2b91af;\">IEdmNavigationSource<\/span> targetNavigationSource, <span style=\"color: #2b91af;\">IDictionary<\/span>&lt;string, string&gt; queryOptions);<\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">Parameters (here the target object indicates what resource path was addressing, see <\/span><span style=\"color: #0563c1; font-family: Calibri; font-size: x-small;\">spec<\/span><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">):<\/span><\/span><\/p>\n<ul>\n<li><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">model is the model the UriParser will refer to;<\/span><\/span><\/li>\n<li><span style=\"font-family: Calibri;\"><span style=\"font-size: x-small;\">targetEdmType is the type for the which query options apply to, it is the type of target object;<\/span><\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">targetNavigationSource is the EntitySet or Singleton where the target comes from, it is usually the NavigationSource of the target object;<\/span><\/span><\/li>\n<li><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">queryOptions is the dictionary containing the\u00a0key-value pairs for query options.<\/span><\/span><\/li>\n<\/ul>\n<p><span style=\"font-family: Calibri; font-size: x-small;\">\u00a0<\/span><\/p>\n<p><span style=\"font-size: x-small;\"><span style=\"font-family: Calibri;\">Here is the demo for its usage, it is almost the same as the ODataUriParser:<\/span><\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Background This post is intended to guide you through the UriParser for OData V4, which is released within ODataLib V6.0 and later. You may have already read the following posts about OData UriParser in ODataLib V5.x: Parsing $filter and $orderby using the ODataUriParser Parsing OData Paths, $select and $expand using the ODataUriParser Some parts of [&hellip;]<\/p>\n","protected":false},"author":516,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-253","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata"],"acf":[],"blog_post_summary":"<p>Background This post is intended to guide you through the UriParser for OData V4, which is released within ODataLib V6.0 and later. You may have already read the following posts about OData UriParser in ODataLib V5.x: Parsing $filter and $orderby using the ODataUriParser Parsing OData Paths, $select and $expand using the ODataUriParser Some parts of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/253","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/516"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=253"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/253\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}