<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Irina Scurtu</title>
    <description>The latest articles on DEV Community by Irina Scurtu (@irina_scurtu).</description>
    <link>https://dev.to/irina_scurtu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F140520%2Ff26e8061-d6dd-457b-8530-e7ae5de8194c.jpg</url>
      <title>DEV Community: Irina Scurtu</title>
      <link>https://dev.to/irina_scurtu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/irina_scurtu"/>
    <language>en</language>
    <item>
      <title>Enabling gRPC server reflection</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Tue, 13 Dec 2022 14:39:11 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/enabling-grpc-server-reflection-278c</link>
      <guid>https://dev.to/irina_scurtu/enabling-grpc-server-reflection-278c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2FArticole-800-%25C3%2597-450-px.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2FArticole-800-%25C3%2597-450-px.png" alt="enable grpc server reflection and use it with postman" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enabling gRPC server reflection will allow you to easily call your gRPC services from &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; without actually loading the protofile .&lt;/p&gt;

&lt;p&gt;PostMan will help you test your gRPC services, by giving you the same look and feel as a you would have with a traditional HTTP API.&lt;/p&gt;

&lt;p&gt;gRPC uses binary serialization, which means that is not human readable as JSON is. Is still possible to use grpcurl or similar tools, but you will not be able to decipher binary. Having the right tools will help you understand gRPC faster, because it has a slightly different vocabulary.&lt;/p&gt;

&lt;p&gt;When you open PostMan and click the New button , you can choose to issue gRPC requests. Thankfully, this is not in beta anymore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-1024x650.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-1024x650.png" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;PostMan New menu options&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To issue a gRPC request, you will need to specify the URL of the server (as you would do with a regular RESTful API), and then give PostMan access to the proto file that is implemented on the server. In this case, you need to help the tool a bit, so you can gain access to available functionality.&lt;/p&gt;

&lt;p&gt;To do that you can simply import the proto file or let PostMan discover what is available.&lt;/p&gt;

&lt;p&gt;In this case we will use the second option, because we would want our service operations to be somehow discoverable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-2-1024x465.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-2-1024x465.png" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Different ways of ‘accessing’ the proto file contract&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, if we try to click the highlighted option, we will get a big red error. This is as if our server throws an Unimplemented exception from a method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-4.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In reality, if we look at the logs, it actually does throw that kind of exception. &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdiiyfecfuhav9w432a2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdiiyfecfuhav9w432a2.png" alt="🙂" width="72" height="72"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;info: Grpc.AspNetCore.Server.Internal.ServerCallHandlerFactory[1]
      Service 'grpc.reflection.v1alpha.ServerReflection' is unimplemented.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enabling gRPC server reflection requires a few code tweaks because we actually need to an implementation that allows reflection over our grPC services.&lt;/p&gt;

&lt;p&gt;First, install &lt;code&gt;Grpc.AspNetCore.Server.Reflection&lt;/code&gt; NuGet package. This will contain the ServerReflection implementation that will we need, that allows external services and tools to discover existing methods&lt;/p&gt;

&lt;p&gt;Next, we need to add the middleware and then map the incoming gRPC requests to the Reflection Service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddGrpcReflection();

