{"id":3664,"date":"2019-04-03T17:26:01","date_gmt":"2019-04-03T17:26:01","guid":{"rendered":"https:\/\/wspelt.com\/?p=3664"},"modified":"2024-07-16T16:00:42","modified_gmt":"2024-07-16T16:00:42","slug":"generic-entity-framework-crud-controller-for-web-api","status":"publish","type":"post","link":"https:\/\/wspelt.com\/?p=3664","title":{"rendered":"Generic Entity Framework CRUD controller for Web API"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">During a job I came across the following wish: <br><em>Developing a generic web service that provides as many standard database actions as possible.<\/em><br>I will elaborate on the implementation of this below.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What do you need<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The starting situation is a created empty MVC Web API 2 project or a WebForms project with the \u201cMicrosoft.AspNet.WebApi\u201d NuGet package added.<br>Also add the EntityFramework NuGet package. This can be easily installed via the NuGet Package Manager console with the following command: <br><em>Install-Package EntityFramework -Version 6.2.0<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set up Web API and Data Model<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Add an empty Web API 2 Controller to the project and name it &#8220;BaseApiController&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"339\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1-1024x339.png\" alt=\"\" class=\"wp-image-3666\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1-1024x339.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1-300x99.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1-768x254.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1-800x265.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/1-1.png 1332w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding an empty Web API 2 Controller<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To provide database actions, we first add a new ADO.NET Entity Data Model.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"257\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1-1024x257.png\" alt=\"\" class=\"wp-image-3668\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1-1024x257.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1-300x75.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1-768x193.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1-800x201.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/2-1.png 1158w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding a new ADO.NET Entity Data Model<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Various options are possible in the wizard depending on your preference and project method.<br>I chose the \u201c<strong>Database First<\/strong>\u201d method, because in this way the data model can be developed from SQL Server Management Studio.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"817\" height=\"412\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/3-1.png\" alt=\"\" class=\"wp-image-3669\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/3-1.png 817w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/3-1-300x151.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/3-1-768x387.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/3-1-800x403.png 800w\" sizes=\"auto, (max-width: 817px) 100vw, 817px\" \/><figcaption class=\"wp-element-caption\"><em>Choice of model type: Database first or Code first<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the next screen, add the database connection, indicate the database tables you want to work with in your project and let the scaffolding do its work. The great thing about Entity Framework is that foreign key relationships are also automatically detected and included in the generated code. Obviously something that can also be expected from an ORM tool. This makes it possible to include \u201cone to many\u201d and \u201cmany to many\u201d relationships in the object model with &#8220;navigation properties&#8221; and maintain integrity in the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the created .EDMX file, the object model can then be updated at any time with database adjustments by clicking on \u201cUpdate model from database\u201d in the context menu (right mouse button).<\/p>\n\n\n\n<blockquote class=\"wp-block-quote has-text-align-center is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u201cNow that we have the design for the Web API and the data model ready, it is of course fun to actually do something with it.\u201d<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Attribute routing and inheritance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that the data model and the BaseApiController have been created in Visual Studio, we come to the generic routing piece. After all, the Web API methods will have to be accessed via endpoints.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I find it strange, but by default it is not possible in MVC to inherit routes. Fortunately, it is possible to achieve this by using the class below. With this we are going to introduce a RouteProvider that is suitable for inheritance.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"167\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1-1024x167.png\" alt=\"\" class=\"wp-image-3673\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1-1024x167.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1-300x49.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1-768x125.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1-800x130.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/4-1.png 1399w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding the Inheritance Direct RouteProvider class<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Note: Pay particular attention to the \u201ctrue\u201d bit in the overload, which makes the difference.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We now add this InheritanceDirectRouteProvider to the initialization of the application.<br>This can be done as follows in the Application_Start method in a WebForms project:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"110\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1-1024x110.png\" alt=\"\" class=\"wp-image-3677\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1-1024x110.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1-300x32.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1-768x82.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1-800x86.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/5-1.png 1398w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Set up routing with Inheritance Direct RouteProvider in a Web Forms project<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Or like this, if you are working in an MVC project:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"414\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1-1024x414.png\" alt=\"\" class=\"wp-image-3678\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1-1024x414.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1-300x121.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1-768x311.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1-800x324.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/6-1.png 1397w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Set up routing with InheritanceDirectRouteProvider in an MVC project<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The standard routing is done based on convention.<br>As you can see in the code above, I chose the BaseApiController to automatically generate the routes in MVC based on the RoutePrefix attribute with the call to \u201cMapHttpAttributeRoutes\u201d.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Initialization and the \u201cR\u201d in CRUD<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To make the BaseApiController generic, the type T is given in the signature class. This is then requested in the constructor and placed in a protected variable. The Entity Framework context of the data model is also instantiated in the constructor.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"867\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1-1024x867.png\" alt=\"\" class=\"wp-image-3680\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1-1024x867.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1-300x254.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1-768x651.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1-800x678.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/7-1.png 1112w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Initialization of the BaseApiController class and the GetAll method<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Note that in the GetAll method an entityDbSet variable is created with the database context of the concrete type passed. Since this type is not known in advance, it is stored as type var.<br>With a StringBuilder the DbSet can then be serialized directly to a Json string and the full collection of objects can be returned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The generic GetEntityById method looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"557\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1-1024x557.png\" alt=\"\" class=\"wp-image-3681\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1-1024x557.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1-300x163.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1-768x417.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1-800x435.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/8-1.png 1150w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding the generic GetEntityById method<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It can be seen that the action is once again taking place on the DbSet, this time with the Find method.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The \u201cD\u201d in CRUD: DeleteEntity<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The generic DeleteEntity method looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"615\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1-1024x615.png\" alt=\"\" class=\"wp-image-3683\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1-1024x615.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1-300x180.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1-768x461.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1-800x481.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/9-1.png 1107w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding the generic DeleteEntity method<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It can be seen that again the action takes place on the DbSet, but this time with the FindAsync method.<br>Entity Framework supports asynchronous operations, which can then be used relatively easily with the async await pattern.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The \u201cCU\u201d in CRUD: Post Batch<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Separate Create and Update methods can of course be created for creating and updating entities. However, in this implementation it has been decided to combine this in one \u201cpostbatch\u201d method. This is elaborated below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"862\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1-1024x862.png\" alt=\"\" class=\"wp-image-3684\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1-1024x862.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1-300x252.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1-768x646.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1-800x673.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/10-1.png 1092w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>The Create section in the postbatch method<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The method signature shows that it has been implemented entirely asynchronously and that the entities parameter is of the type object array. The latter makes it possible to \u201cpost\u201d a JSON string with multiple objects using client-side code (JavaScript). The MVC model binder can cast this automatically, provided the contentType of the post is \u201capplication\/json\u201d.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Furthermore, it can be seen that the \u201cgeneric element\u201d is achieved by creating a DbSet based on the concrete (inheriting) type and serializing it to an entityObject of type var.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the data model, the \u201cId\u201d field is the primary key in most tables, which can be overridden with the property \u201cIdPropertyName\u201d.<br>As you can see, line 104 checks whether the Id contains the value -1.<br>Based on this, the Add method on the DbSet is called or the state is set to \u201cModified\u201d, as shown in the Update section below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"971\" height=\"939\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/11.png\" alt=\"\" class=\"wp-image-3687\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/11.png 971w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/11-300x290.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/11-768x743.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/11-800x774.png 800w\" sizes=\"auto, (max-width: 971px) 100vw, 971px\" \/><figcaption class=\"wp-element-caption\"><em>The Update section in the postbatch method<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The call to this postbatch method can be done with client-side code (JavaScript) as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"787\" height=\"498\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/12.png\" alt=\"\" class=\"wp-image-3688\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/12.png 787w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/12-300x190.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/12-768x486.png 768w\" sizes=\"auto, (max-width: 787px) 100vw, 787px\" \/><figcaption class=\"wp-element-caption\"><em>Calling the postbatch method with clientside code (JavaScript)<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you now want to create a concrete class in which the CRUD actions are immediately available, you can do this as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"791\" height=\"226\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/13.png\" alt=\"\" class=\"wp-image-3689\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/13.png 791w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/13-300x86.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/13-768x219.png 768w\" sizes=\"auto, (max-width: 791px) 100vw, 791px\" \/><figcaption class=\"wp-element-caption\"><em>Implementation of a concrete class with immediately available CRUD actions<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, the auxiliaries below are also needed to get the above code working.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"372\" src=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14-1024x372.png\" alt=\"\" class=\"wp-image-3690\" srcset=\"https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14-1024x372.png 1024w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14-300x109.png 300w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14-768x279.png 768w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14-800x290.png 800w, https:\/\/wspelt.com\/wp-content\/uploads\/2024\/07\/14.png 1028w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Adding helper methods for CRUD actions<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Finally<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the way described above it is possible to create a generic web service that provides standard CRUD database actions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you also wish to use this web service in a secure manner in a SharePoint provider hosted app on pages with client-side code (JavaScript), then this blog may also be interesting for you: <a href=\"https:\/\/wspelt.com\/?p=3643\" data-type=\"post\" data-id=\"3643\">Secure Web API in an SP provider hosted app<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>During a job I came across the following wish: Developing a generic web service that provides as many standard database actions as possible.<br \/>\nI will elaborate on the implementation in this blog post.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[38,39,37],"tags":[],"class_list":["post-3664","post","type-post","status-publish","format-standard","category-net","category-entity-framework","category-javascript","entry","has-post-thumbnail"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/posts\/3664","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wspelt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3664"}],"version-history":[{"count":13,"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/posts\/3664\/revisions"}],"predecessor-version":[{"id":3691,"href":"https:\/\/wspelt.com\/index.php?rest_route=\/wp\/v2\/posts\/3664\/revisions\/3691"}],"wp:attachment":[{"href":"https:\/\/wspelt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3664"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wspelt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3664"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wspelt.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3664"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}