{"id":13178,"date":"2022-05-05T08:04:00","date_gmt":"2022-05-05T15:04:00","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=13178"},"modified":"2025-06-13T20:56:45","modified_gmt":"2025-06-14T03:56:45","slug":"asp-net-core-crud-nosql-part-3","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/","title":{"rendered":"ASP.NET Core CRUD with NoSQL: Part 3"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">ASP.NET CRUD applications consist of create, read, update, and delete. In <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-with-nosql-part-1\/\"><span style=\"font-weight: 400;\">part 1<\/span><\/a><span style=\"font-weight: 400;\">, we set up a basic ASP.NET Core project. In <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-2\/\"><span style=\"font-weight: 400;\">part 2<\/span><\/a><span style=\"font-weight: 400;\">, we added the first <\/span><i><span style=\"font-weight: 400;\">read<\/span><\/i><span style=\"font-weight: 400;\"> endpoint, using a SQL++ query against wishlist data.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Couchbase\u2019s SQL++ is a powerful query language, containing all the best features of relational SQL, with a superset of features for querying JSON data.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, SQL++ isn\u2019t the only way to interact with data in Couchbase. In this post, we\u2019ll explore using the key-value API.<\/span><\/p>\n<h2><b>Key-value vs SQL?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">If you have a relational background, then you are likely accustomed to SQL being <\/span><i><span style=\"font-weight: 400;\">the only<\/span><\/i><span style=\"font-weight: 400;\"> way to interact with data (even if you\u2019re using a tool like Entity Framework Core, it\u2019s still ultimately using SQL). One of the great features of a NoSQL database (like Couchbase) is that while SQL is available, there are other access methods available too. (Hence the <\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/Backronym\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">backronym<\/span><\/a><span style=\"font-weight: 400;\"> &#8220;Not Only SQL&#8221;).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For Couchbase, the most efficient way to access data is via <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/kv-operations.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">key-value lookup<\/span><\/a><span style=\"font-weight: 400;\">. Every other index and query that Couchbase supports (<\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-intro\/queriesandresults.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">SQL++<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/fts\/fts-introduction.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Full-Text Search<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/introduction.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Analytics<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Eventing<\/span><\/a><span style=\"font-weight: 400;\">, and more) are ultimately built upon or rely on the lowly key-value lookup.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The key-value API will give you the best performance, where:<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A key is specified, or<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Your code is given a key, or<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">You can construct a key deterministically<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2><b>Examples: when to use key-value<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Here are some examples of when (and when NOT) to use the key-value API for reading:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><strong>Use case<\/strong><\/td>\n<td><strong>Key-value?<\/strong><\/td>\n<td><strong>Why or why not?<\/strong><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Lookup a user with key &#8220;<em>73892<\/em>&#8220;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Yes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Direct lookup<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Lookup just the email address of a user with key &#8220;<em>73892<\/em>&#8220;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Yes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Even if the user document is large, Couchbase has a key-based <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/reading-data.html#reading-a-sub-document\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">sub-document API<\/span><\/a><span style=\"font-weight: 400;\">, which allows you to retrieve a portion of the document.<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Lookup a group of users with keys &#8220;<em>73892<\/em>&#8220;, &#8220;<em>47212<\/em>&#8220;, and <em>&#8220;90491&#8221;<\/em><\/span><\/td>\n<td><span style=\"font-weight: 400;\">Yes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">This may require multiple key lookup operations, but this still may be faster than using a <em>SQL <\/em><\/span><em><span style=\"font-weight: 400;\">SELECT \u2026\u200b WHERE \u2026\u200b IN<\/span><\/em><span style=\"font-weight: 400;\"> query.<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Lookup the comments from a blog post<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Maybe<\/span><\/td>\n<td><span style=\"font-weight: 400;\">If comments for a blog post are in a single document, and the blog post key is known, a blog post comment key can be constructed. E.g. blog post key is <\/span><span style=\"font-weight: 400;\">I-like-balloons<\/span><span style=\"font-weight: 400;\">, to get comments, use the key <\/span><span style=\"font-weight: 400;\">I-like-balloons::comments<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Lookup all users from &#8220;<em>Ohio<\/em>&#8220;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">No<\/span><\/td>\n<td><span style=\"font-weight: 400;\">User\u2019s state is likely a &#8220;secondary&#8221; attribute, not a key (multiple users can be from Ohio). This is a good use case for SQL++<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Search for products with &#8220;<em>balloons<\/em>&#8221; in their description<\/span><\/td>\n<td><span style=\"font-weight: 400;\">No<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Descriptions are a secondary attribute, not a key (multiple products may have &#8220;balloons&#8221; in their description). This is a good use case for Full-Text Search (FTS)<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Note that Couchbase has a memory-first architecture. The built-in cache means that a key-value lookup will often be retrieving data directly from memory\u2014\u200bmicrosecond latency, no waiting on the disk.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">My rule of thumb is: use key-value API whenever possible, and then fall back to a more flexible option like SQL++ or Full-Text Search when necessary.<\/span><\/p>\n<h2><b>Create a Get CRUD endpoint<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Let\u2019s create an endpoint that uses the key-value API to retrieve a single item from the wishlist.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This endpoint will require the ID of the wishlist item to be given as a parameter:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:c# decode:true \">[HttpGet]\r\n[Route(\"api\/get\/{id}\")]\r\npublic async Task&lt;IActionResult&gt; Get(Guid id)\r\n{\r\n   var bucket = await _bucketProvider.GetBucketAsync(\"demo\");\r\n   var collection = await bucket.CollectionAsync(\"wishlist\");\r\n\r\n   var item = await collection.GetAsync(id.ToString());\r\n\r\n   return Ok(item.ContentAs&lt;WishlistItem&gt;());\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">In this example, we don\u2019t need a <\/span><span style=\"font-weight: 400;\">cluster<\/span><span style=\"font-weight: 400;\"> object (like we did with SQL++), but we do need a <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/scopes-and-collections-for-modern-multi-tenant-applications-couchbase-7-0\/\"><span style=\"font-weight: 400;\">collection<\/span><\/a><span style=\"font-weight: 400;\"> object. Note that since the wishlist collection is in the <em>_default<\/em>\u00a0scope, we can <\/span><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/concept-docs\/collections.html#using-collections-scopes\"><span style=\"font-weight: 400;\">skip right past getting the scope and go directly from bucket to collection<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">When the item is returned from <\/span><em><span style=\"font-weight: 400;\">GetAsync<\/span><\/em><span style=\"font-weight: 400;\">, it\u2019s in an <\/span><em><span style=\"font-weight: 400;\">IGetResult<\/span><\/em><span style=\"font-weight: 400;\"> object. Couchbase doesn\u2019t store C# objects, it stores JSON. So, to serialize to a <\/span><em><span style=\"font-weight: 400;\">WishlistItem<\/span><\/em><span style=\"font-weight: 400;\"> object, use <\/span><em><span style=\"font-weight: 400;\">item.ContentAs&lt;WishlistItem&gt;<\/span><\/em><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This API gives you flexibility: a document returned from Couchbase could be serialized to <\/span><em><span style=\"font-weight: 400;\">WishlistItem<\/span><\/em><span style=\"font-weight: 400;\"> here and perhaps <\/span><em><span style=\"font-weight: 400;\">AmazonWishlistItem<\/span><\/em><span style=\"font-weight: 400;\"> in another part of the application.<\/span><\/p>\n<h2><b>Key-value in action<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Execute the ASP.NET Core application and let\u2019s look at the updated OpenAPI\/Swagger page.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13179\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/05\/image1.png\" alt=\"ASP core dotnet tutorial with Couchbase\" width=\"811\" height=\"408\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/image1.png 811w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/image1-300x151.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/image1-768x386.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/image1-20x10.png 20w\" sizes=\"auto, (max-width: 811px) 100vw, 811px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">The endpoint <\/span><em><span style=\"font-weight: 400;\">\/api\/get\/{id}<\/span><\/em><span style=\"font-weight: 400;\"> under <em>Gifts<\/em>\u00a0should now be listed. Expand that endpoint by clicking on it. Unlike the <\/span><em><span style=\"font-weight: 400;\">\/api\/getall<\/span><\/em><span style=\"font-weight: 400;\"> endpoint, this one requires a parameter: the ID of the wishlist item that you want to get. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">If you don\u2019t remember one of the GUIDs, you can execute <\/span><em><span style=\"font-weight: 400;\">\/api\/getall<\/span><\/em><span style=\"font-weight: 400;\"> first and copy one of them, or use: &#8220;<em>31c9cc33-8dfe-440c-bd1b-bb038939d2e0<\/em>&#8221; (which was the ID I gave to the Joey Votto jersey). Click <strong>Try it out<\/strong>, paste that ID, and click <strong>Execute<\/strong>:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13180\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/05\/testing-aspnet-core-endpoint-couchbase.png\" alt=\"Test the ASPNET Core Couchbase Endpoint \" width=\"764\" height=\"449\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/testing-aspnet-core-endpoint-couchbase.png 764w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/testing-aspnet-core-endpoint-couchbase-300x176.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/testing-aspnet-core-endpoint-couchbase-20x12.png 20w\" sizes=\"auto, (max-width: 764px) 100vw, 764px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Notice that in the response, the ID returned is <\/span><span style=\"font-weight: 400;\">null<\/span><span style=\"font-weight: 400;\">. This is because, as I explained in <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-2\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">part 2<\/span><\/a><span style=\"font-weight: 400;\">, Couchbase stores the ID as metadata. In this situation, that\u2019s not a big deal. The ID was given as a parameter, so you could just assign that to the C# object being returned:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:c# decode:true \">var itemObj = item.ContentAs&lt;WishlistItem&gt;();\r\nitemObj.Id = Guid.Parse(id);\r\n\r\nreturn Ok(itemObj);<\/pre>\n<p><span style=\"font-weight: 400;\">Alternatively, if you don\u2019t want to return ID <\/span><span style=\"font-weight: 400;\">at all, you could create a separate C# view class that only has <\/span><em><span style=\"font-weight: 400;\">name<\/span><\/em><span style=\"font-weight: 400;\"><em>\u00a0<\/em>and use that with <\/span><em><span style=\"font-weight: 400;\">ContentAs<\/span><\/em><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h2><b>What about validation and error handling?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">How wise of you to ask! This endpoint is definitely not ready for production. What\u2019s missing?<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Error handling: what if there\u2019s an exception?<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Validation: what if the ID passed in is invalid?<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Authentication\/authorization: what if the consumer of this API isn\u2019t supposed to have read access?<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Logging: what if something doesn\u2019t go quite right, and we want to examine the outcome later?<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">These are all important concerns. For most of these, ASP.NET Core has built-in functionality and\/or popular 3rd party libraries available to help you. But make sure to check out Couchbase documentation on <\/span><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/error-handling.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Handling Errors with the .NET SDK<\/span><\/a><span style=\"font-weight: 400;\"> and <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/manage\/manage-security\/security-management-overview.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Security Management Overview<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h2><b>What\u2019s next?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">The ASP.NET Core project is connected to Couchbase Capella, and it is reading data via both SQL++ and the key-value API.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In the next blog post, we\u2019ll look at creating and updating (&#8220;C&#8221; and &#8220;U&#8221;) data.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In the meantime, you should:<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/cloud.couchbase.com\/sign-up\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Sign up for a Capella free-trial<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Check out the <\/span><a href=\"https:\/\/cloud.couchbase.com\/sign-up\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Couchbase Playground for .NET<\/span><\/a><span style=\"font-weight: 400;\"> examples that you can run right in the browser.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>ASP.NET CRUD applications consist of create, read, update, and delete. In part 1, we set up a basic ASP.NET Core project. In part 2, we added the first read endpoint, using a SQL++ query against wishlist data. Couchbase\u2019s SQL++ is [&hellip;]<\/p>\n","protected":false},"author":71,"featured_media":13181,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,10126,10127,1816,2201],"tags":[],"ppma_author":[8937],"class_list":["post-13178","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-asp-dotnet","category-c-sharp","category-couchbase-server","category-tools-sdks"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>ASP.NET Core CRUD with NoSQL: Part 3 - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ASP.NET Core CRUD with NoSQL: Part 3\" \/>\n<meta property=\"og:description\" content=\"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-05T15:04:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:56:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1706\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Matthew Groves\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mgroves\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew Groves\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\"},\"author\":{\"name\":\"Matthew Groves\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58\"},\"headline\":\"ASP.NET Core CRUD with NoSQL: Part 3\",\"datePublished\":\"2022-05-05T15:04:00+00:00\",\"dateModified\":\"2025-06-14T03:56:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\"},\"wordCount\":1022,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg\",\"articleSection\":[\".NET\",\"ASP.NET\",\"C#\",\"Couchbase Server\",\"Tools &amp; SDKs\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\",\"name\":\"ASP.NET Core CRUD with NoSQL: Part 3 - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg\",\"datePublished\":\"2022-05-05T15:04:00+00:00\",\"dateModified\":\"2025-06-14T03:56:45+00:00\",\"description\":\"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg\",\"width\":2560,\"height\":1706,\"caption\":\"ASP.NET Core CRUD app\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"ASP.NET Core CRUD with NoSQL: Part 3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58\",\"name\":\"Matthew Groves\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"caption\":\"Matthew Groves\"},\"description\":\"Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP.\",\"sameAs\":[\"https:\/\/crosscuttingconcerns.com\",\"https:\/\/x.com\/mgroves\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/matthew-groves\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"ASP.NET Core CRUD with NoSQL: Part 3 - The Couchbase Blog","description":"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/","og_locale":"en_US","og_type":"article","og_title":"ASP.NET Core CRUD with NoSQL: Part 3","og_description":"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.","og_url":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/","og_site_name":"The Couchbase Blog","article_published_time":"2022-05-05T15:04:00+00:00","article_modified_time":"2025-06-14T03:56:45+00:00","og_image":[{"width":2560,"height":1706,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg","type":"image\/jpeg"}],"author":"Matthew Groves","twitter_card":"summary_large_image","twitter_creator":"@mgroves","twitter_misc":{"Written by":"Matthew Groves","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/"},"author":{"name":"Matthew Groves","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58"},"headline":"ASP.NET Core CRUD with NoSQL: Part 3","datePublished":"2022-05-05T15:04:00+00:00","dateModified":"2025-06-14T03:56:45+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/"},"wordCount":1022,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg","articleSection":[".NET","ASP.NET","C#","Couchbase Server","Tools &amp; SDKs"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/","url":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/","name":"ASP.NET Core CRUD with NoSQL: Part 3 - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg","datePublished":"2022-05-05T15:04:00+00:00","dateModified":"2025-06-14T03:56:45+00:00","description":"Continue building an ASP.NET Core app for Couchbase - in this post, we add key-value NoSQL document retrieval capabilities and test endpoints.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/05\/aspdotnet-core-app-development-couchbase-scaled.jpg","width":2560,"height":1706,"caption":"ASP.NET Core CRUD app"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"ASP.NET Core CRUD with NoSQL: Part 3"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58","name":"Matthew Groves","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54","url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","caption":"Matthew Groves"},"description":"Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP.","sameAs":["https:\/\/crosscuttingconcerns.com","https:\/\/x.com\/mgroves"],"url":"https:\/\/www.couchbase.com\/blog\/author\/matthew-groves\/"}]}},"authors":[{"term_id":8937,"user_id":71,"is_guest":0,"slug":"matthew-groves","display_name":"Matthew Groves","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","author_category":"","last_name":"Groves","first_name":"Matthew","job_title":"","user_url":"https:\/\/crosscuttingconcerns.com","description":"Matthew D. Groves is a guy who loves to code.  It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything.  He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s.  He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community.  He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/71"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=13178"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13178\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13181"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=13178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=13178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=13178"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=13178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}