IWebHostEnvironment env = app.Environment;
if (env.IsDevelopment())
{
   app.MapGrpcReflectionService();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you did this, PostMan will successfully discover the available gRPC methods, and you will be able to call invoke these from the UI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-5-1024x295.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2022%2F12%2Fimage-5-1024x295.png" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;gRPC methods&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s it! A package and a few lines of code and you will enable gRPC server reflection.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/enabling-grpc-server-reflection/" rel="noopener noreferrer"&gt;Enabling gRPC server reflection&lt;/a&gt; appeared first on &lt;a href="https://irina.codes" rel="noopener noreferrer"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aspcore</category>
      <category>grpc</category>
      <category>uncategorized</category>
      <category>web</category>
    </item>
    <item>
      <title>Using custom media types in .NET</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Fri, 01 Apr 2022 09:31:32 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/using-custom-media-types-in-net-2cdi</link>
      <guid>https://dev.to/irina_scurtu/using-custom-media-types-in-net-2cdi</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5jacFQgL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2022/04/Articole-800-%25C3%2597-450-px.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5jacFQgL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2022/04/Articole-800-%25C3%2597-450-px.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to use and create custom mime types in .NET? How to respond to different mime-types in your Web API? Use the same HTTP Verb but hit different actions based on the Content-Type header value? Have 2 methods that have the same number of parameters and respond to the same HTTP Verb?&lt;/p&gt;

&lt;p&gt;These are questions that some of the developers seek answers to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accept &amp;amp; Content-Type
&lt;/h3&gt;

&lt;p&gt;There are 2 very important headers that are often overlooked, &lt;em&gt;Accept&lt;/em&gt; and &lt;em&gt;Content-Type&lt;/em&gt;, and play a major role in a process called &lt;em&gt;Content-Negotiation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Accept&lt;/em&gt; header&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
With this header, the API consumer tells the server what is the mime type it expects as the format for the response.&lt;br&gt;&lt;br&gt;
eg. Accept: application/json or Accept: application/xml.&lt;br&gt;&lt;br&gt;
If the server can’t build a response with the requested format, it will return a 406 – Not Acceptable status code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Type&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Describes the format of the body of the request that is sent to the server or to the client. This tells the server: “Hey, the body you will receive has this format, can you interpret it?”&lt;br&gt;&lt;br&gt;
If the server can’t read the content of the body, it will return a &lt;em&gt;415 Unsupported Media Type&lt;/em&gt; status code_._&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_Content-Negotiation_ is the process that happens with every request, where basically the two parties involved (i.e the Server and the Consumer/Client) do exactly that. : negotiate on the content. Depending on the format send as value for these 2 header properties, the result can differ.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we talk about APIs or&lt;a href="https://irina.codes/how-to-build-rest-ful-apis/"&gt;REST-ful APIs&lt;/a&gt; we implicitly talk about different representations of resources.&lt;/p&gt;

&lt;p&gt;Introducing the problem&lt;/p&gt;

&lt;p&gt;Let’s say we have an API that deals with speakers. For these, we store all kinds of info, but not all are needed every time. Maybe you need to return a full object in one scenario, and just a few properties in another one, like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   public class SpeakerModel
    {    
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Bio { get; set; }
        public string JobTitle { get; set; }
        public string Website { get; set; }
        public string Email { get; set; }
        public string TwitterHandle { get; set; }
        public string CompanyName { get; set; }
        public string Address { get; set; }
        public string Phone { get; set; }
        public string PassportDetails { get; set; }
    }

public class TrimmedSpeakerModel
 {    
        public int Id { get; set; }      
        public string FirstName { get; set; }
        public string LastName { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To achieve this, people end up creating new endpoints because the platform forces us to do so, in a way. We have the controller and in the controller we implement implement 2 actions, with different name, and different routes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/api/speakers&lt;/code&gt; and &lt;code&gt;/api/speakers/trimmed&lt;/code&gt; are basically two representations of the same resource. It shouldn’t matter what scenario you are in, the endpoint should still be something similar to &lt;code&gt;/api/speakers&lt;/code&gt; to the outside world.&lt;/p&gt;

&lt;p&gt;In the example below we focus on the output, and not the logic in the action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        [HttpGet("{speakerId}")]
        public IActionResult GetSpeakerFull([FromQuery] int speakerId)
        {
           return Ok(new SpeakerModel());
        }

        [HttpGet("{speakerId}")]
        public IActionResult GetSpeakerTrimmed([FromQuery] int speakerId)
        {
            return Ok(new SpeakerTrimmedDto());
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something like this would be possible without getting an error from the routing mechanism. We know we have a GET request, but which one of the two actions should be selected? We need to help the framework to distinguish between the two of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing media types(MIME types)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A media type (also known as a Multipurpose Internet Mail Extensions or MIME type) indicates the nature and format of a document, file, or assortment of bytes. MIME types are defined and standardized in IETF's [RFC 6838](https://datatracker.ietf.org/doc/html/rfc6838).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom media types
&lt;/h2&gt;

&lt;p&gt;A custom media type is a media type that we can create, often containg vnd as . This media type is significant to the specific business or domain.&lt;br&gt;&lt;br&gt;
You will often find vendor-specific media types used by different businesses as a mean to address specific customers trough the same api. There are hundreds of vendor-specific media types registered with IANA. Such example can be &lt;em&gt;application/vnd.mspowerpoint&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
GitHub uses them in their API, and a lot of other businesses.&lt;/p&gt;
&lt;h2&gt;
  
  
  Media type structure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7i_DdTzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2022/04/media-type.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7i_DdTzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2022/04/media-type.png" alt="" width="809" height="328"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Media type structure&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Responding to media types in controllers
&lt;/h2&gt;

&lt;p&gt;To respond to a specific media type in our action, all you have to do is annotate with the &lt;code&gt;[Consumes("")]&lt;/code&gt; attribute, passing the value of your media type.&lt;/p&gt;

&lt;p&gt;This attribute will allow us to have actions that return different representations of the same resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        [HttpGet("{speakerId}")]
      [Consumes("vnd.speaker.trimmed")]
        public IActionResult GetSpeakerTrimmed([FromQuery] int speakerId)
        {
            return Ok(new SpeakerTrimmedDto());
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will have to send Content-Type : vnd.speaker.trimmed when you make the request, to hit the action.&lt;/p&gt;

&lt;p&gt;In a similar manner you can use the &lt;code&gt;[Produces("")]&lt;/code&gt; attribute to help the routing mechanism when you want a specific format returned. This attribute will look after &lt;em&gt;Accept&lt;/em&gt; header value. Bear in mind that it will work out of the box only with the mime types supported by the framework. Otherwise you will need to create an &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-6.0"&gt;OutputFormatter&lt;/a&gt;, and register it.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;The approach with media types can be used for versioning too. You can read more about versioning your API &lt;a href="https://irina.codes/versioning-rest-apis/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can create your custom vendor-specific mime types, and include versions in them. From there you leave the routing mechanism to do its job.&lt;/p&gt;

&lt;p&gt;Use this wisely, because currently It will cause a swagger loading error. I’m still looking for a way around it. If you know how, drop a comment or a DM&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/custom-media-types-in-net/"&gt;Using custom media types in .NET&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rest</category>
      <category>web</category>
      <category>webapi</category>
      <category>custommediatypes</category>
    </item>
    <item>
      <title>The .NET Docs Show – Versioning REST APIs</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Tue, 11 May 2021 07:13:30 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/the-net-docs-show-versioning-rest-apis-256d</link>
      <guid>https://dev.to/irina_scurtu/the-net-docs-show-versioning-rest-apis-256d</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vDj-xWtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2021/05/Capture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vDj-xWtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2021/05/Capture.png" alt="The .NET Docs Show"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/the-net-docs-show-versioning-rest-apis/"&gt;The .NET Docs Show – Versioning REST APIs&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rest</category>
    </item>
    <item>
      <title>How to build REST-ful APIs</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Tue, 02 Mar 2021 12:25:57 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/how-to-build-rest-ful-apis-3k02</link>
      <guid>https://dev.to/irina_scurtu/how-to-build-rest-ful-apis-3k02</guid>
      <description>&lt;p&gt;Thank you Edwin van Wijk and Sander Molenkamp for inviting me.&lt;/p&gt;

&lt;p&gt;You can see more interesting videos on &lt;a href="https://www.youtube.com/channel/UCFz17EP7PE2ouhPuVmu__kA"&gt;DotNETFlix channel&lt;/a&gt; on different topics, or &lt;a href="https://irina.codes/category/rest/"&gt;read about REST&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/how-to-build-rest-ful-apis/"&gt;How to build REST-ful APIs&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rest</category>
      <category>webapi</category>
    </item>
    <item>
      <title>Naming your REST endpoints</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Thu, 19 Nov 2020 20:04:46 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/naming-your-rest-endpoints-2fc</link>
      <guid>https://dev.to/irina_scurtu/naming-your-rest-endpoints-2fc</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VL6ijR7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/11/Status-codes-for-REST-APIs-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VL6ijR7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/11/Status-codes-for-REST-APIs-1.png" alt="naming rest enpoints" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to name your REST endpoint? How does your endpoint look? Are there any guidelines or best practices? How to name your endpoints? Let’s&lt;/p&gt;

&lt;h3&gt;
  
  
  A short introduction
&lt;/h3&gt;

&lt;p&gt;We often use APIs to implement CRUD operations, or most APIs start like this, but all of them evolve over time.&lt;br&gt;&lt;br&gt;
CRUD is an acronym that stands for Create, Read, Update, Delete. And these are all the operations that you can apply to a specific resource.&lt;/p&gt;

&lt;p&gt;Let’s take childish example, and say you need to manage pets for a veterinary cabinet and you are interested in cats:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/api/getAllCats&lt;/code&gt;– wouldn’t &lt;code&gt;/api/cats&lt;/code&gt; be easier to remember?&lt;br&gt;&lt;br&gt;
&lt;code&gt;/api/newCat&lt;/code&gt; – how about &lt;code&gt;/api/cats&lt;/code&gt;and use POST as HTTP Verb?&lt;br&gt;&lt;br&gt;
&lt;code&gt;/api/getBlackCats&lt;/code&gt;– why should you have a different endpoint? &lt;code&gt;/api/cats?color=black&lt;/code&gt;will have the same path, but the parameter value will change an get you a lot of flexibility&lt;br&gt;&lt;br&gt;
&lt;code&gt;/api/getCatsOwners&lt;/code&gt;– how about &lt;code&gt;/api/cats/{id}/owners&lt;/code&gt;– this way you will know exactly to which cat you are reffering. The one with the {id} in the URL path.&lt;br&gt;&lt;br&gt;
&lt;code&gt;/api/getHungerLevel&lt;/code&gt;– hunger level of…? cat? which cat? maybe is youru hunger level?&lt;/p&gt;

&lt;p&gt;If you look at the endpoints, are very hard to remember, and once you add more operations, it will be even harder to remember and harder to manage. Plus, you have no reason to include get{something} in the endpoint or have tons of endpoints. The HTTP verb will be the one that tells what operation you are doing. Either is a GET, a POST or something else. KISS, as in code, also applies here. And more than that, we need to keep in mind that we need to leverage the underlying protocol as much as we can.&lt;/p&gt;

&lt;p&gt;In my opinion, an endpoint in a REST API should be self-explanatory. Just by looking at the URL, you( and the server) should be able to tell what is the resource it handles without needing a manunal.&lt;/p&gt;

&lt;p&gt;One ot the things REST is trying to do, is to remove the uglyness we all dealt with in SOAP. SOAP exposed a set of operations in a WSDL file, and to ‘call’ those operations we made a single type of call(POST or GET). REST is trying to get rid of that paradigm and get us closer to the underlying protocol.&lt;/p&gt;

&lt;p&gt;Luckily, if you are nostalgic(or not) we have tools like &lt;a href="https://swagger.io/"&gt;Swagger&lt;/a&gt;and the Open API standard to help us with the documentation, but even so, and URL should express intent in the ‘eyes’ of the consumer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;COOL URI’s don’t change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s look at the 2 endpoints that you will need in a REST API.&lt;/p&gt;

&lt;h3&gt;
  
  
  An endpoint for the collection
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/api/cats&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will allow you 2 operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retrieve the collection by HTTP GET (a read)&lt;/li&gt;
&lt;li&gt;Create a new resource by using HTTP POST (a create)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  An endpoint for a specific item
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/api/pets/{id}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will allow you 4 operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retrieve the item by using HTTP GET(a read)&lt;/li&gt;
&lt;li&gt;update an existing resource by using HTTP PUT(an update) or HTTP PATCH&lt;/li&gt;
&lt;li&gt;delete and existing resource by using HTTP DELETE(a delete)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Related/hierarchical resources
&lt;/h3&gt;

&lt;p&gt;Any hierarchical resource can be represented further in the URL path, but the convention remains, and applies down in the hierarchy.&lt;/p&gt;

&lt;p&gt;Let’s take the example of wanting to represent the owners of a specific cat:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/api/cats/{id}/owners&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Looking at this URL we realize that in the cats collection, we are interested in the specific {id} of the cats, and from this specific cat, we want the owners collection.&lt;/p&gt;

&lt;p&gt;When we obtain the list of owners, we might be interest to obtain a specific one, and we can take another step : &lt;code&gt;/api/cats/{id}/owners/{ownerid}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You are not forced to model your data and store it in the database according to the endpoints, or the other way a round. Remember, in REST, you work with representations of resources, and those representations are handled by you. At the server level, for more decoupling and simplicity, you should use DTOs to transform or aggregate data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Name your endpoints in such a way to have meaning for the business and your consumers&lt;/li&gt;
&lt;li&gt;You don’t need a different endpoint to represent a new operation. You can give meaning to your request by using the right HTTP verb&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use GET, POST to the same endpoint /api/cats : the end result will be different.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;you need two endpoints to represent major operations on a resource&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Variations of specific resources can be represented as parameters in the query string, not different endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, it is up to you how you shape your endpoints. There is no constraint in this. As long as it makes sense for the business, expresses the intent, and is specific enough.&lt;/p&gt;

&lt;p&gt;The meaning for each request/response should be added by using the right HTTP Verbs, headers and &lt;a href="https://irina.codes/status-codes-for-rest-apis/"&gt;status codes.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/naming-your-rest-endpoints/"&gt;Naming your REST endpoints&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rest</category>
      <category>web</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>.NET Core with NGINX on Linux</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Wed, 07 Oct 2020 09:49:23 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/net-core-with-nginx-on-linux-2i59</link>
      <guid>https://dev.to/irina_scurtu/net-core-with-nginx-on-linux-2i59</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F10%2FNET-Core-with-NGINX-on-Linux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F10%2FNET-Core-with-NGINX-on-Linux.png" alt=".NET Core with NGINX on Linux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having .NET Core with NGINX on Linux is easier that you might imagine. In this article I will talk about my experience related to NGINX and what it takes to configure it for the first time. If you come from an IIS/Windows world like me, where you know everything by heart, the declarative approach in NGINX might be a bit odd.&lt;/p&gt;

&lt;h3&gt;
  
  
  I already have Kestrel, why do I need something else?
&lt;/h3&gt;

&lt;p&gt;Kestrel is the default server implementation for ASP.NET Core, and it is super fast, cross-platform, customizable and it can run on its own. It looks like it is the perfect server, but it was lacking a lot of features related to security. Another thing about Kestrel is that “u&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1&amp;amp;WT.mc_id=DOP-MVP-5003404" rel="noopener noreferrer"&gt;sed as an edge server without a reverse proxy server doesn’t support sharing the same IP and port among multiple processes”.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although is not required, it is recommend to have a reverse proxy in front of Kestrel because it will give you an extra layer of configuration and defense and integrates smoothly with the existing infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is NGINX?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.nginx.com/resources/glossary/nginx/" rel="noopener noreferrer"&gt;NGINX&lt;/a&gt; is an open source software for web serving, load balancing, media streaming, that also has reverse proxy capabilities. One of the goals behind NGINX was to create the fastest web server out there. Now, is one of the most popular servers &lt;a href="https://w3techs.com/technologies/cross/web_server/ranking" rel="noopener noreferrer"&gt;out there.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing NGINX on Linux
&lt;/h3&gt;

&lt;p&gt;Depending on your Linux distribution the package manager might differ. I had Red Hat &lt;code&gt;sudo yum install nginx&lt;/code&gt; did the trick. After a successful installation you will find the files and folders for NGINX under &lt;code&gt;/etc/nginx&lt;/code&gt; path on the server looking pretty much like this( without the highlighted folders)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F10%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F10%2Fimage.png" alt="nginx structure"&gt;&lt;/a&gt;nginx structure&lt;/p&gt;

&lt;p&gt;One of the most important files out there is the nginx.conf file that will contain or reference other configurations for your web apps. Bear in mind that, in order to be able to start NGINX server this configuration will have to be valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring NGINX for all your apps
&lt;/h3&gt;

&lt;p&gt;Now, I’ve cleaned up a bit the default nginx.conf and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}

http {
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For easier formatting, I used Visual Studio Code with 2 extensions: &lt;a href="https://marketplace.visualstudio.com/items?itemName=william-voyek.vscode-nginx" rel="noopener noreferrer"&gt;Nginx configuration&lt;/a&gt; and &lt;a href="https://marketplace.visualstudio.com/items?itemName=raynigon.nginx-formatter" rel="noopener noreferrer"&gt;Nginx Formatter.&lt;/a&gt;&lt;br&gt;&lt;br&gt;
At line 28, I’ve added an include statement because I want to place all my configurations for different website in separate files, in sites_enabled folder.&lt;/p&gt;

&lt;p&gt;After that, I’ve created the sites_enabled folder, and the certs folder (that will contain certificates). In the sites_enabled folder, I’ve created a file named myapi.conf and inside it, I’ve added this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    server_name myserver;
    root /var/opt/myapps/ui;

    index index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ /index.html;
        proxy_read_timeout 300s;
        proxy_connect_timeout 75s;
    }

    location /api {
        proxy_pass http://localhost:4906;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
        proxy_connect_timeout 75s;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the configuration file I have 2 ‘location’ sections, one for an UI app, and one for the API. The two apps I want to be served from the same ‘domain’ but on a different path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the ui app from the root like /myapp&lt;/li&gt;
&lt;li&gt;the api from something deeper in the hierarchy like: /myapp/api&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once this is done, you can test the nginx configuration by running &lt;code&gt;nginx -t -c /etc/nginx/nginx.conf&lt;/code&gt;in the terminal. If that is successful, you can go ahead, start NGINX server&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful NGINX commands
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sudo nginx service start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nginx service restart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nginx service status&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In summary
&lt;/h3&gt;

&lt;p&gt;We looked at how to configure .NET Core with NGINX on Linux, but the same configs will work on Windows also. The only thing you need to do besides configure NGINX is to&lt;a href="https://irina.codes/net-api-as-a-linux-service/" rel="noopener noreferrer"&gt;run the API as a Linux Service&lt;/a&gt;, and to make sure is up.&lt;/p&gt;

&lt;p&gt;In a following post we will add https in front of our API, because we need to care about security. &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.0%2F72x72%2F1f642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.0%2F72x72%2F1f642.png" alt="🙂"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/net-core-with-nginx-on-linux/" rel="noopener noreferrer"&gt;.NET Core with NGINX on Linux&lt;/a&gt; appeared first on  &lt;a href="https://irina.codes" rel="noopener noreferrer"&gt;https://irina.codes&lt;/a&gt;, Irina Scurtu's blog&lt;/p&gt;

</description>
      <category>linux</category>
      <category>nginx</category>
      <category>net</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>.NET API as a Linux Service</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Tue, 06 Oct 2020 11:13:39 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/net-api-as-a-linux-service-27mm</link>
      <guid>https://dev.to/irina_scurtu/net-api-as-a-linux-service-27mm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iN4o5KNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/10/linux-service.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iN4o5KNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/10/linux-service.png" alt=".net api as linux service" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;.NET API as a Linux Service is just one of the many options when it comes to hosting.&lt;/p&gt;

&lt;p&gt;One thing I love about .NET Core is that it runs everywhere. Running .NET APIs as Linux services, allows different organizations to reduce some costs by maybe reusing infrastructure. Before .NET Core, .NET was almost synonymous with Windows. The only server for .NET was IIS.&lt;/p&gt;

&lt;p&gt;Now you have a ton of options when it comes to hosting your .NET applications.&lt;br&gt;&lt;br&gt;
You want to keep running it on Windows? You can host and install it as a Windows Service with &lt;a href="https://nssm.cc/"&gt;NSSM&lt;/a&gt;. Do you want Kestrel instead of IIS Express? No worries, you can do that. Nowadays, sky is the limit when it comes to hosting a .NET API.&lt;br&gt;&lt;br&gt;
One thing you will need to do is to install .NET on the server. You can read &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/install/linux?WT.mc_id=DOP-MVP-5003404"&gt;here&lt;/a&gt;how to install .NET on different Linux distributions. (If you never did this or you are not an experienced Linux user).&lt;/p&gt;
&lt;h3&gt;
  
  
  What you need
&lt;/h3&gt;

&lt;p&gt;– Putty or a way to connect to your Linux server&lt;br&gt;&lt;br&gt;
– sudo rights or execution rights on the server&lt;/p&gt;
&lt;h2&gt;
  
  
  Running an API as a Linux Service
&lt;/h2&gt;

&lt;p&gt;If you have your API in good standing, &lt;a href="https://irina.codes/versioning-rest-apis/"&gt;versioned,&lt;/a&gt;and with t&lt;a href="https://irina.codes/status-codes-for-rest-apis/"&gt;he right status codes&lt;/a&gt; and you chose Kestrel, the only thing you need to do is to create a .service file and to put it on your Linux server. In my case, the API was hosted on a RedHat distribution.&lt;br&gt;&lt;br&gt;
The service content will be a file with the .service extension (let’s call the file myapi.service), placed under &lt;code&gt;/etc/systemd/system&lt;/code&gt; path.&lt;/p&gt;

&lt;p&gt;The .service file will contain info related to what it will need to run and from where, and a few flags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Awesome API
[Service]
WorkingDirectory=/var/opt/myapps/myapi
ExecStart=/usr/bin/dotnet /var/opt/myapps/myapi/MyApi.dll
Restart=always
RestartSec=10
SyslogIdentifier=myapi
User=root
Environment=ASPNETCORE_ENVIRONMENT=Development
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming you have sudo rights, you will need to start the service by running &lt;code&gt;systemctl start myapi.service&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful linux commands
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;systemctl stop myapi.service&lt;/code&gt; stops your service&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemctl start myapi.service&lt;/code&gt; starts your service&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemctl status myapi.service&lt;/code&gt; returns the status of your service. Is useful when you want to make sure the service is running or for debugging purposes. The response will contain some aditional info, depending on what you have configure, but it will look pretty much like this: &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qlSwF1pU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/10/thumbnail_image001.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlSwF1pU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/10/thumbnail_image001.png" alt="status response" width="608" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have your NET API as a Linux Service up and running, you might need to make it run on HTTPS.&lt;br&gt;&lt;br&gt;
You’ll see in another article how you can configure NGINX Reverse proxy to have Https.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/net-api-as-a-linux-service/"&gt;.NET API as a Linux Service&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>netcore</category>
      <category>linux</category>
      <category>net</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Status Codes for REST APIs</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Thu, 16 Jul 2020 07:34:19 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/status-codes-for-rest-apis-m4h</link>
      <guid>https://dev.to/irina_scurtu/status-codes-for-rest-apis-m4h</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9yHnX8dn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/07/Status-codes-for-REST-APIs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9yHnX8dn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/07/Status-codes-for-REST-APIs.png" alt="" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to Status Codes for REST APIs, we are all in a hurry to deliver functionality and we often ignore them. Come as it may. We use what we get. And that’s it.&lt;/p&gt;

&lt;p&gt;REST as a concept should also be about meaning, longevity and empathy towards our API consumers. We should be able to look at a request/response in isolation and understand what is wrong or what happened.&lt;/p&gt;

&lt;p&gt;Choosing Status Codes for REST APIs sometimes is not easy, but at least we should give this a thought.&lt;/p&gt;

&lt;p&gt;In this article, I will talk about Status Codes for REST APIs: the most common and the ignored ones, and a few usage scenarios.&lt;/p&gt;

&lt;p&gt;We all know that we have 5 categories when it comes to status codes. And depending on the response category we should be able to tell what happened with that request. Was the request bad? There is an error processing it?&lt;/p&gt;

&lt;h4&gt;
  
  
  Status Codes – Categories
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;1xx – Informational&lt;/li&gt;
&lt;li&gt;2xx – Success&lt;/li&gt;
&lt;li&gt;3xx – Redirect&lt;/li&gt;
&lt;li&gt;4xx – Client Error&lt;/li&gt;
&lt;li&gt;5xx – Server error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve seen APIs where the status code was 200 OK, but the response body looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rQt76pnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/07/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rQt76pnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/07/image.png" alt="" width="812" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, me or my app, as an API consumer…what should I understand? Was my request successfully processed, or…. am I unauthorized? #confusing. So don’t do this in your APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  2xx – Sucess status codes
&lt;/h2&gt;

&lt;p&gt;These are success status codes because they start with 2, but in particular, that code should express exactly what happened. You shouldn’t return 200 OK for all the scenarios and then write an error in the body. (if you want to add meaning and have a well-rounded API.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;200 OK&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When the response what processed with success, and usually has a response body.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;201 Created&lt;/strong&gt; – As a response for a POST request that has the effect of creating a new resource. This should be accompanied by a Location header indicating the location for the newly created resource  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;202 Accepted&lt;/strong&gt; – For scenarios where there is no need for a response body. e.g for queuing something for later processing.&lt;br&gt;&lt;br&gt;
Also, this works very fine with the Location header, for polling scenarios, where you call the endpoint from time to time to see the status of a resource processing&lt;br&gt;&lt;br&gt;
&lt;strong&gt;204 No Content&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4xx – Client errors
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;400 – Bad Request&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Bad Request is in my opinion, one of the most miss-used status codes. I’ve seen it returned when due to some business logic the request couldn’t be processed, but the request was well formed.&lt;br&gt;&lt;br&gt;
Think about it – when the request is well-formed, it has the parameters, the body and everything all good, but is a business rule on the backend that prevents that request from being processed….is not a Bad Request. Is anything but a Bad Request.&lt;br&gt;&lt;br&gt;
When you see a Bad Request, the tendency is to look at the content of the request to see what is wrong, fix that, and issue the request again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dummy Scenario&lt;/strong&gt; : Online Store. You can’t create 2 products with the same name and brand.   &lt;/p&gt;

&lt;p&gt;Status Code: 409 – Conflict not Bad Request. Here you are basically informing your consumer that there is a rule somewhere that prevents you to add that resource; hence, a 409 – Conflict&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;401 – Unauthorized&lt;/strong&gt; , &lt;strong&gt;403 – Forbidden&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;404 – Not Found&lt;/strong&gt; – resource is not there, or maybe it was deleted.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;406 – Not acceptable&lt;/strong&gt; – when the server can’t return a response that matches the Accept header of the request. To force .NET to take the Accept header into consideration you will need to set a flag to true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; services.AddControllers(setupAction =&amp;gt;
 {
    setupAction.ReturnHttpNotAcceptable = true;
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;409 – Conflict&lt;/strong&gt; – When there is a business rule that prevents you from creating that resource as a result of a POST. Another scenario can be with using PUT to update a specific resource, and due to its state, you can’t.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;410 – Gone&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;415 – Unsupported Media-Type&lt;/strong&gt; ; When the server can’t understand the body of the request, due to a wrong Content-Type header, or limited capabilities on the server.&lt;br&gt;&lt;br&gt;
For example, if you try to send an XML in the request but the server doesn’t know how to read XML, you should get this status code.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;422 – Unprocessable Entity –&lt;/strong&gt; the server understands the request, the request is well-formed but due to some rules, it can’t be processed. It can be used instead of 409 – Conflict and also covers a lot of ground. You can configure this in&lt;code&gt;Startup.cs&lt;/code&gt; by leveraging &lt;code&gt;ApiBehaviourOptions&lt;/code&gt;like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           services.AddControllers()
                .ConfigureApiBehaviorOptions(setupAction =&amp;gt;
            {
                setupAction.InvalidModelStateResponseFactory = context =&amp;gt;
                {
                    var problemDetails = new ValidationProblemDetails(context.ModelState)
                    {
                        Type = "https://yourApi.com/modelvalidationproblem",
                        Title = "One or more model validation errors occurred.",
                        Status = StatusCodes.Status422UnprocessableEntity,
                        Detail = "See the errors property for details.",
                        Instance = context.HttpContext.Request.Path
                    };

                    problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);

                    return new UnprocessableEntityObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json" }
                    };
                };
            });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can hook yourself to the ModelState and treat validation errors as 422 status codes instead of Bad requests if you need that. You can find more examples &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-3.1"&gt;in the docs&lt;/a&gt;. As a result, ASP.NET higher than 2.1 generates&lt;a href="https://tools.ietf.org/html/rfc7807"&gt;RFC-7807 compliant responses&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a side note, if you configure ApiBehaviour to return BadRequest for model validation, you won’t need to scatter all over your controllers these lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (ModelState.IsValid) 
 {
     return BadRequest(ModelState);
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Even though the most common status codes that might fit a lot of scenarios, we should bear in mind that there are around &lt;strong&gt;63 of them!!&lt;/strong&gt; Why? For us to use!&lt;br&gt;&lt;br&gt;
If we don’t use “one size fits all” in terms of the technology we choose, why do we apply this on status codes?&lt;br&gt;&lt;br&gt;
If don’t think &lt;a href="https://irina.codes/versioning-rest-apis/"&gt;about versioning&lt;/a&gt;, or headers, or HATEOAS in our APIs, at least we should have the right status codes.(and verbs, and naming &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2EAkP1Kt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2EAkP1Kt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" alt="🙂" width="72" height="72"&gt;&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/status-codes-for-rest-apis/"&gt;Status Codes for REST APIs&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rest</category>
      <category>webapi</category>
    </item>
    <item>
      <title>Extending EF Core DbContext</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Fri, 29 May 2020 14:44:30 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/extending-ef-core-dbcontext-3h1a</link>
      <guid>https://dev.to/irina_scurtu/extending-ef-core-dbcontext-3h1a</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F05%2Fextending-dbcontext.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F05%2Fextending-dbcontext.png" alt="extendin ef core DbContext"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entity Framework allows you to extend the DbContext class to add your own entities, extend existing entities, and customize them at runtime. All of these in a clean and simple manner, if you are willing to do so. It doesn’t even matter if those entities don’t have a table representation. You can do that by leveraging C# partial classes and methods. Extending EF Core DbContext is a common scenario, but I think we’re often not aware of its real power.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F05%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Firina.codes%2Fwp-content%2Fuploads%2F2020%2F05%2Fimage-1.png"&gt;&lt;/a&gt;The way I like to organize entities in my projects&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing OnModelCreatingPartial
&lt;/h2&gt;

&lt;p&gt;Commonly your application context will be similar to this: a lot of DbSet that map to the database table object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public partial class ConferenceContext : DbContext
    {
        public ConferenceContext(DbContextOptions&amp;lt;ConferenceContext&amp;gt; options)
            : base(options)
        {
            this.Database.EnsureCreated();

        }

        public DbSet&amp;lt;Speaker&amp;gt; Speakers { get; set; }
        public DbSet&amp;lt;Talk&amp;gt; Talks { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might notice the OnModelCreatingPartial method in the example above. I’ve noticed this recently after using a database-first approach in a small project. To be honest, it was really an “Aha!” moment, because if you look into DbContext class source, you will not find a reference to it.&lt;/p&gt;

&lt;p&gt;This method gives you a simple and clean way to hook into &lt;code&gt;OnModelCreating&lt;/code&gt; method to add customization for the extra-entities you might need.&lt;br&gt;&lt;br&gt;
If you are like me you keep an eye on performance or data transfer from the database into the project, you will use raw SQL queries. As a result, you will end up with many classes used only for specific scenarios.&lt;/p&gt;

&lt;p&gt;Before EF Core 3.0 there was another datatype DbQuery that allowed you to specify that the entity T is used only for querying and not for inserts or other operations. &lt;a href="https://irina.codes/how-to-generate-idempotent-scripts-from-ef-core-migrations/" rel="noopener noreferrer"&gt;Migrations and idempotent scripts&lt;/a&gt;generated are done in the same way, but above EF Core 3.0, everything is a DBSet.&lt;/p&gt;

&lt;p&gt;It is up to you to tell EF Core that T has no key, like in the example below. You can read more about keyless entity types and the future of this in the &lt;a href="https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types?tabs=data-annotations" rel="noopener noreferrer"&gt;Microsoft docs.&lt;/a&gt; As you see. extending EF Core DbContext is easy and you can use the approach you are comfortable with either with FluentApi or annotations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public partial class ConferenceContext
    {
        public DbSet&amp;lt;TicketSummary&amp;gt; TicketSummaries { get; set; }

        public void OnModelCreatingPartial(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity&amp;lt;TicketSummary&amp;gt;().HasNoKey();

        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, TicketSummary class is used to retrieve results from a raw SQL query. In that query, I make a join and cherry-pick a few columns. That is it. I have no such table called TicketSummary in my database. Instead, I used &lt;a href="https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types?tabs=fluent-api" rel="noopener noreferrer"&gt;FluentApi&lt;/a&gt;to specify that there is no key for the entity.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/extending-ef-core-dbcontext/" rel="noopener noreferrer"&gt;Extending EF Core DbContext&lt;/a&gt; appeared first on &lt;a href="https://irina.codes" rel="noopener noreferrer"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>netcore</category>
      <category>efcore</category>
    </item>
    <item>
      <title>Versioning REST APIs</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Fri, 24 Apr 2020 16:13:06 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/versioning-rest-apis-4d30</link>
      <guid>https://dev.to/irina_scurtu/versioning-rest-apis-4d30</guid>
      <description>&lt;h2&gt;Headers or URL?&lt;/h2&gt;

&lt;p&gt;In the context of REST APIs there is a lot of confusion around versioning. Some people recommend versioning REST APIs by adding the version in the URL. Others don’t version at all, and others recommend versioning REST APIs using headers.&lt;br&gt;Nothing bad so far, but I’ve personally seen a lot of different APIs, that serve different domains and purposes that have a v1 in the URL. Not that is very bad, but the same APIs reach their end of life, with the same v1 in the URL. It’s hard to believe that was no change there since their inception. If so, why add a version in the first place?&lt;/p&gt;

&lt;p&gt;I think that these APIs end up with having the v1 forever because the consumer apps are also controlled by the same organization or teams.&lt;/p&gt;

&lt;p&gt;This way, the teams just go and change the consumer apps to accommodate the API changes, and that is it. They don’t have to worry about breaking something, somewhere, because they know and have full ownership over those changes.&lt;/p&gt;

&lt;p&gt;But what if you would have and API exposed for consumers and you have no control over the consumer code? Would this change something in terms of having v1 forever embedded in your endpoints? For sure it would! You would be forced somehow not to break your consumers, or constrained by some SLAs or legal stuff to ensure backwards compatibility, and to be very transparent about your API changes.&lt;/p&gt;

&lt;p&gt;More than than, you will need to ensure that nobody gets hurt by calling your API, and you don’t end up answering to support calls from them. This will make you think about designing your API changes carefully.&lt;br&gt;Now, let’s see how we can version.&lt;/p&gt;

&lt;h3&gt;The usual approach to versioning( URL versioning)&lt;/h3&gt;

&lt;p&gt;The most common approach to versioning is through URLs. You have our endpoints in a form that includes a version like: &lt;code&gt;&lt;a href="https://myapp.com/api/v1/resources"&gt;https://myapp.com/api/v1/speakers&lt;/a&gt;.&lt;/code&gt;&lt;br&gt;In order to call anything from there, you need to add v1 and you are done.&lt;br&gt;If you are talking .NET and WEB API, is very easy to do that for every endpoint just by decorating the Controller with that version, and you are all set.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Route("api/v1/speakers")]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The inventor of REST - Roy Fielding said in a tweet that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9jYlujaQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://irina.codes/wp-content/uploads/2020/04/v1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9jYlujaQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://irina.codes/wp-content/uploads/2020/04/v1.png" alt="Roy Fielding about v1" width="767" height="265"&gt;&lt;/a&gt;REST should imply evolvability&lt;/p&gt;

&lt;p&gt;If you correlate this with what Tim Berners-Lee said then you might have no reason to version in URL. Not in the path anyways.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.w3.org/Provider/Style/URI.html" rel="noreferrer noopener"&gt;COOL URIs don’t change&lt;/a&gt;&lt;/p&gt;
&lt;cite&gt;Tim Berners-Lee, 1998&lt;/cite&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Why not change the URLS?&lt;/h3&gt;

&lt;p&gt;Think about it. Sometimes you navigate to websites and you know the URL by heart. URLs matters for SEO, need to be discoverable, express intent and describe the content.&lt;br&gt;If you suddenly decide to reorganize a website, and you go around and change everything in terms of URLs there a big chance to lose users. Their bookmarks won’t work anymore, and they won’t be able to find the content they are interested in. That’s when people usually give up and move on and forget about you.&lt;/p&gt;

&lt;p&gt;If you decide(hopefully) to increase the version, you might break all your clients. And remember, you can’t force your clients to move to the new version when you want.&lt;br&gt;Surely you can’t say: &lt;strong&gt;“From now on, all my consumers will use v2”&lt;/strong&gt;. It is physically impossible, since you don’t have control over them, and each of them has different priorities.&lt;/p&gt;

&lt;p&gt;Suddenly, taking everyone on board for the new version becomes a long process. You need to ensure backwards compatibility for who knows how long (read it as forever) and documentation.&lt;/p&gt;

&lt;p&gt;More than that, let’s take another scenario. Microservices and data transfer in Microservices with HttpClients. You usually have somewhere the URLs hardcoded, in a JSON or something or even inside libs with that are distributed through some package manager. If you change the URLs, to change the version to v2, you will need to find all those places in your code where you have it ‘hardcoded’. PS: you know you forget all the places.&lt;br&gt;Versioning your REST API in URL, to me is not the best idea.&lt;/p&gt;

&lt;h3&gt;Versioning trough headers&lt;/h3&gt;

&lt;p&gt;Now I know is not the most common way to do versioning but is my personal preference. Why? &lt;strong&gt;“Because cool URIs don’t change”&lt;/strong&gt;.&lt;br&gt;Adding meaning and some kind of specificity to a request can be done in different ways, why do it through the URL itself. The URL should be self-describing, don’t pollute that with versioning-related pieces.&lt;/p&gt;

&lt;p&gt;In my opinion, as long as that endpoint is very clear in terms of naming – is specific enough, gives a clear understanding of what is the resource it is supposed to handle you are all set.&lt;/p&gt;

&lt;p&gt;You can add meaning to your requests very easily. You can add proper verbs, custom headers, to hydrate the request, to specify intent. Remember that a request should be understood in isolation, and HTTP is stateless.&lt;br&gt;This way you help a bit with content negotiation.&lt;br&gt;You add &lt;em&gt;Accept &lt;/em&gt;header property to help the server understand what the client needs and expects, &lt;em&gt;Content-Type&lt;/em&gt; to describe the request body, and so on.&lt;/p&gt;

&lt;p&gt;In the same manner, you can add a custom header property that specifies what is the version that the client wants to call.  &lt;/p&gt;

&lt;h3&gt;Using a library&lt;/h3&gt;

&lt;p&gt;Luckily there is an awesome library in .NET called &lt;code&gt;Microsoft.AspNetCore.Mvc.Versioning&lt;/code&gt; that will speed up a lot of manual work. It will give you a lot of flexibility and config options, and your code won't be a mess.&lt;/p&gt;

&lt;p&gt;You will need to configure it in Startup.cs with the behavior you want.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;services.AddApiVersioning(o =&amp;gt; o.ApiVersionReader =
               new HeaderApiVersionReader("api-version"));&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br&gt;Then, you can go ahead and decorate the controllers with the right API version attribute.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Route("api/speakers")]
    [ApiController]
    [ApiVersion("1.0")]
    public class SpeakersController : ControllerBase
    {
        //code removed for brevity
    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using simple attributes, you are now allowed to have 2 controllers side by side, that have the same route. One of them has the previous version, and the second the new version. Using the same URL and without any changes will respond correctly to requests, as long as the correct header is specified in the request.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    [Route("api/speakers")]
    [ApiController]
    [ApiVersion("2.0")]
    public class Speakers2Controller : ControllerBase
    {
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you issue a request to the API, you will need to have&lt;strong&gt; api-version&lt;/strong&gt; header with the correct value specified. &lt;code&gt;api-version:1.0 or api-version : 2.0 &lt;/code&gt; Based on that, the request will hit a controller on another.&lt;br&gt;You are not limited to only this kind of configuration.&lt;br&gt;You can assume a default version if this header is not there, or you can enforce a query parameter for the version, configure default behavior and error pages, and so on.&lt;br&gt; Everything is configurable inside Startup.cs&lt;/p&gt;

&lt;h3&gt;When to increase the version?&lt;/h3&gt;

&lt;p&gt;There is no clear answer to this. It depends on the number of changes and their magnitude. Be pragmatic about it, and don't take it to the extreme. &lt;strong&gt;An API version number is not the build number&lt;/strong&gt;. Don't do that.&lt;br&gt;How often do you increase the version number is a matter of API design first. Ask yourself a few questions:&lt;/p&gt;

&lt;p&gt;How many consumers you have? In what way are these clients affected by your changes? What is the development speed for your consumers? Are there legal/contract matters? (Maybe they don't have the same agility as you have) &lt;br&gt;Is it easy for you to maintain multiple versions of the same API?&lt;/p&gt;

&lt;p&gt;In conclusion&lt;/p&gt;

&lt;p&gt;Versioning REST APIs is not that hard, and REST itself is not bad. There is a certain amount of discipline to do this. You need to design the API with your consumers/clients in mind and take responsibility when you introduce changes.&lt;/p&gt;

&lt;p&gt;If you find this intriguing, ping me on twitter. Let's chat!&lt;/p&gt;

</description>
      <category>rest</category>
      <category>versioning</category>
      <category>api</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>View Razor changes without building the project</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Sun, 05 Apr 2020 12:54:21 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/view-razor-changes-without-building-the-project-40eo</link>
      <guid>https://dev.to/irina_scurtu/view-razor-changes-without-building-the-project-40eo</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8b9zn1rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/04/views.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8b9zn1rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/04/views.png" alt="How to view changes in ASP MVC Views without building the project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to view Razor changes without building the project. There is no need to build the project to see changes in Views.&lt;/p&gt;

&lt;p&gt;When I was a junior developer I remember my team lead telling me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No, you don’t need to rebuild the solution if you modify something views&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve absorbed this phrase and kept telling it to my students. Until recently to realize that is not of actuality anymore. For many years after that, I stopped working in ASP MVC projects, having only APIS, angular, and React client apps.&lt;/p&gt;

&lt;p&gt;Recently I’ve upgraded an MVC project&lt;a href="https://dev.to/irina_scurtu/from-net-2-2-to-3-1-routing-issues-4lne"&gt;from 2.2 to 3.1&lt;/a&gt; and needed to make some changes in Views.&lt;/p&gt;

&lt;p&gt;Nothing bad so far, I still remembered how it’s done. Yey! It is like riding a bike.&lt;br&gt;&lt;br&gt;
Oddly enough, I had to rebuild the solution to see the changes made in Views and I was really annoyed, I had just static HTML and couldn’t understand why I have to rebuild. Up until this moment, compilation of views was triggered by the editing. I started to dig around and did some research, and here’s what I’ve found out.&lt;/p&gt;
&lt;h2&gt;
  
  
  Razor compilation is enabled by default only for build/publish
&lt;/h2&gt;

&lt;p&gt;Razor compilation is enabled by default only for the build and publish scenarios, not for runtime aka when you edit the view.&lt;/p&gt;

&lt;p&gt;Now, if you want that functionality back, you need to install a NuGet package: &lt;code&gt;Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation&lt;/code&gt; and add the middleware and boom, it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddControllersWithViews()
        .AddRazorRuntimeCompilation();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conditional runtime compilation
&lt;/h2&gt;

&lt;p&gt;Another method to obtain the same thing, which I really don’t like is based on directives. This way, you can keep the default mode, but enable what you need only when you are debugging (running locally).&lt;/p&gt;

&lt;p&gt;First, you need to start by editing your csproj file to add a condition on the package.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;Version="3.1.3" Condition="'$(Configuration)' == 'Debug'" /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that, you need to make some adjustments in your startup file to add the condition. Start by adding a property to hold IWebHostEnvironment, and set the value from the controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            HostEnvironment = env;
        }

        public IConfiguration Configuration { get; set; }

        public IWebHostEnvironment HostEnvironment { get; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After you did that you need to add the #if condition to enable the ‘dynamic’ loading for the conditional runtime compilation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            var builder = services.AddControllersWithViews();
#if DEBUG
            if (HostEnvironment.IsDevelopment())
            {
                builder.AddRazorRuntimeCompilation();
            }
#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this in mind, make sure you change the IWebHostEnviroment scattered around your Startup class, and point it to the newly introduced property. Is not the cleanest solution, I do not prefer this, but it does the job. More than that, we all lie to ourselves that, ok, I’m gonna change the default, and just comment the line of code before deploying. Only this will never happen.&lt;/p&gt;

&lt;p&gt;In the official docs, they say that by using the conditional compilation you make sure that the published output uses the compiled views, are smaller in size, and it doesn’t enable file watchers in production. All these might be true, but it doesn’t make my developer experience nicer. What do you think?&lt;/p&gt;

&lt;blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/view-razor-changes-without-building-the-project/"&gt;View Razor changes without building the project&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>netcore</category>
      <category>aspcore</category>
      <category>web</category>
      <category>runtimecompilation</category>
    </item>
    <item>
      <title>From .NET 2.2 to 3.1 – Routing issues</title>
      <dc:creator>Irina Scurtu</dc:creator>
      <pubDate>Mon, 30 Mar 2020 18:10:32 +0000</pubDate>
      <link>https://dev.to/irina_scurtu/from-net-2-2-to-3-1-routing-issues-4lne</link>
      <guid>https://dev.to/irina_scurtu/from-net-2-2-to-3-1-routing-issues-4lne</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jeiSbbFB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/03/routing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jeiSbbFB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://irina.codes/wp-content/uploads/2020/03/routing.png" alt="From 2.2 to 3.1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having a website on 2.2, I thought that there is about the case to upgrade. Now or never I said. How hard can it be?&lt;/p&gt;

&lt;p&gt;I went pretty smooth, by using the -&amp;gt; migration guide..until…. I’ve bumped into routing. I’ve spent a decent amount of time trying to debug the issue, without visible progress.&lt;/p&gt;

&lt;p&gt;My issue was that my website had a public side and an Admin area where all the administration magic happens after login.&lt;/p&gt;

&lt;p&gt;Changing from &lt;code&gt;app.AddMvc()&lt;/code&gt; to &lt;code&gt;app.UseEndpoints()&lt;/code&gt; is pretty easy just by changing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseMvc(routes =&amp;gt;     {          routes.MapRoute(             name: "areaRoute year",             template: "{area:exists}/{controller}/{action}/{id?}",             defaults: new { controller = "Home", action = "Index" }             );}});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseEndpoints(endpoints =&amp;gt;{    endpoints.MapControllerRoute(        name: "areaRoute year",        pattern: "{area:exists}/{controller}/{action}/{id?}",        defaults: new {controller = "Home", action = "Index"}    );});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So the real changes in here are the template parameter name to &lt;em&gt;pattern&lt;/em&gt;, and &lt;code&gt;MapRoute&lt;/code&gt;to &lt;code&gt;MapControllerRoute&lt;/code&gt; and the rest is pretty much the same.&lt;/p&gt;

&lt;p&gt;So far so good, but my routes on the Admin area simply didn’t work anymore. Everything on the admin was not accessible, and I got 404 in the browser. This led me to believe that my routes had an issue around authorization. I tried again and failed again, and I gave up.&lt;/p&gt;

&lt;p&gt;Fortunately, we still have the option to ignore for now the UseEndpoints and fallback to the old version by setting a single property to false in ConfigureServices.&lt;br&gt;&lt;br&gt;
&lt;code&gt;services.AddMvc(options =&amp;gt; options.EnableEndpointRouting = false);&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Now, by setting this you can use the old approach without any issues, just make sure you don’t add the app.UseRouting() by any means.&lt;/p&gt;
&lt;h2&gt;
  
  
  Take 2 – try again
&lt;/h2&gt;

&lt;p&gt;Renamed everything as it should be and looked a bit at the order of Midleware imports.&lt;/p&gt;

&lt;p&gt;I can say that 3.1 middleware order matters even more than before. You must have&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; app.UseRouting();
 //anything in between
 app.UseAuthentication();
 app.UseAuthorization();
 app.UseEndpoints(endpoints =&amp;gt;...);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;My actual issue was that &lt;code&gt;app.UseAuthentication()&lt;/code&gt; and &lt;code&gt;app.UseAuthorization()&lt;/code&gt; order was reversed. I can’t tell you why it worked in 2.2, but for sure doesn’t work anymore in 3.1.&lt;/p&gt;

&lt;p&gt;After this fix, I was able to have a fully working app migrated to 3.1, and now I use endpoints not routes.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;&lt;br&gt;
We knew that order of the middlewares matters, but in this case there is a slight difference. Make sure you have .UseRouting(), any other middleware you need and then UseAuthentication, UseAuthorization, UseEndpoints&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://irina.codes/from-net-2-2-to-3-1-routing-issues/"&gt;From .NET 2.2 to 3.1 – Routing issues&lt;/a&gt; appeared first on &lt;a href="https://irina.codes"&gt;Irina Scurtu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>netcore</category>
      <category>aspcore</category>
    </item>
  </channel>
</rss>
